var self = this?

def*_*ull 180 javascript jquery closures scope

使用实例方法作为事件处理程序的回调改变的范围this"我的实例""无论只是调用的回调".所以我的代码看起来像这样

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

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

它有效,但这是最好的方法吗?这对我来说很奇怪.

Eug*_*kin 205

这个问题并不是特定于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!
  }
  ...
};
Run Code Online (Sandbox Code Playgroud)

这种技术依赖于使用闭包.但它不起作用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!
  }
  ...
};
Run Code Online (Sandbox Code Playgroud)

我们能做什么?将其分配给某个变量并通过别名使用它:

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!
  }
  ...
};
Run Code Online (Sandbox Code Playgroud)

this在这方面不是唯一的:arguments是应该以相同的方式处理的另一个伪变量 - 通过别名.

  • @michael为什么会这样? (9认同)
  • 你真的应该将"this"绑定到函数调用,而不是传递它或遍历变量作用域 (7认同)

Ben*_*ter 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
  }
}
Run Code Online (Sandbox Code Playgroud)


Ara*_*kar 12

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

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

  • 作为解释:在ES2015中,箭头函数从它们的定义范围中捕获``this``.正常的函数定义不会这样做. (5认同)

ser*_*kan 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.
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • “核心问题是如何在嵌入式函数中“引导”变量。” 我同意接受的答案中的这一说法。除此之外,“那个”实践没有错。这很普遍。因此,作为“代码对我来说看起来很奇怪”的答案,我选择解释其工作原理。我相信“代码对我来说看起来很奇怪”的原因是由于代码的工作方式混乱。 (2认同)