之前面试遇到一道题,问

function a(){
    this.b=5;
}
var b=9;
a();
console.log(b)

请问b的输出是多少?当时简单的回答了是5。然而这并非是正确的答案,应该从js的运行环境说起。
先说一下运行结果:
在node上我们得到的结果是9
而在浏览器上我们得到的结果是5
为什么是这样呢,我们首先知道一个js的规则:

A global variable is a variable that is declared in the global scope in other words, a variable that is visible from all other scopes. In JavaScript it is a property of the global object.

一个全局变量是在全局作用域被声明的变量,对于其它所有的作用域可见。在javascript中,全局变量是全局对象的一个属性
我们知道在浏览器中的全局变量是window,那么在全局作用域声明的变量是全局属性,全局属性也是一个全局变量。在题目中,运行a时,this指向的是全局变量window,即

this.a===window.a===var a;

因此执行a函数之后,全局变量b变为了5;

那么在node中呢,node中的一个js实际上是一个模块,我们首先说清楚node中的this指向问题

this.a=6;
(function(){
    this.a=6;
})();

函数外this的指向和函数内this的指向是不同的,函数外的this指向的是该模块,即

this===module.exports

而立即执行函数内的this指向的是node执行环境中的全局变量global

而后我们再说说node中的模块是怎样执行的

function Module() {   //  Node 模块管理类
    this.exports = {};
}

function Fun(exports, require, module, __filename, __dirname) {   //  自定义模块包装后
    var x = 1;

    console.log(module.x);  // undefined
    console.log(exports.x);  // undefined
    console.log(this.x);  // undefined

    console.log(this === module);  // false
    console.log(this === exports);  // true

}

var module = new Module();    //  实例化
var exports = module.exports;
var options = [exports, require, module, filename, dirname];

Fun.apply(exports, options);   //  自定义模块实例化

我们可以发现在node中一个模块内用var声明的变量实际上是一个函数中用var声明的变量,它并不是全局变量。由作用域链我们可知,函数作用域中的b覆盖了全局作用域中的b,由此在node中输出的是9.

参考


huaiyuG
63 声望1 粉丝

Front-end beginner.