字符串字面值是对象吗?

4

我正在努力加强我的JavaScript基础知识。所以问题是关于字符串字面量。它们不是对象吗?如果你的答案是“是”,那么我的问题是为什么instanceof返回false

> var s = new String
> s.constructor.toString()
function String() { [native code] }

> typeof s
object

> s instanceof String
true

> s instanceof Object
true

> s instanceof Number
false

迄今为止还不错。
> typeof 'c'
string

> 'c' instanceof Object
false

> 'c' instanceof String
false

> 'c'.length
1

> 'c'.charAt(0)
c

> 'c'.constructor.toString()
function String() { [native code] }

3
我认为这个问题是https://dev59.com/TXVC5IYBdhLWcg3wtzoQ的重复,但是那个重复的答案是完全错误的(在那里接受的答案的评论中概述)。 - Crescent Fresh
@Cresent Fresh - 你说得完全正确!3 .toString() 或 3..toString() 都可以用(顺便问一下,那两个点是怎么回事?) - Murali
当我尝试使用3个点时,它会出现奇怪的错误!3...toString() TypeError在第1行:XML后代内部方法在不兼容的数字上调用 - Murali
2
@wizard@,第一个问题:数字字面量的DecimalLiteral部分中的DecimalDigits是可选的(http://bclary.com/2004/11/07/#a-7.8.3),因此数字字面量以第一个点结束,第二个点是属性访问器。关于错误:现在你知道`3.`是一个完整的数字字面量,那么另外两个点就是ECMAScript用于XML(也称为E4X)的`..`运算符。http://en.wikipedia.org/wiki/E4X - Christian C. Salvadó
2个回答

5

字符串字面量是基本类型(字符串值),字符串对象可以使用String构造函数new表达式中创建:

"foo" instanceof String // false

new String("foo") instanceof String // true
编辑:看起来有些令人困惑(通过查看这里的被接受答案),即使是在原始值的原型对象上定义属性,你仍然可以访问它们。例如:
"foo".indexOf == String.prototype.indexOf // true
"foo".match == String.prototype.match // true
String.prototype.test = true;
"foo".test // true
true.toString == Boolean.prototype.toString
(3).toFixed == Number.prototype.toFixed // true
// etc...

那是由于属性访问器、点符号.和方括号符号[]的原因。
让我们看一下ECMA-262规范中的算法:
MemberExpression : MemberExpression [ Expression ](或MemberExpression . Identifier)的生成如下所示:
1. 计算MemberExpression。 2. 调用GetValue(Result(1))。 3. 计算表达式。 4. 调用GetValue(Result(3))。 5. 调用ToObject(Result(2))。 6. 调用ToString(Result(4))。 7. 返回类型为Reference的值,其基对象为Result(5),属性名称为Result(6)
步骤5中,ToObject内部操作符根据其类型将MemberExpression转换为对象。
原始值被转换为对象而不会引起注意,这就是为什么可以访问在原型上定义的属性。

0

这里有一个很好的解释在这里。以下是为了参考而复制的。


那是因为那些东西是原始数据类型,除非需要将它们作为对象使用(例如在调用方法时),否则它们仍然是原始数据类型。它们“变成”对象的唯一时间是需要进行包装时。如果您熟悉.NET中的“装箱”概念,则可以用类似的方式来理解。
这是一个例子-看看这段代码:
Number.prototype.times = function(func) {
   for(var index = 1; index <= this; index++) {
      func(index);
   }
};

因此,以下代码将失败:
3.times(print); // assume 'print' writes to standard out

3本身是一个原始值。也就是说,以下代码可以正常工作:

(3).times(print); // assume 'print' writes to standard out

这将显示数字1、2和3。由于括号的存在,JavaScript解释器将暂时将原始值3包装在Number对象中,调用该方法,然后垃圾回收该对象,因为它不再需要。

无论如何,关于这个问题的完整讨论可以在"JavaScript权威指南"中找到。


找到了。3.13. 基本数据类型包装器对象。再次感谢。 - Murali
4
不,3.times 会失败,因为它是一个语法错误:解析器允许 3. 作为小数点。括号只是消除了模棱两可的部分,与 "boxing" 无关。试试这个:3 .times 可以工作,以及 3..times3. .times 也可以。 - Crescent Fresh
@Crescent,我编辑了我的答案,使其更加清晰,关于为什么您可以从Number原始类型访问Number.prototype属性,就像这个例子一样。 - Christian C. Salvadó

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接