属性描述对象是一个内部对象,无法直接读写,可以通过下面几个函数进行操作。
- Object.getOwnPropertyDescriptor():可以读出指定对象的私有属性的属性描述对象。
- Object.defineProperty():通过定义属性描述对象,来定义或修改一个属性,然后返回修改后的对象,具体用法可以参考22.3.1节内容。
- Object.defineProperties():可以同时定义多个属性描述对象。
- Object.getOwnPropertyNames():获取对象的所有私有属性。
- Object.keys():获取对象的所有本地可枚举的属性。
- propertyIsEnumerable():对象实例方法,直接调用,判断指定的属性是否可枚举。
【示例1】在下面示例中,定义obj的x属性允许配置特性,然后使用Object.getOwnPropertyDescriptor()函数获取对象obj的x属性的属性描述对象。修改属性描述对象的set函数,重设检测条件,允许非数值型数字,也可以赋值。
var obj = Object.create(Object.prototype, {
_x : { //数据属性
value : 1, //初始值
writable:true
},
x: { //访问器属性
configurable:true, //允许修改配置
get: function( ) { //getter
return this._x ; //返回_x属性值
},
set: function(value) { //setter
if(typeof value != "number" ) throw new Error('请输入数字');
this._x = value; //赋值
}
}
});
var des = Object.getOwnPropertyDescriptor(obj, "x"); //获取属性x的属性描述对象
des.set = function( value ){ //修改属性x的属性描述对象的set函数
//允许非数值型的数字,也可以进行赋值
if(typeof value != "number" && isNaN(value * 1) ) throw new Error('请输入数字');
this._x = value;
}
obj = Object.defineProperty( obj, "x", des);
console.log(obj.x); //1
obj.x = "2"; //把一个非数值型数字赋值给属性x
console.log(obj.x); //2
【示例2】下面示例先定义一个扩展函数,使用它可以把一个对象包含的属性,以及丰富的信息复制给另一个对象。
【实现代码】
function extend(toObj, fromObj) { //扩展对象
for (var property in fromObj) { //遍历对象属性
if (!fromObj.hasOwnProperty(property)) continue; //过滤掉继承属性
Object.defineProperty( //复制完整的属性信息
toObj, //目标对象
property, //私有属性
Object.getOwnPropertyDescriptor(fromObj, property) //获取属性描述对象
);
}
return toObj; //返回目标对象
}
【应用代码】
var obj = {}; //新建对象
obj.x = 1; //定义对象属性
extend(obj, { get y(){ return 2 } }) //定义读取器对象
console.log(obj.y); //2