原型javascript混乱

时间:2015-12-07 06:48:52

标签: javascript prototype

我正在尝试下面的代码。

function Foo(who){
        this.me = who;
}
Foo.prototype.identify = function(){
     return "I am " + this.me;
};
var a1 = new Foo("a1");
a1.identify();
a1.identify = function(){
     alert("Hello, " + Foo.prototype.identify.call(this));
};
a1.identify();  

上面的代码运行良好,我理解为什么使用Foo.prototype.identify.call。我想测试一下我对此的理解,所以我将a1.identify改为

a1.identify2 = function(){
     alert("Hello, " + a1.identify());
};
a1.identify2();

我期望上面的工作方式相同。我现在只是指直接协议链识别。但是,当我跑到上面时,我得到了不确定。我错过了什么(或误解了吗?)。

2 个答案:

答案 0 :(得分:1)

a1.identify2 = function(){
 alert("Hello, " + a1.identify());
};
a1.identify2();
应该使用a1.identify()调用{p> ()

a1.identify()调用alert()并且不返回任何值。在这种情况下,返回undefined。因此,当a1.identify2()调用a1.identify()时,将执行a1.identify()并返回未定义。因此,您会看到“Hello,undefined”。

如果您希望在identify2()中看到输出,请在identify1()中查看输出,而不是警告return值。

答案 1 :(得分:1)

我不清楚你的问题是什么。当我运行您的代码in a jsFiddle时,其中没有undefined。你在alert()而不是a1.identify上进行了a1.identify(),所以你实际上并没有调用该函数,我猜这是你的错误。相反,a1.identify将尝试对将尝试转储函数源的方法进行.toString()转换(这就是我的jsFiddle或您的代码所示)。

所以,可能,你打算这样做:

a1.identify2 = function(){
     alert("Hello, " + a1.identify());
     //         parens added here ^^
};
a1.identify2();

也许您可能需要解释的是,这两者可能有些不同:

Foo.prototype.identify

a1.identify

如果没有直接向a1.identify分配任何内容,则执行a1.identify()将无法直接在.identify对象上找到a1属性,因此它将在Foo.prototype上查找{1}}它将在那里找到属性名称并在原型上执行该属性。

但是,只要你这样做:

a1.identify = function() {...}

然后,你“覆盖”了这个属性。现在,当你这样做时:

a1.identify()

JS解释器直接在a1对象上找到您的overriden属性,而不是驻留在原型上的属性。当您执行obj.property时,JS解释器首先直接在该对象上查找该属性,并且只有在找不到直接分配给该对象的属性时才会在该对象的原型中搜索具有该名称的属性。

如您所知,您可以随时访问原型上的函数,即使该属性已直接覆盖在对象上,直接通过原型:

Foo.prototype.identify.call(a1)

因此,您可以覆盖特定实例的原型属性,即使您已经覆盖它,如果您需要或者想要,仍然可以访问原型上的原始属性。