为所需的箭头功能设置此项

Set this for required arrow-functions

我正在尝试在各种情况下设置 this

在 node.js v6.8.1 中执行的以下代码将打印每行末尾注释的内容:

function requireFromString(src) {
  var Module = module.constructor;
  var m = new Module();
  m._compile(src, __filename);
  return m.exports;
}

(function(){
  var f1 = (() => {console.log(this.a === 1)});
  var f2 = function(){ console.log(this.a === 1) };
  var f3 = requireFromString('module.exports = (() => {console.log(this.a === 1)});');
  var f4 = requireFromString('module.exports = function(){ console.log(this.a === 1) };');

  console.log('Body:');
  console.log(this.a === 1);                          // true
  (()=>console.log(this.a === 1))();                  // true
  (()=>console.log(this.a === 1)).call(this);         // true
  (function(){console.log(this.a === 1)})();          // false
  (function(){console.log(this.a === 1)}).call(this); // true


  console.log('\nFunctions:');
  f1();                                               // true
  f1.call(this);                                      // true
  f2();                                               // false
  f2.call(this);                                      // true
  f3();                                               // false [1]
  f3.call(this);                                      // false [2]
  f4();                                               // false 
  f4.call(this);                                      // true

}).apply({a:1});

借助 this and arrow functions 的文档,我可以解释所有情况,但标有 [1][2] 的情况除外。

有人可以阐明观察到的行为吗?也许可以提示我如何调用 f3 以便函数打印 true.


注释

原因是因为 "fat arrow functions" 总是从周围的代码中按词法获取它们的 this。他们不能将他们的this更改为callbind等运行此代码为例:

var object = {
  stuff: 'face',

  append: function() {
    return (suffix) => {
      console.log(this.stuff + ' '+suffix);
    }
  }
}
var object2 = {
  stuff: 'foot'
};

object.append()(' and such');
object.append().call(object2, ' and such');

您只会看到 face and such

所以,至于为什么在 f3 的情况下它不起作用,这是因为它是一个独立的模块。因此,它的基础级箭头函数将仅使用模块中的 this,它们不能与所讨论的 bindcall 等绑定。 为了在它们上面使用 call,它们必须是常规函数,而不是箭头函数。


"lexical this" 是什么意思? 基本上和闭包一样工作。以这段代码为例:

fileA.js:

(function () {
    var info = 'im here!';

    var infoPrintingFunctionA = function() {
        console.log(info);
    };

    var infoPrintingFunctionB = require('./fileB');

    infoPrintingFunctionA();
    infoPrintingFunctionB();
})();

fileB.js:

module.exports = function() {
    console.log(info);
};

结果会怎样?一个错误,info is not defined。为什么?因为函数的可访问变量(作用域)仅包括可用的变量定义函数的地方。因此,infoPrintingFunctionA 可以访问 info,因为 info 存在于定义 infoPrintingFunctionA 的范围内。

然而,尽管 infoPrintingFunctionB 在同一范围内被 调用 ,但它并未在同一范围内 定义 .因此,它无法从调用范围访问变量。

但这都与变量和闭包有关; this 和箭头函数呢?

箭头函数的this与函数中其他变量的闭包作用相同。基本上,箭头函数只是说在创建的闭包中包含 this 。并且以同样的方式你不能期望 fileA 的变量可以被 fileB 的函数访问,你不能期望调用模块(fileA)的 this 能够从主体中引用被调用模块 (fileB).

TLDR:我们如何定义"surrounding code",在表达式"lexical this is taken from the surrounding code?"周围的代码是定义函数的范围,不一定是调用它的地方。