请考虑以下代码:
var Test = function(name) {
this.member = name;
}
Test.prototype.perform = function() {
console.log(this);
};
Test.prototype.perform.prototype.dance = function() {
console.log(this);
};
var actor = new Test('jane');
actor.perform();
actor.perform.dance();
我希望能够添加要执行的方法。当我在perform方法中调用console.log(this)时,我可以看到舞蹈方法已被添加到原型链中并且执行可以访问所有内容(我可以访问this.member
)但是当我退出时{{ 1}}在舞蹈方法内部,它只返回一个如下所示的对象:
this
似乎已失去对父母的访问权限,现在我无法再访问Object {dance: function}
。
这是为什么?是不是可以像上面那样在原型中添加方法?
答案 0 :(得分:1)
如果你这样称呼它会起作用 -
actor.perform.prototype.dance()
考虑这一行 -
Test.prototype.perform = function() {
console.log(this);
};
这表示,只要有人使用new Test()
创建对象,就会设置原型(您无法以统一的方式访问所有浏览器,Chrome支持非标准__proto__
访问者)到prototype
的{{1}}属性。因此,您可以访问Test
方法。
现在这个 -
perform
tell表示已添加到Test.prototype.perform.prototype.dance = function() {
console.log(this);
};
的{{1}}属性的perform
本身具有另一个名为prototype
的属性,此属性具有另一个名为{Test
的属性{1}},其中包含您想要的方法。
如果你这样做 -
prototype
然后,这表示添加到dance
的{{1}}属性的Test.prototype.perform.dance = function () {....}
有一个名为dance的属性,它指向一个函数。由于perform
对象的原型(再次,只能使用prototype
以非标准方式访问)被设置为Test
的{{1}}属性,因此您将能够以下列方式访问它 -
actor
希望这能为你清除空气。
答案 1 :(得分:1)
将Test.prototype.perform.prototype.dance
更改为Test.prototype.perform.dance
和actor.perform.dance();
将起作用
答案 2 :(得分:1)
actor.perform.dance();
执行此操作且所有功能均未绑定时,舞蹈中的this
将指向actor.perform
。您希望它指向actor
。有两种方法可以实现这个目标:
解决方案1:使用正确的方法调用方法:
actor.perform.dance.call(actor);
优点:您可以保持声明相同。
缺点:你必须在任何你称之为舞蹈的地方这样做。
解决方案2:声明方法时绑定方法:
var Test = function(name) {
this.member = name;
this.perform = function() {
console.log(this);
};
this.perform.dance = function() {
console.log(this);
}.bind(this);
}
优点:您可以保持调用代码相同(actor.perform.dance()
)
缺点:将为每个actor创建一些新函数(它们不能在原型上共享)
编辑:解决方案3:委派功能
我不会为此提供代码,因为它更难,但主要的想法是这样的。
您创建了另一个具有必要方法和target
属性的类(Performance)。您的Test.prototype.perform()
方法返回一个Performance实例,其target属性设置为调用它的Test实例。演出的舞蹈方法是针对目标而不是针对此。由您决定Test perform方法每次调用时是否创建新实例,或者每次为特定Test实例调用时都返回相同的实例。
优点:不再为每个实例创建更多功能。不需要记得用正确的方法打电话给舞蹈。
缺点:复杂性。