详解JavaScript常量定义
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
详解JavaScript常量定义
相信同学们在看见这个标题的时候就⼀脸懵逼了,什么?JS能常量定义?别逗我好吗?确切的说,JS当中确实没有常量(ES6中好像有了常量定义的关键字),但是深⼊⼀下我们可以发现JS很多不为⼈知的性质,好好利⽤这些性质,就会发现⼀个不⼀样的JS世界。
⾸先,在JS当中,对象的属性其实还含有⾃⼰的隐含性质,⽐如下⾯对象:
var obj = {};
obj.a = 1;
obj.b = 2;
在这⾥我们定义了⼀个对象 obj ,并且定义了这个对象的两个属性 a 、 b ,我们可以修改这两个属性的值,可以⽤ delete 关键字删除这两个属性,也可以⽤ for ... in ... 语句枚举 obj 对象的所有属性,以上的这些操作叫做对象属性的性质,在我们平常编写代码的时候我们会不知不觉的默认了这些性质,把他们认作为JS应有的性质,殊不知这些性质其实是可以修改的。我通常的定义的属性的⽅法,默认了属性的性质,不过我们也可以在定义属性的时候修改属性的性质,⽐如:
var obj = {};
obj.a = 1;
obj.b = 2;
//等价于
var obj = {
a: 1,
b: 2
}
//等价于
var obj = {};
Object.defineProperty(obj, "a", {
value: 1, //初始值
writable: true, //可写
configurable: true, //可配置
enumerable: true //可枚举
});
Object.defineProperty(obj, "b", {
value: 2, //初始值
writable: true, //可写
configurable: true, //可配置
enumerable: true //可枚举
});
这⾥涉及到了⼀个⽅法,Object.defineProperty(),该⽅法是ES5规范中的,该⽅法的作⽤是在对象上定义⼀个新属性,或者修改对象的⼀个现有属性,并对该属性加以描述,返回这个对象,我们来看⼀下浏览器兼容性:
特性Firefox (Gecko)Chrome Internet Explorer Opera Safari
基本⽀持4.0 (2)59 [1]11.60 5.1 [2]
还是天煞的IE8,如果你的项⽬要求兼容IE8,那么这个⽅法也就不适⽤了,不过IE8也对该⽅法进⾏了实现,只能在DOM对象上适⽤,⽽且有⼀些独特的地⽅,在这⾥就不讲解了。
Object.defineProperty() ⽅法可以定义对象属性的数据描述和存储描述,这⾥我们只讲数据描述符,不对存储描述符讲解,数据描述符有以下选项:
configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false。
enumerable
当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
注意,当我们⽤常规⽅法定义属性的时候,其除 value 以外的数据描述符默认均为 true ,当我们⽤ Object.defineProperty() 定义属性的时候,默认为 false。
也就是说,当我们把 writable 设置为 false 的时候,该属性是只读的,也就满⾜了常量了性质,我们把常量封装在CONST命名空间⾥⾯:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false, //设置属性只读
configurable: true,
enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2; //在严格模式下会抛错,在⾮严格模式下静默失败,修改⽆效。
但是这样定义的常量不是绝对的,因为我们依然可以通过修改属性的数据描述符来修改属性值:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false,
configurable: true,
enumerable: true
});
Object.defineProperty(CONST, "A", {
value: 2,
writable: true, //恢复属性的可写状态
configurable: true,
enumerable: true
})
console.log(CONST.A); //2
CONST.A = 3;
console.log(CONST.A); //3
想要做到真正的常量,还需要将属性设置为不可配置:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false, //设置属性只读
configurable: false, //设置属性不可配置
enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2; //错误!属性只读
Object.defineProperty(CONST, "A", {
value: 2,
writable: true,
configurable: true,
enumerable: true
}); //错误!属性不可配置
但是如果只设置属性为不可配置状态,依然可以对属性值进⾏修改:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: true, //设置可写
configurable: false, //设置属性不可配置
enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2;
console.log(CONST.A); //2
进⽽我们可以推断出,configurable 描述符仅冻结属性的描述符,不会对属性值产⽣影响,也就是说该描述符会冻结writable、configurable、enumerable 的状态,不会对属性值加以限制:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false, //设置不可写
configurable: false, //设置属性不可配置
enumerable: false //设置不可枚举
});
Object.defineProperty(CONST, "A", {
value: 2, //该属性本⾝不受 configurable 的影响,但由于属性不可写,受 writable 的限制
writable: true, //错误!属性不可配置
configurable: true, //错误!属性不可配置
enumerable: true //错误!属性不可配置
});
但是 configurable 的限制有⼀个特例,就是 writable 可以由 true 改为 false,不能由 false 改为 true: