Why are JavaScript primitives not instanceof Object?
今天我碰巧有太多时间要杀死,我在Node(v0.10.13)命令行上玩了一点:
1 2 3 4 5 6 7 8 | > 1 instanceof Object false > (1).__proto__ {} > (1).__proto__ instanceof Object true > (1).__proto__.__proto__ === Object.prototype true |
现在,根据MDN,
The instanceof operator tests whether an object has in its prototype
chain the prototype property of a constructor.
但是很明显,
好的,我接受了,并且进行了更多测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | > (1).__proto__ === (2).__proto__ true > 'a'.__proto__ === 'b'.__proto__ true > (1).__proto__ === 'a'.__proto__ false > (1).__proto__.__proto__ === 'a'.__proto__.__proto__ true > (1).__proto__.type = 'number' 'number' > 'a'.__proto__.type = 'string' 'string' > (2).type 'number' > (1.5).type 'number' > 'b'.type 'string' |
因此,显然所有数字原语都从一个对象继承,而所有字符串原语都从另一个对象继承。这两个对象都继承自
现在的问题是,如果数字和字符串被认为是基元,为什么还要从其他对象继承它们呢?或相反,当它们从其他对象继承时,为什么不也将它们视为对象呢?在我看来,对象的子对象不是对象是没有意义的。.
顺便说一句,我也在Firefox 22中对它们进行了测试,并得到了相同的结果。
您被一种通常被称为"装箱"的机制所迷惑(与c#相关的文章,与Java有关的文章),使所有碰到它的人着迷。开始时您有正确的答案:
Perhaps because 1 is a primitive not an object to begin with?
就是这样。但是,原语如何能够包含方法?它们如何包含属性?毕竟,在js中,它们以尽可能最低的级别表示(请参阅#4.3.2)。为了使这些值实际有用,无论何时执行
1 | Object(primitive).property; |
换句话说,js具有自动装箱功能。可以使用我最喜欢的技巧之一来证明这一点:
1 2 3 | var primitive = 'food'; primitive.isPizza = true; //yummy console.log(primitive.isPizza); //undefined. where did my pizza go!? |
1 2 3 | var primitive = 'food'; Object(primitive).isPizza = true; console.log(Object(primitive).isPizza); |
装箱的
如果您的原始图元不是原始图元,则不会发生这种情况:
1 2 3 | var obj = new String('food'); obj.isPizza = true; console.log(obj.isPizza); //true |
这是否意味着您应该只使用对象,而不能使用基元?不,原因很简单,您确实需要在元数据上存储元数据的时间非常少,而对象使事情变得复杂:
1 | obj === primitive; //false, obj is an object, primitive is a primitive |