jquery“this”阻止访问包含对象“this”

时间:2012-08-16 17:27:41

标签: javascript jquery

我现在已经遇到过这几次了。我试图创建最简单的代码片段来展示它。

问题是,在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”。

4 个答案:

答案 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});