js里对象的属性有三个特性:
1. writable,就是这个属性能不能被修改。
2. enumerable,用for...in遍历的时候,这个属性出不出现。
3. configurable,这属性的配置能不能改,能不能被delete删掉。
ES3的时候这三个默认都是true,新建的属性都能写、能枚举、能删。
到了ES5,可以用property descriptor来设置这些特性了。
如果把值也算成一个属性,那其实每个属性有四个特征:value、writable、enumerable、configurable。
还有一种是用getter和setter定义的属性,这种没有writable(能不能写看有没有setter),但它也有四个特性:get、set、enumerable、configurable,其中get和set是函数。
怎么获取属性的这些信息?
ES5提供了Object.getOwnPropertyDescriptor()这个方法:
js
var o = {x:1};
var a = Object.create(o);
a.y = 3;
console.log(Object.getOwnPropertyDescriptor(a, y)); // {configurable: true, enumerable: true, writable: true, value: 3}
console.log(Object.getOwnPropertyDescriptor(a, x)); // undefined
注意啊,要是属性不存在,或者是从原型链上继承来的,返回的就是undefined。
那怎么改属性的特性?
用Object.defineProperty():
js
Object.defineProperty(a, y, {
value: 3,
writable: true,
enumerable: false,
configurable: true
});
console.log(a.propertyIsEnumerable(y)); // false
这里把y设成不可枚举了,for...in就遍历不出来了。
还有一个坑:如果你要define的属性是继承来的,比如x是从o继承的,那你用defineProperty会给a自己加一个同名属性,相当于覆盖了继承的那个,这点跟直接赋值行为一样。
举个例:
js
Object.defineProperty(a, x, {
value: 1,
writable: true,
enumerable: true,
configurable: true
});
// 现在a自己有个x了,不再是继承的
1. writable,就是这个属性能不能被修改。
2. enumerable,用for...in遍历的时候,这个属性出不出现。
3. configurable,这属性的配置能不能改,能不能被delete删掉。
ES3的时候这三个默认都是true,新建的属性都能写、能枚举、能删。
到了ES5,可以用property descriptor来设置这些特性了。
如果把值也算成一个属性,那其实每个属性有四个特征:value、writable、enumerable、configurable。
还有一种是用getter和setter定义的属性,这种没有writable(能不能写看有没有setter),但它也有四个特性:get、set、enumerable、configurable,其中get和set是函数。
怎么获取属性的这些信息?
ES5提供了Object.getOwnPropertyDescriptor()这个方法:
js
var o = {x:1};
var a = Object.create(o);
a.y = 3;
console.log(Object.getOwnPropertyDescriptor(a, y)); // {configurable: true, enumerable: true, writable: true, value: 3}
console.log(Object.getOwnPropertyDescriptor(a, x)); // undefined
注意啊,要是属性不存在,或者是从原型链上继承来的,返回的就是undefined。
那怎么改属性的特性?
用Object.defineProperty():
js
Object.defineProperty(a, y, {
value: 3,
writable: true,
enumerable: false,
configurable: true
});
console.log(a.propertyIsEnumerable(y)); // false
这里把y设成不可枚举了,for...in就遍历不出来了。
还有一个坑:如果你要define的属性是继承来的,比如x是从o继承的,那你用defineProperty会给a自己加一个同名属性,相当于覆盖了继承的那个,这点跟直接赋值行为一样。
举个例:
js
Object.defineProperty(a, x, {
value: 1,
writable: true,
enumerable: true,
configurable: true
});
// 现在a自己有个x了,不再是继承的
