繁体   English   中英

为什么JavaScript“ this”在节点和浏览器环境中返回不同的值?

[英]Why does JavaScript “this” returns different values in Node and Browser environments?

看完Kyle Simpson在Pluralsight上的高级JavaScript课程之后,我创建了一个简单的代码片段来尝试this绑定。 我通常在SublimeText编辑器中工作,并在其中配置了节点构建引擎,有时我也在浏览器中运行相同的代码。 我注意到在Node和浏览器[Chrome]中执行代码时,程序输出中的一个区别。

以下是尝试进行this绑定的代码段。

function foo() {
    console.log(this.bar);
}

var bar = "bar1";
var obj = {bar : "bar2"};

foo();
foo.call(obj);

当我使用Sublime执行它时,它返回undefinedbar2 但是,当我在浏览器中执行相同的代码片段时,它将返回bar1bar2 ,我认为这是正确的,因为变量bar是在全局范围内定义的。 我不明白为什么Node环境会返回undefined 请帮助。

在node.js中,您的bar变量是该模块本地的模块变量。 它不是全局变量。 必须将节点中的全局变量明确分配给global对象。 node.js模块中的顶级声明并不像浏览器JS文件中那样自动成为全局变量。 从技术上讲,它们存在于模块加载器创建的功能范围内,因此它们是模块功能范围的局部变量。

在node.js中,像foo()这样的普通函数调用中的this值是global对象。

但是,在node.js中,您的bar变量不是全局对象的属性。 因此,当您尝试引用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偶然地起作用,所以这一切在浏览器中都无法正常工作。 两种错误使一项权利有时仅适用。

就像我在评论中说的那样,强烈建议您以严格模式运行代码,有时情况不会偶然发生,但其他情况则不会正常-这个问题都是高度一致的,并且如果您写错了错误,您将立即得到错误。某种代码。


尽管您已经说过您已经了解了浏览器环境中正在发生的事情,但是由于您的问题询问了两者为何不同,因此,我将仅出于涵盖所有基础的目的来描述浏览器的情况。

在浏览器中的值this在一个普通的函数调用(在不严格模式)是window对象。

在浏览器中, bar变量是全局变量,因此自动成为window对象的属性。

因此,在浏览器中,您实际上是在这样做:

function foo() {
    console.log(window.bar);
}

window.bar = "bar1";

foo();

并且,因此,您可以看到为什么它愉快地在window对象上创建一个属性,然后引用它。

那是因为变量声明var bar = "bar1"; 在全局范围内声明。 所有全局变量都可以用作窗口对象的属性。

当您在没有任何上下文的情况下调用foo() ,该方法的默认上下文是window对象(在非严格模式下),因此您的代码执行将成为console.log(window.bar); ,正如我们在上方看到的, bar变量已将其自身作为属性附加到window对象,因此其输出值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> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM