在Javascript排序方法中访问外部"this"

zah*_*pov 24 javascript

我有这个代码:

function some_object(...) {
   this.data = {...};

   this.do_something = function(...) {
      var arr = [...];

      arr.sort(function (a, b) {
         return this.data[a] - this.data[b];
      });  
   }
}
Run Code Online (Sandbox Code Playgroud)

然而它不起作用我认为因为this无法访问sort- 另一个this是出于某种原因看到的,而不是this封闭的外部对象.

该怎么办?谢谢

Dou*_*ner 33

不同之this处在于,通过arr.sort调用函数将匿名函数(它自己的闭包)this设置为与主对象不同的项.在Array.sort中,我实际上并不确定this设置的是什么,但它可能是您正在排序的数组.在这种情况下正常的解决方法是使用另一个变量:

function some_object(...) {
   var so = this; // so = current `this`
   this.data = {...};

   this.do_something = function(...) {
      var arr = [...];

      arr.sort(function (a, b) {
         return so.data[a] - so.data[b];
      });  
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,但这是Javascript中接受的方法吗?坦率地看起来像丑陋的黑客:-) (7认同)
  • 不,它根本不是黑客.唯一的另一种方法是通过将它绑定到函数来专门设置`this`的含义.但是,在这种情况下,`arr.sort`方法执行调用,并且您没有机会设置`this`的含义.在类似场景的对象中,我实际上在顶部声明`var base = this;`,然后仅使用`base`来引用函数范围内的那个对象.这样,我不必猜测何时使用`this`以及何时使用`base`. (2认同)
  • @z:它_is_是一个hack,但由于javascript规范中*this*的错误实现而需要.指定var = this; 在构造函数中是保留对正在创建的对象的有效引用的标准方法. (2认同)

小智 9

您可以通过调用bind内部函数上的方法将"外部"实例绑定到"内部" 函数.在MDN了解更多信息.

示例:https://jsfiddle.net/eheobo/twv3emh7/1/

var foo = {
    data: [1, 2, 3, 4],
    bar: function () {
        var printData = function(){
            this.data.forEach(a => console.info(a))
        }.bind(this)
        printData()
    }
}

foo.bar()
Run Code Online (Sandbox Code Playgroud)


Rob*_*ore 8

我知道这是 2010 年的问题,但现在您可能应该使用箭头函数(和类):

class some_object {
  constructor() {
    this.data = {...};
  }
  do_something(...) {
    let arr = [...];
    arr.sort((a, b) => this.data[a] - this.data[b]);
  }
}
Run Code Online (Sandbox Code Playgroud)

箭头函数没有this,因此它们使用封闭作用域中的那个。