'this'关键字在Nodejs和浏览器中的行为有所不同

dan*_*doh 26 javascript node.js

我有这段代码:

var obj1;
var obj2;

function x() {
    obj1 = this;
}

function y() {
    obj2 = this;
}

x();
y();

console.log(obj1 === obj2);
console.log(obj1 === this);
Run Code Online (Sandbox Code Playgroud)

我使用命令行:node app.js在NodeJS中运行此代码,并在Chrome浏览器中作为脚本运行

结果:在NodeJS中,结果是:true false NodeJS结果

在Chrome浏览器中,结果为:true true 浏览器结果

这怎么可能发生?任何人都能解释一下真正发生的事情吗?

ade*_*neo 29

在浏览器中,在全局范围内运行this始终window在您的示例中

var obj1;
var obj2;

function x() {
    obj1 = this; // window
}

function y() {
    obj2 = this; // window
}

x();
y();

console.log(obj1 === obj2);  // window === window = true
console.log(obj1 === this);  // window === window = true
Run Code Online (Sandbox Code Playgroud)

这不是它在Node中的工作方式.在Node.js中,所有模块(脚本文件)都在它们自己的闭包中执行,而浏览器直接在全局范围内执行所有脚本文件.

换句话说,在Node中运行的任何文件中,this只是一个空对象,因为Node将代码包装在一个立即调用的匿名函数中,而您将在该上下文中访问全局作用域GLOBAL.

Globals文档中也提到了这一点:

其中一些对象实际上并不在全局范围内,而是在模块范围内 - 这将被注意到.

但是,当在Node.js中调用没有特定上下文的函数时,它通常会默认为全局对象 - GLOBAL前面提到的相同,因为它是执行上下文.

所以在函数之外,this是一个空对象,因为代码由Node包装在一个函数中,为每个模块(脚本文件)创建它自己的执行上下文,而在函数内部,因为它们是在没有指定执行上下文的情况下调用的,this是Node GLOBAL对象

在Node.js中你会得到

var obj1;
var obj2;

function x() {
    obj1 = this; // GLOBAL
}

function y() {
    obj2 = this; // GLOBAL
}

x();
y();

console.log(obj1 === obj2);  // GLOBAL === GLOBAL = true
console.log(obj1 === this);  // GLOBAL === {} = false
Run Code Online (Sandbox Code Playgroud)

this如上所述,最后一个确实是空物体


为了完整起见,值得注意的是,在严格模式下,您在浏览器(true, false)中获得的结果与在Node中相同,但这是因为变量与它们在Node中的结果正好相反

"use strict"

var obj1;
var obj2;

function x() {
    obj1 = this; // undefined
}

function y() {
    obj2 = this; // undefined
}

x();
y();

console.log(obj1 === obj2);  // undefined === undefined = true
console.log(obj1 === this);  // undefined === window = false
Run Code Online (Sandbox Code Playgroud)

这是因为this在严格模式下传递给函数的值不会被强制成为对象(也称为"盒装").
对于非严格模式下的常规函数​​,this始终是一个对象,如果使用或者此值调用它,它始终是全局对象,即没有特定的执行上下文.undefinednull

自动装箱不仅是性能成本,而且在浏览器中暴露全局对象也存在安全隐患,因为全局对象提供了对"安全" JavaScript环境必须限制的功能的访问.

因此对于严格模式函数,指定this的不会被装入对象,如果未指定,this则将undefined在函数内部,如上所示,但this仍将是全局范围内的窗口.

同样的事情发生在严格模式在Node.js的,其中this的函数中不再GLOBAL,但是undefined,和this职能以外的仍然是同样的空对象,而最终的结果仍然是true, false,但价值this会在不同Node.js中的strict-mode也是如此.

  • 您可能想提一下严格模式对此的影响(双关语:) (3认同)

Sri*_*tha 8

创建一个表格来显示this不同范围模式下的值:

在此输入图像描述

注意:Node 环境中,函数this 外部的值意味着该this值在函数声明之外,但在由 node.js 创建的用于实现模块作用域的匿名函数包装器


ism*_*iet 5

区别很简单

在节点环境中:

是指module.exportsexports简称。但在函数内部this指的是整个Node.js包。

如果您登录到控制台,您可以看到它:

function test(){
    console.log('this inside a function = ',this);
}

console.log('this outside a function = ',this);
test();
Run Code Online (Sandbox Code Playgroud)

而在浏览器环境中,函数内部或函数外部的 this指的是 window 对象,除非您使用new关键字,这是另一回事。

在 Node.js 和浏览器环境中执行前面的示例,您就会明白。


Ben*_*aum 5

节点在此处显式设置this为模块导出:

const result = compiledWrapper.apply(this.exports, args);
Run Code Online (Sandbox Code Playgroud)

什么apply不明确的是固定的this值(和参数) -在这种情况下-将其设置到this.exports。例如,您可以执行以下操作:

(function() { console.log(this.x); }).apply({x:3}); // alerts 3
Run Code Online (Sandbox Code Playgroud)

节点替代是默认行为。但是,必须global按照JS规范的要求,使用- 调用对象内部的函数。


Paf*_*low 3

在浏览器上下文中,最后一个 this 指向 Window 对象,该对象确实存在于节点上下文中。因此最后的 this 是一个空对象。然而,函数中 this 的出现指向节点上下文中的某个全局对象。