为什么数字从Object.prototype继承时不是Object的实例?

Mah*_*Ali 3 javascript object ecmascript-6

请参见下面的代码段。

let num = 3;
Object.prototype.prop = "something";
console.log(num instanceof Object); //false;
console.log(num.hasOwnProperty('prop')) //false

console.log(num.prop) //'something'
Run Code Online (Sandbox Code Playgroud)

有人可以解释原因num instanceof Objectnum.hasOwnProperty('prop')返回,false但仍然可以访问Object.prototypeon 的属性num

tri*_*cot 5

数字是基元,因此它们不继承Object也不是instanceof任何东西。

但是,Number当您尝试访问属性(例如方法)时,Javascript会在Number对象上加上一个数字,以使该属性访问实际上位于即时创建的对象上。就像您这样做:

console.log((new Number(num)).constructor.name);
console.log((new Number(num)).hasOwnProperty('prop'));
console.log((new Number(num)).prop): 
Run Code Online (Sandbox Code Playgroud)

prop将在的原型链中找到Number对象,但hasOwnProperty-顾名思义-没有看原型链,因此不会考虑你穿什么的Object.prototype

请注意,当您不尝试访问属性时,不会发生这种无声拳击,因此在num instanceof原语中考虑的Number是它,而不是其变体。

您实际上可以通过调用toSource方法查看该装箱的痕迹:

console.log((new Number(num)).constructor.name);
console.log((new Number(num)).hasOwnProperty('prop'));
console.log((new Number(num)).prop): 
Run Code Online (Sandbox Code Playgroud)

有趣的事实:您还可以使用数字文字来获得此装箱-它需要第二个点才能与小数点区分开来:

let num = 5;
console.log(num.toSource());
Run Code Online (Sandbox Code Playgroud)

“拳击”的规格

EcmaScript规范在“ 属性访问器 ”部分中定义了此过程。评估依赖

GetValue(propertyNameReference).
Run Code Online (Sandbox Code Playgroud)

继而在其流程定义中具有以下内容:

If IsPropertyReference(V) is true, then

   If HasPrimitiveBase(V) is true, then
       Assert: In this case, base will never be undefined or null.
       Set base to ! ToObject(base).
Run Code Online (Sandbox Code Playgroud)

最后ToObject执行实际的包装。