JavaScript之ES6学习一(ES3、ES5与ES6常量定义对比)
1、JavaScript常量定义
(1)、常规定义对象参考
//定义对象obj,并制定属性name,age var obj = {}; obj.name = "张三"; obj.age = 20; //等价于 var obj = { name = "张三"; age = 20; } //等价于 var obj = {}; Object.defineProperty(obj, "name", {
value: "张三", //初始值
writable: true, //可写
configurable: true, //可配置
enumerable: true //可枚举 }); Object.defineProperty(obj, "age", { value: 20, //初始值 writable: true, //可写 configurable: true, //可配置 enumerable: true //可枚举 });
这里涉及到了一个方法,Object.defineProperty(),该方法是ES5规范中的,该方法的作用是在对象上定义一个新属性,或者修改对象的一个现有属性,并对该属性加以描述,返回这个对象。
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, "NUM", { value: 1, writable: false, //设置属性只读 configurable: true, enumerable: true }); console.log(CONST.NUM); //1 CONST.NUM = 2; //在严格模式下会抛错,在非严格模式下静默失败,修改无效。
但是这样定义的常量不是绝对的,因为我们依然可以通过修改属性的数据描述符来修改属性值:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, writable: false, configurable: true, enumerable: true }); Object.defineProperty(CONST, "NUM", { value: 2, writable: true, //恢复属性的可写状态 configurable: true, enumerable: true }) console.log(CONST.NUM); //2 CONST.NUM = 0; console.log(CONST.NUM); //0
想要做到真正的常量,还需要将属性设置为不可配置:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, writable: false, //设置属性只读 configurable: false, //设置属性不可配置 enumerable: true }); console.log(CONST.NUM); //1 CONST.NUM = 2; //错误!属性只读 Object.defineProperty(CONST, "NUM", { value: 2, writable: true, configurable: true, enumerable: true }); //错误!属性不可配置
但是如果只设置属性为不可配置状态,依然可以对属性值进行修改:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, writable: true, //设置可写 configurable: false, //设置属性不可配置 enumerable: true }); console.log(CONST.NUM); //1 CONST.A = 2; console.log(CONST.NUM); //2
进而我们可以推断出,configurable 描述符仅冻结属性的描述符,不会对属性值产生影响,也就是说该描述符会冻结 writable、configurable、enumerable 的状态,不会对属性值加以限制:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, writable: false, //设置不可写 configurable: false, //设置属性不可配置 enumerable: false //设置不可枚举 }); Object.defineProperty(CONST, "NUM", { value: 2, //该属性本身不受 configurable 的影响,但由于属性不可写,受 writable 的限制 writable: true, //错误!属性不可配置 configurable: true, //错误!属性不可配置 enumerable: true //错误!属性不可配置 });
但是 configurable 的限制有一个特例,就是 writable 可以由 true 改为 false,不能由 false 改为 true:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, writable: true, //设置可写 configurable: false, //设置属性不可配置 enumerable: false //设置不可枚举 }); Object.defineProperty(CONST, "NUM", { value: 2, //该属性本身不受 configurable 的影响,由于属性可写,修改成功 writable: false, configurable: false, enumerable: false }); console.log(CONST.NUM); //2 CONST.NUM = 0; //错误!属性只读
可枚举描述符用于配置属性是否可以枚举,也就是是否会出现在 for ... in ... 语句中:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, writable: false, configurable: false, enumerable: true //可枚举 }); Object.defineProperty(CONST, "NUM", { value: 2, writable: false, configurable: false, enumerable: false //不可枚举 }); for (var key in CONST) { console.log(CONST[key]); //1 };
有了以上的基础,我们也就学会一种定义常量的方法,使用属性的数据描述符,下次我们需要用到常量的时候,就可以定义一个 CONST 命名空间,将常量封装在该命名空间里面,由于属性描述符默认为 false,所以我们也可以这样定义:
var CONST = {}; Object.defineProperty(CONST, "NUM", { value: 1, enumerable: true }); Object.defineProperty(CONST, "NUM", { value: 2, enumerable: true });
(2)ES6中常量的定义
const NUM = 1 console.log(NUM) NUM = 2; //错误,属性为只读