起因:
最近在看vue的监听机制时,遇到了Object.defineProperty这个方法,在MDN上是这样写的:
Object.defineProperty(obj, prop, descriptor)方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
既然是改变对象的属性的,那平时写代码时,也不见大家用呀,反正我平时都是这样写的:
let obj = {
a: '111',
b: '222'
};
obj.aaa = '333'; // 修改属性
obj.ccc = '444'; // 添加属性
console.log(obj); // {a: "111", b: "222", aaa: "333", ccc: "444"}
思考:
那两种方式有什么区别呢?
探究:
MDN上还说了,该方法允许精确地添加或修改对象的属性。那么何谈精确呢?
那就要说到Object.defineProperty的几个属性了:
configurable
:当且仅当该属性为true
时,该属性的描述符descriptor
才能够被改变,同时该属性也能从对应的对象上被删除,默认为false
。enumerable
:当且仅当该属性为true
时,该属性才会出现在对象的枚举属性中,默认为false
。value
:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等),默认为 undefibed。writable
:当且仅当该属性为true
时,属性的值,也就是上面的value
,才能被赋值运算符改变,默认为false
。
主要区别:
如果用赋值运算符 = 赋值,这些属性是不能设置的,默认为:
- 使用 = 添加或删除修改的属性,默认是在属性枚举期间显示的属性(用for...in 或 Object.keys 方法可以遍历到),即
enumerable 为 true。
- 这些值也是可以被改变、删除的,即
writable 为true
。
下面是一个简单的小实践:
// 用赋值法创建一个对象
let obj = {
a: '111',
b: '222'
};
// 用赋值法添加一个属性
obj.c = '333';
// 用Object.defineProperty添加一个对象,不可修改,属性不会出现在对象的枚举属性
Object.defineProperty(obj, "d", {
value : '444',
writable : false,
enumerable : false,
configurable : false
});
console.log(Object.keys(obj)); // ["a", "b", "c"],没有d