我试图在各种情况下设置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和arrow functions的文档,除了标有[1]
和[2]
的案例外,我可以解释所有案例。
有人可以对观察到的行为有所了解吗?并且可能会提示我如何调用f3
以便函数打印为true。
备注
requireFromString
- 函数是从Load node.js module from string in memory改编而来的,只是为了减少这个stackoverflow问题。在实践中,这被普通的require(...)
答案 0 :(得分:1)
原因是"胖箭头功能"总是从周围的代码中学习this
词法。他们 无法 将this
更改为call
,bind
等。运行此代码作为示例:
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
,它们不能与bind
,call
等绑定,如上所述。
为了对它们使用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
。并且以同样的方式你不能期望fileB的函数可以访问fileA的变量,你不能期望调用模块(fileA)的this
能够成为从被调用模块(fileB)的主体引用。
TLDR:我们如何定义"周围的代码",在表达式" lexical this
中取自周围的代码?"周围的代码是定义函数的范围,不一定是调用它的位置。