this 变量 #
Node 应用的顶层变量是global
,对应浏览器的window
变量。
顶层的 this #
在 REPL 环境,顶层的this
就指向global
。
> global === this
true
顶层变量是global
和this
的属性。
> var foo = "bar";
> this.foo
bar
> global.foo
bar
上面代码中,foo
是一个顶层变量,自动生成了this.foo
和global.foo
两个属性。
在模块环境,顶层的this
指向当前模块,即module.exports
,默认是一个空对象,与global
不是同一个对象。
// 模块环境
console.log(this) // {}
console.log(this === global) // false
模块内部的顶层变量,不会自动成为global
和this
的属性。
// 模块环境
var foo = "bar";
console.log(this.foo); // undefined
console.log(global.foo); // undefined
上面代码中,顶层变量foo
并不会生成this.foo
和global.foo
两个属性。这是因为foo
是模块内部的变量,不是全局有效,因此不是global
的属性,而this
是当前的模块对象,this.foo
代表模块实例的属性,这跟变量foo
是两回事情。
另外,如果声明变量的时候,不使用var
命令,而是直接赋值,那么该变量在 REPL 环境下将成为global
和this
的属性,在模块环境将只成为 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
指向新建的实例对象。