node.js module和函数中“this”的含义

IT技术 javascript node.js
2021-02-08 19:04:40

我有一个由require.

// loaded by require()

var a = this; // "this" is an empty object
this.anObject = {name:"An object"};

var aFunction = function() {
    var innerThis = this; // "this" is node global object
};

aFunction();

(function(anyParameter){
    console.log(anyParameter.anObject);
})(
    this // "this" is same having anObject. Not "global"
);

我的问题是:this在 var 中a = this;是一个空对象,而this在函数中的语句是 node.js 全局对象的影子。我知道this关键字在函数中是不同的,但我不明白为什么 firstthis不等于 global 而this在函数中等于 global。

node.js 如何注入globalthis函数作用域中,为什么不注入到module作用域中?

4个回答

以下是您必须了解的一些基本事实才能澄清情况:

  • 在 Node module的顶层代码中,this相当于module.exports. 那就是你看到的空物体。

  • 当您使用this一个函数内,valuethis就是重新确定之前,每个执行的功能,并且它的值由下式确定如何执行该功能这意味着this如果调用机制不同(例如aFunction()vs. aFunction.call(newThis)vs.emitter.addEventListener("someEvent", aFunction);等),对完全相同的函数对象的两次调用可能具有不同的。在您的情况下,aFunction()在非严格模式下运行该函数并this设置为全局对象。

  • 当 JavaScript 文件require作为 Node module时,Node 引擎会在包装函数内运行module代码。该module包装函数是通过this设置为 调用的module.exports(回想一下,上面的函数可能会以任意this运行。)

因此,您会得到不同的this值,因为每个值都this驻留在不同的函数中:第一个值在 Node 创建的module包装器函数中,第二个值在aFunction.

我想我也找到了 module.export 来的代码。在 module.js(node.js 源代码)中,执行代码使用 javascriptapply方法作为return compiledWrapper.apply(self.exports, args);. 非常感谢大家的帮助。
2021-04-06 19:04:40

要理解这一点,您需要了解 Node.js 实际上将您的module代码包装成一个函数,就像这样

(function (exports, require, module, __filename, __dirname) {
    var test = function(){
        console.log('From test: '  + this);
    };
    console.log(this);
    test();
});

详细解释可以在这个答案中找到


现在,这个包装函数实际上是这样调用的

var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);

因此,this在module级别,实际上是exports对象。

你可以像这样确认

console.log(this, this === module.exports);
// {} true
可能值得指出,test可以以不同的方式调用,设置this为其他内容
2021-03-16 19:04:40
小心评论我的评论(和我的答案?),我认为你的答案具有误导性,因为调用 test() 的 this 的值不会影响 test() 内部的 this 的值,这完全取决于它的调用方式. 我很想知道我是否遗漏了什么
2021-03-25 19:04:40
据我所知,调用一个函数,例如fn()this指向全局对象,或者在使用时为 null use strict,当前this什么无关紧要......在设置方面,Node 与浏览器不同this吗?我认为正确的答案只是全局对象设置为exports
2021-04-08 19:04:40

概括:

在 Javascript 中, 的值this在调用函数时确定的不是在创建函数时。在module最外层范围的 nodeJS 中, 的值this是当前module.exports对象。当函数作为对象的属性被调用时, this 的值会更改为它被调用的对象。您可以通过点左规则简单地记住这一点

当一个函数被调用时,你可以this通过查看函数调用的位置来确定 的值点左边的对象是 的值this如果没有剩余的对象点的值thismodule.exports对象(window在浏览器中)。

警告:

  • 此规则不适用于es2015没有自己绑定的箭头函数this
  • 函数callapplybind可以改变有关this的规则

示例(NodeJS):

console.log(this);  // {} , this === module.exports which is an empty object for now

module.exports.foo = 5;

console.log(this);  // { foo:5 }

let obj = {
    func1: function () { console.log(this); },
    func2: () => { console.log(this); }
}

obj.func1();  // obj is left of the dot, so this is obj
obj.func2();  // arrow function don't have their own this
              // binding, so this is module.exports, which is{ foo:5 } 

输出:

在此处输入图片说明

当我运行时,module.exports = {a:4}console.log(this)我得到一个空对象
2021-03-23 19:04:40

这是因为 Node.js module中的默认全局对象是exports对象,而您正在调用test()它没有指定this. 在传统的 JS 中,this指向全局对象,用use strict,this会为空。

this 可以指向任何东西,这取决于你如何称呼它。

  • test(): 使用全局对象 ( exports) as this,除非在严格模式下, wherethis将为 null;
  • test.call({})test.apply({}):您正在指定要用作的内容this(第一个参数)
  • var obj = {testRef: test}; obj.testRef():this设置在 的左侧.,即obj

打击thefourtheye的答案

确实,this在module的顶层是exports,但这并不一定意味着thisinsidetest()也将指向与调用它的地方相同的东西。


试图证明这this和全局对象都指向exports

 myGLobal = 5;
 this.myGlobal; // 5
global object in Node.js is the exports object- 这是不正确的。每个module都有自己的exports对象。
2021-03-16 19:04:40
@Curious 谢谢,这就是我问的原因,我从命令行运行测试
2021-03-16 19:04:40
@JuanMendes 全局变量确实存在于 Node 中,但与客户端 JS 不同,您应该访问global对象。例如,global.myName = 'Mike';将通过global.myName或仅在所有module中看到myName但是var myName = 'Mike';ormyName = 'Mike'只在当前module中看到。看一下文档
2021-03-30 19:04:40
对不起,纠正你,但thisglobalREPL仅模式
2021-04-01 19:04:40
@thefourtheye 我确实从文档中收集到的,这是否意味着没有全局变量?在我上面的例子中,myGlobal 不存在于不同的module中吗?
2021-04-09 19:04:40