【问题标题】:Access "this" from within anonymous function从匿名函数中访问“this”
【发布时间】:2014-11-08 15:48:54
【问题描述】:

好的,这听起来可能非常简单,但由于这是我第一次真正认真地使用 JavaScript/jQuery,所以我想知道最好的方法是什么。

所以,情况如下:

var someClass = function()
{
    var someProperty;

    /*********************************
     Initialisation
     *********************************/

    this.construct = function(options){

        this.someProperty = "someValue";

        $("#someDiv").click(function(){
            // I want to access "this" (= the someClass object) here
        });

    }
}

var theObj = new someClass();

现在,这就是:鉴于在我的特定情况下,theObj 只是一个(全局)对象,我显然可以这样做:

$("#someDiv").click(function(){
     console.log(theObj.someProperty);
});

但我绝对不喜欢它 - 必须有更优雅/面向对象友好的方式。


那么,你会怎么做呢?

【问题讨论】:

  • 提示:函数可以访问所有外部作用域中的变量。

标签: javascript jquery class oop this


【解决方案1】:

您可以bind 保持相同的上下文:

$("#someDiv").click((function(){
        // same this as externally
}).bind(this));

或者你可以在闭包中定义一个变量:

var obj = this;
$("#someDiv").click(function(){
        // your this is obj
});

或者,如果使用 Firefox(以及其他浏览器),您可以使用箭头功能:

$("#someDiv").click(() => {
        // same this as externally
});

【讨论】:

    【解决方案2】:

    使用bind 或保存对this 的引用:

    $("#someDiv").click((function() {
      console.log(this.someProperty);
    }).bind(this));
    

    var that = this;
    
    $("#someDiv").click((function(){
       console.log(that.someProperty);
    });
    

    【讨论】:

    • 非常感谢!为了公平起见,由于@dystroy 的回答快了几秒钟,所以我要选择这个。 :-)
    【解决方案3】:

    由于您没有使用 .prototype 添加方法,而是将它们创建为类中的特权方法,因此只需在构造函数的范围内使用一个附加变量来引用该对象:

    var someClass = function() {
    
        var self = this;
    
        ...
    
    };
    

    这允许您保留this 引用单击元素的正常jQuery 语义,同时使self 可用于引用包装对象。出于这种语义保留的原因,我特别建议不要使用.bind(this)

    关于您最终提出的仅在回调中使用 theObj 的“解决方案” - 您还应该从不从内部以自己的名称引用对象,因为这些名称不在您的控制并可能改变。它可能在您当前的代码中是安全的,但它是代码维护和代码隔离的噩梦。

    【讨论】:

      【解决方案4】:

      有很多方法。你的方法是一种,它是最简单有效的方法之一,据我所知,它意味着更少的性能损失(它使用闭包)。

      其他方法:

      .bind(this).

      bind 在给定函数的范围内改变了this 的含义。如果您执行以下操作,请单击处理程序,此关键字将是外部 this 引用:

       // This will bind outter "this" as the object referenced by 
       // inner this
       $("#someDiv").click(function(){
            console.log(this.someProperty);
       }.bind(this));
      

      .call(this, arg1, argN).

      call 定义了被调用函数中this 的引用。第一个参数是this 在被调用函数范围内的引用为this。下一个参数是可调用的函数参数(如果函数有它们)。 这不适用于点击处理程序用例

      在某些极端情况下,您可能希望使用 call。例如,如果您想以某种自定义方式路由事件并且事件处理程序接收自定义上下文:

       var that = this;
      
       $("#someDiv").click(function(){
            // Some handler function from the outter scope. It will have a "this"
            // reference to the outter "this" object reference
            someHandlerFunction.call(that, { currentElement: this, timeStamp: Date.now() });
       });
      

      .apply(this, [arg1, argN]).

      call 相同,函数参数以数组形式给出,而不是像常规函数调用那样以逗号分隔的实际函数参数。 同样,不适用于您的用例

      结论

      首选方法:您的。 bind/call/apply 方法性能较差,如果您在 DOM 事件处理程序中使用它有一个很大的缺点:您失去了由 DOM 定义的标准 this 含义 - DOM 的引用引发事件的元素 -

      在其他边缘情况下使用绑定,其中this 表示window JavaScript 对象,并且您希望避免闭包方法

      【讨论】:

      • @Alnitak 不相关,这就是为什么我说 这不适用于点击处理程序用例。,但我想向 OP 展示如何操纵 this 引用在其他用例中...
      • 所以你做了 - 恕我直言,它可能有点混淆了答案。
      • @Alnitak 现在我提供了call(...) 的一个可能用例,它有时在KnockoutJS 中使用。
      • @Alnitak 好吧,不仅在 KO 中,我在其他情况下也多次要求。
      猜你喜欢
      • 2010-11-08
      • 1970-01-01
      • 2012-03-22
      • 2015-05-04
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      相关资源
      最近更新 更多