我现在已经遇到过这几次了。我试图创建最简单的代码片段来展示它。
问题是,在inside和object方法中,如果我将一个匿名函数传递给jQuery方法(比如“each”),在函数内部,我将无法访问对象的“this”。因为“this”现在与jQuery对象有关。
请参阅logNameAndElementIds
方法中间的注释,了解问题的症结所在:
(我正在使用Crockford的对象函数来生成基于使用对象文字定义的对象的对象实例。)
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
var objectLiteral = {
setName: function(name){
this.name = name;
},
logNameAndElementIds: function(){
// works fine, 'this' refers to object instance
console.log( this.name );
$('.foo').each(function(){
// we've lost "this" because it now refers to jQuery
console.log( this.name );
console.log( $(this).attr('id') );
});
}
};
obj1 = Object.create(objectLiteral);
obj1.setName('Mike');
obj1.logNameAndElementIds();
处理或解决此类情况的正确方法是什么?
显然我的例子是愚蠢的,但这只是为了证明一个观点。更常见的是,我想循环遍历jQuery匹配集,然后在每个项上调用包含对象的方法。但我无法访问该对象的方法,因为我现在有jQuery的“this”。
答案 0 :(得分:1)
解决此问题的方法是将this
保存到您可以在新范围内访问的变量。
查看你的logNameAndElementIds函数:
logNameAndElementIds: function(){
// works fine, 'this' refers to object instance
console.log( this.name );
var that = this;
$('.foo').each(function(){
// we've lost "this" because it now refers to jQuery
console.log( that.name );
console.log( $(this).attr('id') );
});
}
答案 1 :(得分:0)
'指针'this
的值会根据功能块的范围而改变。要从外部作用域引用this
,请保存原始对象this
的副本(常见约定将其保存为self
):
var objectLiteral = {
setName: function(name){
this.name = name;
},
logNameAndElementIds: function(){
// works fine, 'this' refers to object instance
console.log( this.name );
var self = this;
$('.foo').each(function(){
//use 'self' instead of 'this'
console.log( self.name );
console.log( $(this).attr('id') );
});
}
};
答案 2 :(得分:0)
这是众所周知的事情。通常我们会使用原始this
的代理。
var that = this;
$('.foo').each(function(){
console.log( that ); // original object
console.log( this );
});
答案 3 :(得分:0)
我认为有一个比我之前接受的更好的答案,那就是使用ES5的新Function.prototype.bind方法。更清洁,适用于所有现代浏览器,并且易于为旧浏览器提供垫片。
使用bind(),您可以执行以下操作:
var myObj = {
name: "Foo";
iterateParagraphs: function() {
$("p").each(function(i,p){
$(p).addClass("bar"); // use $(p) where you use to use $(this);
$(p).text(this.name); // this refers to myObj = Foo
}.bind(this)); // get this (myObj) into callback
}
};
Mozilla垫片的缩小版本(似乎是最好的):
Function.prototype.bind||(Function.prototype.bind=function(b){if("function"!==typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var d=Array.prototype.slice.call(arguments,1),e=this,a=function(){},c=function(){return e.apply(this instanceof a&&b?this:b,d.concat(Array.prototype.slice.call(arguments)))};a.prototype=this.prototype;c.prototype=new a;return c});