我正在研究常规函数和箭头函数中的'this'关键字,所以在Stack Overflow中的示例中,我认为我已经理解了这一点,但还有一个细节没有解决。请帮帮我我不知道为什么,但是当我使用node myScript.js
测试下面的代码时,结果是undefined
,而使用Fiddle或Chrome或Firefox时,结果是预期的。
正如我所读到的,因为fo2
函数是在没有绑定任何对象的情况下调用的,所以它的'this'关键字是指全局对象,而'hi'应该被打印出来。使用node myScript.js
不会发生这种情况,但使用浏览器控制台或Fiddle会发生这种情况。我没有在函数内部使用console.log()
,以避免返回undefined
,因为它已经在其他Stack Overflow答案中解释过了。
这是代码;
var greeting = 'hi';
const obj = {
greeting: 'hey',
fo() {
const greeting = 'hello';
function fo2 () {
return this.greeting;
};
return fo2();
}
};
console.log(obj.fo()); // 'hi' using browser console and Fiddle, but undefined using `node myScript.js`
我使用的是NodeJS 18.12.1。
1条答案
按热度按时间au9on6nz1#
这里有几件事。
一个是当您运行像
node myScript.js
这样的脚本时,脚本是作为“模块”运行的。如果你的package.json有"type": "commonjs"
,或者没有指定"type"
字段,它将作为CommonJS模块运行。如果你的package.json有"type": "module"
,它将作为ECMAScript模块运行。(相关文档)。也就是说,如果您使用.js
作为文件扩展名。如果你使用.cjs
,NodeJS会将其视为CommonJS模块,如果你使用.mjs
,NodeJS会将其视为ECMAScript模块。(相关文档)。参见'this' different between REPL and script。TL;DR是使用CommonJS模块,模块中的代码运行时就像它被 Package 在下面的代码中一样:
但是如果你在REPL模式下运行NodeJS(只在系统控制台中运行
node
),那么this === globalThis
就是true
,并且在“顶级作用域”中用var
声明的变量将被放置在globalThis
对象中,就像它们在浏览器控制台中一样(其中globalThis
与全局window
对象同义)。在您的浏览器控制台中,您会得到“hi”,因为您调用
console.log(this.greeting)
的函数没有给定特定的this
,因此它福尔斯到globalThis
。但是在ECMAScript模块上下文中(例如:NodeJS脚本使用package.json和"type": "module"
或web<script module>
(模块脚本)运行,顶层的this
始终是undefined
。另一件事是,如果您不指定strict mode,JavaScript通常会默认在"sloppy mode"中运行,其中
this
永远不会是undefined
。严格模式通常是可选的,但在ECMAScript模块上下文中,严格模式是默认模式。这就是为什么在运行node myScript.js
时会得到undefined
,而如果启用严格模式,实际上会得到一个错误。下面是在启用严格模式的情况下运行CommonJS模块的“幕后”情况(如果您将
"use strict";
放在脚本文件的顶部):如果您将
"type": "module"
放入package.json中,则在没有显式使用"use script";
的情况下运行上述代码时会出现相同的错误。更多阅读:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this。