如何更改ES6箭头功能的'this'指向的内容?

时间:2015-11-15 18:21:28

标签: javascript node.js callback this ecmascript-6

traverse npm包中有这个例子

var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];

traverse(obj).forEach(function (x) {
    if (x < 0) this.update(x + 128);
});

在回调函数中,您可以调用this.update。我知道在这种情况下你应该使用常规(不是ES6箭头)样式的函数定义,如上所示。

但出于好奇,你如何使用ES6箭头函数语法使代码工作?如果我尝试如下操作,我会TypeError: Cannot read property 'update' of undefined,因为this当然与上述不同。

traverse(obj).forEach((x) => {
    if (x < 0) this.update(x + 128);
});

我尝试使用this更改bind,但未成功。如何在ES6箭头功能中更改this

2 个答案:

答案 0 :(得分:8)

  

如何更改ES6箭头功能中的this

你不能,这是使用箭头功能的全部要点(除了简洁的语法)。如果您需要控制this,请不要使用箭头功能。

答案 1 :(得分:2)

ES6中的箭头功能有lexical this。这意味着您可以通过询问问题“定义函数时this的值是多少?”来告诉他们的this - 值。它们不受this - 调用,应用,绑定和方法调用的影响。

让我们看一下用Babel编译ES6到ES5的预期效果。

ES6:

let foo = {
  bar() {
    return [
      () => this,
      function() { 
        return this 
      }
    ]
  },
  baz: () => this
}

let fns = foo.bar()
fns.push(...fns.map((fn, i) => fn.bind({i})))
fns.map(fn => fn()).forEach(thisVal => {
  console.log(thisVal)
  console.log('-------')
})
console.log(foo.baz())

编译为ES5:

'use strict';

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var foo = {
  bar: function bar() {
    var _this = this;

    return [function () {
      return _this;
    }, function () {
      return this;
    }];
  },

  baz: function baz() {
    return undefined;
  }
};

var fns = foo.bar();
fns.push.apply(fns, _toConsumableArray(fns.map(function (fn, i) {
  return fn.bind({ i: i });
})));
fns.map(function (fn) {
  return fn();
}).forEach(function (thisVal) {
  console.log(thisVal);
  console.log('-------');
});
console.log(foo.baz());

查看foo.bar内发生的事情。有插入的行:

var _this = this;

更改了箭头函数的主体,使其从词法外部范围返回_this。因此,绑定this的值不应该有任何影响。通过在函数定义之前“冻结”“this”的值,我们阻止了通过绑定,使用call / apply或将函数作为方法调用来更改函数行为的能力。

请注意baz如何将此值简单地替换为undefined。那是因为如果我们问问题“定义函数时this的价值是多少?”,我们显然必须回答undefined或某些全局对象上下文,如Node global或浏览器的window。通过提出这个问题,您可以轻松地推导出箭头函数中this的值,这是其固有价值的重要组成部分。

因此输出:

{ bar: [Function: bar], baz: [Function: baz] }
-------
undefined
-------
{ bar: [Function: bar], baz: [Function: baz] }
-------
{ i: 1 }
-------
undefined

第一个和第三个输出对应bar()中定义的箭头函数。请注意他们如何自动拥有this - 值,该值指向foo引用的对象,因为它们是使用foo.bar()调用创建的。有用吗?只能通过绑定更改非箭头功能的行为。在绑定之前,它是this - 值是undefined,这是传递函数时许多JS错误和冗余绑定的常见原因。箭头功能带来了很多麻烦。