跳转至

this 变量

Node 应用的顶层变量是global,对应浏览器的window变量。

顶层的 this

在 REPL 环境,顶层的this就指向global

> global === this
true

顶层变量是globalthis的属性。

> var foo = "bar";
> this.foo
bar
> global.foo
bar

上面代码中,foo是一个顶层变量,自动生成了this.fooglobal.foo两个属性。

在模块环境,顶层的this指向当前模块,即module.exports,默认是一个空对象,与global不是同一个对象。

// 模块环境
console.log(this) // {}
console.log(this === global) // false

模块内部的顶层变量,不会自动成为globalthis的属性。

// 模块环境
var foo = "bar";
console.log(this.foo); // undefined
console.log(global.foo); // undefined

上面代码中,顶层变量foo并不会生成this.fooglobal.foo两个属性。这是因为foo是模块内部的变量,不是全局有效,因此不是global的属性,而this是当前的模块对象,this.foo代表模块实例的属性,这跟变量foo是两回事情。

另外,如果声明变量的时候,不使用var命令,而是直接赋值,那么该变量在 REPL 环境下将成为globalthis的属性,在模块环境将只成为 global 的属性。

// REPL 环境
> foo = "bar";
> global.foo
bar
> this.foo
bar

// 模块环境
foo = "bar";
console.log(this.foo); // undefined
console.log(global.foo); // bar

函数内部的 this

直接执行一个函数(不使用new命令),函数内部的this指向global,REPL 环境和模块环境都是如此。

foo = "bar";

function testThis () {
  this.foo = "foo";
}

console.log(global.foo); // bar
testThis();
console.log(global.foo); // foo

如果是严格模式,函数内部的this返回undefined

foo = "bar";

function testThis() {
  "use strict";
  this.foo = "foo";
}

console.log(this.foo); // "bar"
testThis();  // TypeError: Cannot set property 'foo' of undefined

如果使用new命令调用某个函数,该函数就变成了构造函数,函数内部的this指向新建的实例对象。