【问题标题】:Set this for required arrow-functions将此设置为所需的箭头功能
【发布时间】:2025-12-07 13:05:02
【问题描述】:

我正在尝试在各种情况下设置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});

有了thisarrow functions 的文档,我可以解释所有情况,除了标有[1][2] 的情况。

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


备注

【问题讨论】:

  • 箭头函数的重点是从词法上下文中继承this的值。如果那不是你想要的,那么不要使用箭头函数。如果要“设置”或“控制”this 的值,请使用常规函数调用和可用的各种方法之一(.apply().call()obj.method() 等...)在该函数调用中控制this 的值。
  • 您在调用f4();f4.call(this); 时是否有预期的行为?
  • 给你一些背景信息:我正在重构FluentFlow,它使用用户提供的函数,即所谓的“匹配器”。作为detecting arrow functions seems to be hard(我不喜欢接受的答案),无论提供什么样的功能,我都想为“匹配器”设置this
  • 更多上下文:this is how a matcher should be defiend by the userthis is how the matcher is called by FluentFlow,是的:我知道我可以简单地将 obj 作为参数传递。但我确实喜欢this 版本的可读性。

标签: javascript node.js arrow-functions


【解决方案1】:

原因是因为“胖箭头函数”总是在词法上从周围的代码中获取它们的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,它们必须是常规函数,而不是箭头函数。


“词汇this”是什么意思? 它基本上和闭包一样。以这段代码为例:

文件A.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:我们如何定义“周围代码”,在表达式“词法this 取自周围代码”中?周围的代码是定义函数的范围,不一定是调用它的地方。

【讨论】:

  • 您能否进一步详细说明“所以,至于为什么这在 f3 的情况下不起作用,这是因为它需要一个独立的模块。” ?为什么this在这种情况下不是取自周围的代码?
  • @Ente 我用一些额外的说明更新了答案,如果有帮助,请告诉我。
  • 谢谢this 的帮助;)所以我回到detecting arrow functions 并在提供异常时引发异常。