为什么JavaScript“this”在Node和Browser环境中返回不同的值?
在观看了Kyle Simpson的Pluralsight 高级JavaScript课程之后,我创build了一个简单的代码片段来尝试this
绑定。 我通常在SublimeText编辑器中工作,并在其中configuration了节点构build引擎,偶尔我也在浏览器中运行相同的代码。 在节点和浏览器[Chrome]中执行代码时,我注意到了程序输出中的一个区别。
以下是testingthis
绑定的代码片段。
function foo() { console.log(this.bar); } var bar = "bar1"; var obj = {bar : "bar2"}; foo(); foo.call(obj);
当我使用Sublime执行它时,它将返回undefined
和bar2
。 但是,当我在浏览器中执行相同的代码片段时,它会返回bar1
和bar2
,我认为这是正确的,因为variablesbar
是在全局范围内定义的。 我无法理解为什么Node环境将其作为undefined
返回。 请帮助。
在node.js中,您的bar
variables是该模块本地的模块variables。 这不是一个全局variables。 节点中的全局variables必须显式分配给global
对象。 node.js模块中的顶层声明并不像在浏览器的JS文件中那样是全局的。 从技术上讲,它们存在于由模块加载器创build的function范围内,因此它们是模块function范围的局部variables。
在node.js中,像foo()
这样的普通函数调用中的值是global
对象。
但是,在node.js中,你的bar
variables不是全局对象的一个属性。 所以,当您尝试引用this.bar
,这是global.bar
并且该名称没有全局对象的属性。
所以,在node.js中,你基本上是这样做的:
// create a function which is like the module scope function myModuleFunc() { function foo() { // the value of this in a plain function call in node.js is the // global object console.log(global.bar); } // this isn't a global var bar = "bar1"; foo(); } // execute that module scope function myModuleFunction();
而且,希望你能看到为什么没有global.bar
属性,因此你得到undefined
。
这一切都意外地在浏览器中工作,因为var bar
是一个全局和全局在window
对象和this === window
所以它意外的作品。 两个错误做出的权利,有时只有作品。
正如我在评论中所说的那样,强烈build议在严格模式下运行你的代码,有时候事情不会意外地起作用,而不是别人 – 这个问题将是高度一致的,当你写错了的时候,你会立即得到一个错误一些代码。
虽然你说你已经理解浏览器环境中发生的事情,但是由于你的问题是为什么这两个不同,所以我将描述浏览器的情况就是为了覆盖所有的基础。
在浏览器中, this
在纯函数调用中的值(当不是严格模式时)是window
对象。
在浏览器中,你的bar
variables是一个全局variables,因此自动成为window
对象的一个属性。
所以,在浏览器中,你基本上是这样做的:
function foo() { console.log(window.bar); } window.bar = "bar1"; foo();
而且,因此你可以看到为什么它愉快地在window
对象上创build一个属性,然后引用它。
那是因为variables声明var bar = "bar1";
这是在全球范围内宣布的。 所有的全局variables都可以作为窗口对象的属性。
当你没有任何上下文调用foo()
方法的默认上下文是window
对象(在非严格模式下),所以你的代码执行变成console.log(window.bar);
,就像我们在上面看到的那样,你的bar
variables已经把自己作为一个属性附加到窗口对象上,所以它打印的值是bar1
function foo() { snippet.log('is window:' + (this instanceof Window)) snippet.log('bar value: ' + this.bar); } var bar = "bar1"; snippet.log('window.bar: ' + window.bar) var obj = { bar: "bar2" }; foo(); foo.call(obj);
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>