我看不出你想要达到什么目的。您可以“深入”到原型的唯一原因是构造函数没有设置任何属性,而是创建了隐含的全局变量。只需将此行添加到您的小提琴中:sonB
console.log(age);//<--logs 31
它记录由sonB
构造函数设置的值。如果你想获得原型属性,你要么:删除孩子的属性,要么使用该Object.getPrototypeOf()
方法。
澄清一下:这不是调试器固有的,而是 JS 获取对象的值和属性的方式。考虑以下:
var emptyObject = {};
console.log(emptyObject.someProperty);//logs undefined
Object.prototype.someProperty = 'YaY';
console.log(emptyObject.someProperty);//logs YaY
emptyObject.someProperty = function()
{
return Object.getPrototypeOf(this).someProperty;
};
console.log(typeof emptyObject.someProperty);//function
console.log(emptyObject.someProperty());//YaY again
delete(emptyObject.someProperty);//returns true
console.log(emptyObject.someProperty);//logs YaY.
这是什么意思:简单地说,如果您尝试访问任何对象(数组、对象、函数、批次)上的属性,JS 将首先检查该特定实例是否定义了该属性,如果没有,则 JS 步骤在原型链中上升一个级别。如果该原型没有请求的属性,则 JS 跳到下一个原型,以此类推。如果没有找到财产,undefined
将被退回。
因此,如果你的构造函数设置了某些属性,JS 就不会打扰原型并尽快返回属性。
同样的逻辑适用于隐含的全局变量。如果变量缺少var
关键字,JS 会扫描范围(当前函数、“父”函数,最后是全局范围)以搜索该变量。如果找到,该变量将被使用或重新分配(取决于您在代码中使用它做什么)。如果没有找到变量,那么 JS 会为您创建一个。可悲的是,没有费心回到当前范围。结果:创建了一个全局变量。
在您的代码中,Father
构造函数为每个实例创建一个新的函数对象。这个函数依赖于一个闭包变量 ( sirname
) 和一个全局变量 ( firstname
)。后者不是由SonA
,因为该构造函数分配了一个新属性。但是,SonB
确实会创建两者共享的全局变量。SonA
SonB
getName
的成员函数Father
正在处理的唯一原因sonB
是因为该方法也依赖于范围扫描和隐含的全局:
new SonB();//<-- constructor sets age and firstname globals
SonB.getName();//<-- ~= Father.getName.apply(SonB,arguments);
||
---> gets firstname global that was set in SonB constructor, uses that value
就这些了,只需将Father的getName方法重新定义为:
this.getName = function()
{//use this to point at calling context -> IE the instance on which the member function is being invoked
return this.firstname + ' ' + surname;
};