如何定义常量在全局范围内nodejs

JavaScript011

如何定义常量在全局范围内nodejs,第1张

如果正在使用一系列node模块,或许是一个像Express.js一样的框架,突然需要使用几个全局变量。怎样在nodejs里创建全局变量呢?

对此最常见的建议是“不使用‘var’关键字声明一个变量”或“给object对象添加一个变量”或“给OBJECT对象添加一个变量”。你会使用哪种方式呢?

首先,让分析下global对象。打开一个终端,启动一个node命令提示界面:

[plain] view plain copy print?

$ node

>

在命令提示界面下看看关于global的所有信息:

[plain] view plain copy print?

>global

那是一个超级大的对象!事实上,看到了node的核心。所有在node进程里的对象都挂在这个对象上。如果非常熟悉javascript所在的浏览器环境,global对象是等同于window对象。

现在已经指导global对象是声明

[plain] view plain copy print?

>global.name

undefined

>global.name = 'El Capitan'

>global.name

'El Capitan'

>GLOBAL.name

'El Capitan'

>delete global.name

true

>GLOBAL.name

undefined

>name = 'El Capitan'

'El Capitan'

>global.name

'El Capitan'

>GLOBAL.name

'El Capitan'

>var name = 'Sparrow'

undefined

>global.name

'Sparrow'

令人兴奋的观察!

global和BLOBAL看起来是一个同一个东西且是一回事。确实,Global是global一个别名。

感兴趣的是一个使用还是不使用var关键字声明的变量附加到global对象上。在node里创建一个全局变量的最基本的方式就是通过不使用var关键字声明一个变量。这种做法与使用一个模块(module)略有不同

当启动一个node进程,将会启动一个模块,那么所有的模块将会被包含在它里面,所有模块都共享同一个global对象。应用上面的测试观察结合实际,你就会明白全局变量怎样在node里工作。然而有些轻微的变化,如果使用var关键字声明的变量将会保留在本地模块里;这些声明的变量没有附加到global对象里。

那么现在已经知道”没有使用var关键字声明的变量“,”向global里添加一个变量“,”给GLOBAL对象添加一个变量“,所有这些都是一回事。

在一个module里全局声明的变量能够被其他任何模块使用它们的名字来引用,没必要从global对象引用它们。但是这不意味这你就可以这样做。为什么呢?请看这样:

[plain] view plain copy print?

var company = 'Yahoo'

console.log(global.company)// 'Google'

console.log(company)// 'Yahoo'

当使用global.company时,知道使用的是全局变量,但是它的备用名字company在module是当作局部变量来使用的。

如果打算在你的node应用里使用全局变量,那么讨论的创建变量方法会工作的很好。然而,请不要过度使用它。话虽如此,还有可以不使用全局对象的替代解决方案吗?

是的,有这么一个,它涉及到module.exports的使用。使用例子来演示:

File: main.js

[plain] view plain copy print?

exports.company = 'Google'

var m = require('./mod')

File: mod.js

[plain] view plain copy print?

var company = require('./main').company

console.log(company)

现在看看执行结果:

[plain] view plain copy print?

$ node main.js

Google

这样就实现了,一个其他模块的的变量可以在另外的模块中使用他而没有使用global对象。可以include main.js在其他的module来访问company名字。

注意:引用(include)一个已经被其他模块引用过的模块时,仅仅创建一个指向之前包体的引用,因此这意味着不会极度消耗内存。也因为没有重新创建一个真正的包体,在module里的所有初始化方法没有再执行。

因此,一个包体中,有2钟创建node全局变量的方法,一个是使用global对象,另一个是使用modules.exports。global方法适用小的应用,modules.exprots适用于大的应用。

1. 用global来保存常量

const.js

global.MY_CONST= 'global const'11

技术上可以,你只需要 require const.js,无需保存返回值

main.js

require('./const')

console.log(global.MY_CONST)

global.MY_CONST = 'changed global const'

console.log(global.MY_CONST)12341234

但是设计原则上来讲,应该将内容封装到文件内,通过exports导出。

而且,这种方式并不能定义常量。

2. 直接export一个包含常量的对象

const.js

const obj = {

MY_CONST:'my const'

}

module.exports = obj

123456123456

这种方式有同样的问题,const并不能定义一个属性无法修改的对象,MY_CONST依然是可以修改的。

3. 用Object.defineProperty来定义常量

上面的方法试图定义一个const对象,但这是不可能的。但是我们可以通过配置将对象属性的设定为不可修改的。

const.js

Object.defineProperty(exports, "PI", {

value:3.14,

enumerable: true,

writable: false,

configurable: false

})123456123456

writable和configurable默认是false,所以可以简化一下

Object.defineProperty(exports, "PI", {

value:3.14,

enumerable:true

})12341234

更好的方式,如果你不想为每一个属性都手写配置的话:

function define(name, value) {

Object.defineProperty(exports, name, {

value: value,

enumerable: true

})

}

define("PI", 3.14)1234567812345678

看起来更舒服了。

4. 通过 Object.freeze 来固定属性值

const.js

module.exports = Object.freeze({

MY_CONSTANT: 'some value',

ANOTHER_CONSTANT: 'another value'

})12341234

freeze的简单介绍,来自 mozilla:

The Object.freeze() method freezes an object: that is, prevents new properties from being added to itprevents existing properties from being removedand prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.

大概意思是说,freeze能够阻止对象属性的添加,删除,以及属性的enumerable, writable,configurable的修改,也就是将此对象变成一个不可变对象。

想必前一种方案,这种更简单,更安全(因为阻止了对属性writable的修改,所以也不担心某些别有用心的人修改了常量的writable后,再进一步修改属性值)。