191

使用实例方法作为事件处理程序的回调将范围this"My instance"更改为"Whatever just called the callback"。所以我的代码看起来像这样

function MyObject() {
  this.doSomething = function() {
    ...
  }

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}

它有效,但这是最好的方法吗?我觉得很奇怪。

4

8 回答 8

218

这个问题不是特定于 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是另一个应该以相同方式处理的伪变量——通过别名。

于 2008-12-03T17:58:14.540 回答
18

是的,这似乎是一个共同的标准。一些编码员使用自我,其他人使用我。它被用作对“真实”对象的引用,而不是事件。

这是我花了一点时间才真正理解的东西,起初看起来确实很奇怪。

我通常在我的对象顶部执行此操作(请原谅我的演示代码 - 它比其他任何东西都更具概念性,并且不是关于优秀编码技术的课程):

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
  }
}
于 2008-12-03T17:11:05.713 回答
14

如果您正在执行 ES2015 或执行类型脚本和 ES5,那么您可以在代码中使用箭头函数并且您不会遇到该错误,这指的是您在实例中所需的范围。

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});

作为解释:在 ES2015 中,箭头函数this从其定义范围中捕获。普通函数定义不这样做。

于 2016-09-12T22:39:31.690 回答
12
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.
  }
}

编辑:尽管如此,对象内的嵌套函数采用全局窗口对象而不是周围对象。

于 2015-04-26T18:07:11.230 回答
4

bind一种解决方案是使用 javascript 的方法将所有回调绑定到您的对象。

您可以使用命名方法执行此操作,

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
});
于 2016-06-01T18:55:50.690 回答
3

我没有使用过 jQuery,但是在像 Prototype 这样的库中,您可以将函数绑定到特定范围。因此,考虑到这一点,您的代码将如下所示:

 $('#foobar').ready('click', this.doSomething.bind(this));

bind 方法返回一个新函数,该函数在您指定的范围内调用原始方法。

于 2008-12-03T17:16:16.340 回答
2

只需在 ES6 中添加这一点,因为箭头函数,您不需要这样做,因为它们捕获了this值。

于 2015-10-29T21:56:31.200 回答
1

我认为这实际上取决于你要在你的doSomething函数中做什么。如果您要MyObject使用此关键字访问属性,那么您必须使用它。但我认为,如果您不使用object(MyObject)属性做任何特殊的事情,以下代码片段也将起作用。

function doSomething(){
  .........
}

$("#foobar").ready('click', function(){

});
于 2008-12-03T17:10:06.790 回答