2014-09-28 46 views
0

也许标题听起来有点不可思议(请改进) - 但我需要以下方案的解决方案。我有以下代码:即使使用修改上下文的函数也不要修改上下文

var Foo = function() { 
    this._hello = "world!"; 
}; 

Foo.prototype.bar = function() { 
    console.log(this._hello); 
}; 

var f = new Foo(); 
f.bar(); // => "world!" 
f.bar.apply(this); // => undefined 

我知道apply变化的情况下,所以里面barthis将是全局对象(在第二次调用)。

但我需要的是从Foo功能访问this。我看到的解决方案是:

var Foo = function() { 
    var self = this; 
    self._hello = "world!"; 
    self.bar = function() { 
     console.log(self._hello); 
    }; 
}; 

但是,我会选择不在另一个函数中有方法声明。

我宁愿定义方法(只是代码风格)同列级:

var Foo = ...; 
Foo.prototype.method = ...; 

这可能吗?怎么样?

+0

只是不打扰缩进你的代码。 – 1983 2014-09-28 23:12:04

+0

这不是“范围”,它是调用的*上下文* – Bergi 2014-09-29 20:59:41

+0

为什么要在'bar'上使用'apply'?你的电话怎么看起来不是简单的'f.bar()'? – Bergi 2014-09-29 21:00:50

回答

2

请参见您可以使用bind() method解决these kinds of problems。而不是something.method(f.bar)调用something.method(f.bar.bind(f))以获取bar方法始终在预期的上下文中调用(f)。

如果你不想在你传递bar周围作为回调每个位置使用bind,你也可以把它在构造函数中默认创建的每个实例专用的约束功能:

function Foo() { 
    this._hello = "world!"; 
    this.bar = this.bar.bind(this); 
} 
Foo.prototype.bar = function() { 
    console.log(this._hello); 
}; 

var f = new Foo; 
something.method(f.bar); // works! 
+1

应该是'this._hello' – CupawnTae 2014-09-30 14:46:57

+0

这是正确的解决方案,但我不推荐它,因为它不是我记忆友好。 – 2014-09-30 15:05:16

+0

@IonicăBizău:为什么?它不应该比关闭解决方案更少的内存友好。 – Bergi 2014-09-30 15:20:52

0

这样做不可能通过将函数分配给原型来实现。

除非您直接指定f.bar(如第二个示例和Bergi的答案),否则f.bar将获得的值是您分配给原型属性Foo.prototype.bar的功能的参考。对于任何其他以Foo.prototype为原型的对象,这将是完全相同的函数对象。此函数对象中没有提及f

因此,当您拨打f.bar()时,this如何参考值f?这是一种特殊的语法,基本相当于f.bar.apply(f)。只有您使用此方法调用语法才能将this设置为f的值。对f.bar的任何其他参考将仅评估原型的单个共享函数对象。

如果用f.bar.apply(somethingElse)调用它,则this现在设置为somethingElse,并且与f的所有关联都将丢失。

这不是apply(...)改变范围的问题。 fn.apply(x)设置thisxfn内,而y.fn()设置thisy

同样,在你的例子,如果你指定f.bar给一个变量,然后通过该变量调用它,而不是使用方法调用的语法f.bar()的,你this将是window对象(如果在浏览器中运行),并再次你会得到undefined

var func=f.bar; // now func === Foo.prototype.bar 
func(); // => undefined 

How to find the object a function belongs to?

相关问题