关于node中var一个变量
发布于 9 年前 作者 hinson0 10711 次浏览 最后一次编辑是 8 年前 来自 问答
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

我要晓得当前申明的x挂在哪个对象上?

我是这么理解的: node对js文件进行如下封装,


(function (exports, require, module, __filename, __dirname) {
	// js code
});

而根据node源码的lib/module.js中


Module._load = function () {
	// some codes
	
	return module.exports; // 这句说明,将当前模块的exports导出
}

因此,当前文件的this即为exports,我也通过上述的代码,进行了验证,确实如此。(console.log(this === exports); // true) 我又接着认为,this.x可以访问到当前模块申明的x变量,结果this.x 却为undefined? 请各位帮我分析下。

12 回复

即使是这样 this.x跟x也毫无关系

var x 之后,x 不会成为 exports.x。所以 this.x 也取不到。

可能是我的思维比较固定。一般在浏览器端,我们在script标签var x = 1后,我直接想到这个x在window.x可以访问到它。我以为类似也可以通过exports.x可以访问到x呢。

大致明白了。刚在网上搜索了一篇变量对象的文章,给大家分享下 1 http://www.cnblogs.com/TomXu/archive/2012/01/16/2309728.html 。 深入理解JavaScript系列(12):变量对象(Variable Object) 2 https://cnodejs.org/topic/5599521293cb46f578f0a57e 图解Javascript上下文与作用域

读完这2片文章后,我自己简单理了下自己的思路 一个函数在执行后,会创建该函数的变量对象,该变量对象上有的一些属性:arguments(函数参数),函数内申请的变量(通过var申明的),函数内申明的函数

而在Node中,像我之前提到的,Node对js文件进行封装后,以避免污染全局上下文环境,因此

(function (exports, require, module, __filename, __dirname) {
    var x = 1;
});

实际上是x挂在在该函数的变量对象上,因此与this,exports是没有关系的。如果有一种手段可以访问到变量对象的话,假设为vo这样一个对象,倒是可以通过console.log(vo.x)访问到x了。不知道我的理解算不算正确。 @alsotang @hoozi

其实是个局部变量

在某个作用域下用var定义的变量, 它是这个作用域下的局部变量. 如果x不是this的属性,它就不能通过this.x访问到. 如果你在浏览器定义了个全局变量x,你可以通过window.x访问它, 那是因为全局变量有点特殊, 它会(自动)成为全局对象的属性,所以可以通过window.x

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.

see Global variable

我想,它之所以把全局变量自动成为全局对象的属性,应该是至少考虑到有下面的情况吧: 当我们在某个作用域下调用某个变量x,它会一层一层找上去. 如果它是全局变量, 作用域链可能会有点长,这种情况我们肯定不希望看到,效率太低,我们希望能用很快的方法就找到全局变量,例如window.x,但是这个语法是调用属性用的,所以就把全局变量自动成为全局对象的属性方便调用.

Node中全局是‌‌global,浏览器是window,给你简化下Nodejs模块执行

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.js 端

@enmoon 了解。谢谢关注。 :)

@yaochun 也不是吧 只是会用以前在浏览器的一些知识点进行对比 当然 通过这个问题 反应了 我对Js的理解还没有深入到了然于胸。还要继续深入学习。 谢谢关注:)

好了 大家就不要回复了 让这个帖子沉下去吧。谢谢关注。

回到顶部