这个'的影响Chrome调试器中的关键字

时间:2012-11-16 13:25:50

标签: javascript google-chrome-devtools

我注意到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可以使问题更清楚地理解;

Screenshot

http://jsfiddle.net/7z8sp/1/

3 个答案:

答案 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会创建SonASonB共享的全局变量。

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您要在全局对象上分配agefirstname(在这种情况下为window)。在result iframe:

的上下文中运行
> firstname
"Graham"
> age
31