对象常量
在一些比较现代的环境中可能会提供const
来创建常量,但在其它的环境中,JavaScript是没有常量的。
一种常用的解决办法是通过命名规范,让不应该变化的变量使用全大写。这个规范实际上也用在JavaScript原生对象中:
Math.PI; // 3.141592653589793
Math.SQRT2; // 1.4142135623730951
Number.MAX_VALUE; // 1.7976931348623157e+308
你自己的常量也可以用这种规范,然后将它们作为静态属性加到构造函数中:
// 构造函数
var Widget = function () {
// 实现……
};
// 常量
Widget.MAX_HEIGHT = 320;
Widget.MAX_WIDTH = 480;
同样的规范也适用于使用字面量创建的对象,常量会是使用大写名字的属性。
如果你真的希望有一个不能被改变的值,那么可以创建一个私有属性,然后提供一个取值的方法(getter),但不给赋值的方法(setter)。这种方法在很多可以用命名规范解决的情况下可能有些矫枉过正,但不失为一种选择。
下面是一个通用的constant
对象的实现,它提供了这些方法:
set(name, value)
定义一个新的常量
isDefined(name)
检查一个常量是否存在
get(name)
取常量的值
在这个实现中,只允许基本类型的值成为常量。同时还要使用hasOwnProperty()
小心地处理那些恰好是原生属性的常量名,比如toString
或者hasOwnProperty
,然后给所有的常量名加上一个随机生成的前缀:
var constant = (function () {
var constants = {},
ownProp = Object.prototype.hasOwnProperty,
allowed = {
string: 1,
number: 1,
boolean: 1
},
prefix = (Math.random() + "_").slice(2);
return {
set: function (name, value) {
if (this.isDefined(name)) {
return false;
}
if (!ownProp.call(allowed, typeof value)) {
return false;
}
constants[prefix + name] = value;
return true;
},
isDefined: function (name) {
return ownProp.call(constants, prefix + name);
},
get: function (name) {
if (this.isDefined(name)) {
return constants[prefix + name];
}
return null;
}
};
}());
测试这个实现:
// 检查是否定义
constant.isDefined("maxwidth"); // false
// 定义
constant.set("maxwidth", 480); // true
// 再次检查
constant.isDefined("maxwidth"); // true
// 尝试重定义
constant.set("maxwidth", 320); // false
// 看看这个值是否被改变
constant.get("maxwidth"); // 480