var self = 这个?

IT技术 javascript jquery scope closures
2021-01-20 10:56:24

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

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

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

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

6个回答

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

@michael 为什么?
2021-03-21 10:56:24
@SkanderJenhani 该评论已有 8 年历史。我今天的答案会大不相同
2021-03-21 10:56:24
你真的应该将“this”绑定到函数调用,而不是传递它或用它遍历变量范围
2021-03-26 10:56:24
@michael 您可能在管道、映射、订阅...中工作,在一个函数中而不是调用函数,在这种情况下,“this”正在发生变化,因此变量范围是解决方案
2021-03-26 10:56:24

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

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

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

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 或 type script 和 ES5,那么您可以在代码中使用箭头函数,并且您不会遇到该错误,这指的是您的实例中所需的范围。

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

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

@defnull 我认为这没什么特别的。函数创建一个块作用域。所以使用箭头符号而不是函数可以防止您创建范围,因此, this 仍将引用外部 this 变量。
2021-03-11 10:56:24
作为解释:在 ES2015 中,箭头函数this从它们的定义范围捕获普通的函数定义不会那样做。
2021-03-26 10:56:24
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.
  }
}

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

您似乎在描述做什么var self = this,但这不是问题所要问的(问题是问这是否是问题的最佳解决方案)。
2021-03-27 10:56:24
” 核心问题是如何在嵌入式函数中“引导”一个变量。” 我同意接受的答案中的这一说法。除此之外,“那个”练习没有任何问题。这是很常见的。因此,作为对“代码对我来说看起来很奇怪”部分的回答,我选择解释它是如何工作的。我相信“代码对我来说看起来很奇怪”的原因来自对其工作方式的混淆。
2021-04-05 10:56:24

对此的一种解决方案是使用 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向您展示您了解thisjavascript 中绑定的行为并且不依赖于闭包引用。

此外,ES6 中的粗箭头运算符基本上与调用.bind(this)匿名函数相同:

doCallback( () => {
  // You can reference "this" here now
});
就我个人而言,我认为 .bind(this) 只是更多的输入,将 this 引用更改为我(或其他),然后仅使用它来代替使代码更清晰。胖箭头是未来。
2021-04-04 10:56:24