我注意到Google Chrome调试程序的行为完全不同,具体取决于JS对象的创建方式;
如果我像这样创建一个js对象;
var SonA = function(thename) {
this.firstname = thename || "Graham";
this.age = 31;
}
SonA.prototype = new Father();
然后Chrome的调试器不允许我向下钻取并查看原型。但它确实为我提供了实例变量name和age的键值对。
但是,如果省略this
关键字,我可以深入查看原型,但是我没有在调试器中显示实例变量。
//SonB doesn't use this keyword
var SonB = function(thename) {
firstname = thename || "Graham";
age = 31;
}
SonB.prototype = new Father();
console.log(new SonA()); //this logs as: SonA {firstname: "graham", age: 31}
console.log(new SonB()); //this logs as as drill down object that shows the prototype
有谁知道这里发生了什么,为什么调试器的行为不同?以下图像和jsfiddle可以使问题更清楚地理解;
答案 0 :(得分:2)
我看不出你想要实现的目标。 为什么你可以“向下钻取”到sonB
中的原型的唯一原因是因为构造函数没有设置任何属性,但它正在创建暗示全局。只需将此行添加到您的小提琴中:
console.log(age);//<--logs 31
它记录sonB
构造函数设置的值。如果您想获得prototype-properties,您可以:删除子属性,或者使用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
的{{1}}成员函数正在处理Father
的唯一原因是因为该方法也依赖于范围扫描和隐含的全球:
sonB
这就是它的全部,只需将父的getName方法重新定义为:
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
答案 1 :(得分:1)
使用Console.dir()
代替:[{3}}
答案 2 :(得分:1)
使用24.0.1312.5(官方版本166104)测试版,我得到了这个:
SonA
age: 31
firstname: "Graham"
__proto__: Father
getName: function () {
__proto__: Object
SonB
__proto__: Father
getName: function () {
__proto__: Object
哪个是正确的,因为没有this
您要在全局对象上分配age
和firstname
(在这种情况下为window
)。在result
iframe:
> firstname
"Graham"
> age
31