English 中文(简体)
var self = this --> var self = 这个
原标题:
  • 时间:2008-12-03 16:55:39
  •  标签:

将实例方法用作事件处理程序的回调会改变this的作用域,从“我的实例”变为“刚刚调用回调函数的对象”。所以我的代码看起来像这样。

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

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

它能正常运行,但这是否是最佳的方式呢?在我看来,它看起来有些奇怪。

最佳回答

这个问题并不仅限于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也应该以相同的方式进行别名处理。

问题回答

是的,这似乎是一种常见的标准。有些编码者使用self,有些使用me。它用作将事件与“真实”对象相对应的参照。

这是我需要一些时间才明白的事情,起初确实看起来很奇怪。

我通常会在对象的顶部执行此操作(请原谅我的示范代码 - 它更多的是概念性的,而不是优秀编码技术的课程):

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
  }
}

如果您正在使用ES2015或进行类型脚本和ES5,那么您可以在您的代码中使用箭头函数,这样您就不会面临错误,并且这会引用您实例中所需的范围。

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

作为解释:在ES2015中,箭头函数从它们定义的作用域中捕获 this。普通函数定义不会这样做。

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.
  }
}

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

这个问题的一个解决方案是使用JavaScript的bind方法将所有回调函数绑定到您的对象。

你可以使用一个命名方法来做到这一点。

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表明您理解JavaScript中this的绑定行为,并且不依赖于闭包引用。

此外,在ES6中的箭头函数运算符基本上就是在匿名函数上调用 .bind(this)

doCallback( () => {
  // You can reference "this" here now
});

I haven t used jQuery, but in a library like Prototype you can bind functions to a specific scope. So with that in mind your code would look like this:

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

The bind method returns a new function that calls the original method with the scope you have specified.

Just adding to this that in ES6 because of arrow functions you shouldn t need to do this because they capture the this value.

I think it actually depends on what are you going to do inside your doSomething function. If you are going to access MyObject properties using this keyword then you have to use that. But I think that the following code fragment will also work if you are not doing any special things using object(MyObject) properties.

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

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

});




相关问题