使用实例方法作为事件处理程序的回调,将this
的范围从“我的实例”更改为“无论什么叫做回调”。所以我的代码看起来像这样
function MyObject() {
this.doSomething = function() {
...
}
var self = this
$('#foobar').bind('click', function(){
self.doSomethng()
// this.doSomething() would not work here
})
}
它有效,但这是最好的方法吗?这对我来说很奇怪。
答案 0 :(得分:204)
这个问题不是特定于jQuery,而是特定于JavaScript。核心问题是如何在嵌入式函数中“引导”变量。这是一个例子:
var abc = 1; // we want to use this variable in embedded functions
function xyz(){
console.log(abc); // it is available here!
function qwe(){
console.log(abc); // it is available here too!
}
...
};
这种技术依赖于使用闭包。但它不适用于this
,因为this
是一个伪变量,可能会动态地从范围更改为范围:
// we want to use "this" variable in embedded functions
function xyz(){
// "this" is different here!
console.log(this); // not what we wanted!
function qwe(){
// "this" is different here too!
console.log(this); // not what we wanted!
}
...
};
我们能做什么?将其分配给某个变量并通过别名使用它:
var abc = this; // we want to use this variable in embedded functions
function xyz(){
// "this" is different here! --- but we don't care!
console.log(abc); // now it is the right object!
function qwe(){
// "this" is different here too! --- but we don't care!
console.log(abc); // it is the right object here too!
}
...
};
this
在这方面不是唯一的:arguments
是另一个应该以相同方式处理的伪变量 - 通过别名。
答案 1 :(得分:17)
是的,这似乎是一个共同的标准。有些程序员使用自己,有些则使用我。它被用作参考“真实”对象的参考,而不是事件。
这让我花了一些时间才真正得到它,起初看起来确实很奇怪。
我通常在我的对象顶部执行此操作(请原谅我的演示代码 - 它比其他任何内容都更具概念性,而不是优秀编码技术的课程):
function MyObject(){
var me = this;
//Events
Click = onClick; //Allows user to override onClick event with their own
//Event Handlers
onClick = function(args){
me.MyProperty = args; //Reference me, referencing this refers to onClick
...
//Do other stuff
}
}
答案 2 :(得分:10)
var functionX = function() {
var self = this;
var functionY = function(y) {
// If we call "this" in here, we get a reference to functionY,
// but if we call "self" (defined earlier), we get a reference to function X.
}
}
编辑:尽管如此,对象中的嵌套函数会占用全局窗口对象而不是周围的对象。
答案 3 :(得分:10)
如果您正在使用ES2015或执行类型脚本和ES5,那么您可以在代码中使用箭头功能,并且您不会遇到该错误,这指的是您实例中所需的范围。
this.name = 'test'
myObject.doSomething(data => {
console.log(this.name) // this should print out 'test'
});
答案 4 :(得分:4)
一个解决方案是使用javascript的bind
方法将所有回调绑定到您的对象。
您可以使用命名方法
执行此操作function MyNamedMethod() {
// You can now call methods on "this" here
}
doCallBack(MyNamedMethod.bind(this));
或使用匿名回调
doCallBack(function () {
// You can now call methods on "this" here
}.bind(this));
执行这些操作而不是诉诸var self = this
表明您了解this
在javascript中的行为如何表现并且不依赖于闭包引用。
此外,ES6中的胖箭头操作符基本上与匿名函数上的调用.bind(this)
相同:
doCallback( () => {
// You can reference "this" here now
});
答案 5 :(得分:3)
我没有使用过jQuery,但是在像Prototype这样的库中,你可以将函数绑定到特定的范围。因此,考虑到这一点,您的代码将如下所示:
$('#foobar').ready('click', this.doSomething.bind(this));
bind方法返回一个新函数,该函数使用您指定的作用域调用原始方法。
答案 6 :(得分:1)
我认为这实际上取决于你在doSomething
函数中要做什么。如果您要使用此关键字访问MyObject
属性,则必须使用该属性。但我认为如果你没有使用object(MyObject)
属性做任何特殊的事情,下面的代码片段也会起作用。
function doSomething(){
.........
}
$("#foobar").ready('click', function(){
});
答案 7 :(得分:1)
只是在ES6中添加arrow functions因为它们捕获p[1][8][0]
值而不需要这样做。