关于原型链,原语和对象的混淆

时间:2013-03-29 14:26:06

标签: javascript prototype primitive

在firebug控制台中

>>> a=12 
12
>>> a.__proto__
Number {}
>>> (12).__proto__
Number {}
>>> a.constructor.prototype === (12).__proto__
true
>>> a.constructor.prototype.isPrototypeOf(a)
false

与其他线路相比,最后一行让我感到很困惑。另见Constructor.prototype not in the prototype chain?

3 个答案:

答案 0 :(得分:2)

当您使用带有基元的.运算符时,该语言会使用相应的对象类型(在本例中为Number)自动将其括起来。那是因为JavaScript中的简单原始类型实际上不是对象实例。

因此,

的实际左侧
a.__proto__

不是数字12,而是new Number(12)。但是,变量“a”仍然是简单的数字值12

编辑 - Section 8.7 of the spec使用典型的ECMA 262月球语言“解释”这一点。我找不到一个清晰的段落来描述原始 baseValue 被视为Number,Boolean或String实例的方式,但该部分直接暗示它。我认为,因为那些非原始的合成值是短暂的(它们只是“真实的”,而.[]表达式正在被评估),规范只讨论行为而没有明确要求构造一个实际的数字。我猜这个。

答案 1 :(得分:1)

@Pointy解释得非常好。基本上,如果你想要你的最后一个陈述是真的,你必须写成:

a.constructor.prototype.isPrototypeOf(new Number(a));

答案 2 :(得分:0)

在JavaScript原语中没有原型链。只有对象。原始值包括:

  1. 布尔
  2. 数字
  3. 字符串
  4. 未定义
  5. 因此,如果您使用原始值调用isPrototypeOf,那么它将始终返回false

    如果您尝试使用布尔值,数字或字符串作为对象,则JavaScript会自动将其强制转换为对象。因此a.constructor在幕后评估为new Number(a).constructor。这就是您可以将原始值用作对象的原因。

    如果您希望使用将原始值存储为对象的变量,那么最好明确地将其作为对象。例如,在您的情况下,最好将a定义为new Number(12)。优点是:

    1. 每次尝试将对象用作对象时,JavaScript都不需要将对象强制转换为对象。您只需创建一次对象。因此它的性能效率很高。
    2. 您的案例中的isPrototypeOf方法将返回true,因为a将是Number的实例。因此,它的原型链中会有Number.prototype