1、知识储备:javascript
一、枚举属性名称的函数:java
(1)for...in:能够在循环体中遍历对象中全部可枚举的属性(包括自有属性和继承属性)数组
(2)Object.keys():返回数组(可枚举的自有属性)函数
(3)Object.getOwnPropertyNames():全部的自有属性学习
三、属性的特性:数据属性和存取器属性this
(1)数据属性:可写(writable) 可枚举(enumerable) 可配置(configurable) 值(value)es5
数据属性只有一个简单的值;spa
(2)存取器属性: 写入(set) 读取(get) 可枚举(enumerable) 可配置(configurable)对象
存取器属性不可写(即没有writable特性)。blog
属性有set方法,那这个属性是可写的,有get方法,那这个属性就是可读的。
四、定义属性特性的方法:Object.defineProperty(对象,属性,描述符对象)
五、获取属性的描述符对象:Object.getOwnPropertyDescriptor(对象,属性)
2、示例
一、根据for...in的用法,咱们能够写出模拟“继承”的方法:
<script type="text/javascript"> var child={}; var mother={ name:"zhangzhiying", lastAge:21, sex:"女" }; function extend(target,source){ for(var p in source){ target[p]=source[p]; } return target; } extend(child,mother); console.log(child); //Object {name: "zhangzhiying", lastAge: 21, sex: "女"} </script>
二、使用for in来循环遍历原型对象的属性,而后一一赋值给咱们的空对象,从而实现了“继承”。这个思路很正确,下面咱们来对以上示例进行改造:
<script type="text/javascript"> var child={}; var mother={ name:"zhangzhiying", lastAge:21, set age(value){ this.lastAge=value; }, get age(){ return this.lastAge+1; }, sex:"女" };
mother.age=15; //有set方法,具备可写性 function extend(target,source){ for(var p in source){ target[p]=source[p]; } return target; } extend(child,mother); console.log(child); //Object {name: "zhangzhiying", lastAge: 15, age: 16, sex: "女"} </script>
能够看到代码中使用了一对set,get;其中age是一个存取器属性。
运行的结果:一个不包含set,get的普通对象。
结论:for in实现的“继承”不处理set和get ,它把存取器属性(age)转换为一个静态的数据属性。
三、给mother对象设置数据属性
<script type="text/javascript"> var child={}; var mother={ name:"zhangzhiying", lastAge:21, set age(value){ this.lastAge=value; }, get age(){ return this.lastAge+1; }, sex:"女" }; Object.defineProperty(mother,"lastAge",{writable:false}); //把lastAge设置成了不可写 mother.age=15; //设置无效,由于lastAge的值不变,因此lastAge+1不变,即age不变 function extend(target,source){ for(var p in source){ target[p]=source[p]; } return target; } extend(child,mother); console.log(child); //Object {name: "zhangzhiying", lastAge: 21, age: 22, sex: "女"} child.lastAge=12; //结果显示lastAge改变,说明child.lastAge没有“继承”到mother.lastAge的特性,咱们再用getOwnPropertyDesriptor()方法确认一下
console.log(Object.getOwnPropertyDescriptor(child,"lastAge")); //Object {value: 12, writable: true, enumerable: true, configurable: true}
console.log(child); //Object {name: "zhangzhiying", lastAge: 12, age: 22, sex: "女"}
</script>
结论:要实现继承,咱们还须要解决的问题->“继承”属性特性。
四、完善版本
<script type="text/javascript">
var child={};
var mother={
name:"zhangzhiying",
lastAge:21,
set age(value){
this.lastAge=value;
},
get age(){
return this.lastAge+1;
},
sex:"女"
};
Object.defineProperty(mother,"lastAge",{writable:false});
mother.age=15;
function extend(target,source){ var names=Object.getOwnPropertyNames(source); //获取全部的属性名 for(var i=0;i<names.length;i++){ if(names[i] in target) continue; //若是这个属性存在,就跳过(原型继承中,若是自有属性和原型对象的属性重名,保留自有属性) var desc=Object.getOwnPropertyDescriptor(source,names[i]); //获取mother属性的描述符对象(即属性特性的集合,es5中用描述符对象来表示) Object.defineProperty(target,names[i],desc); //将mother的描述符对象给child的属性定义 } return target; }
extend(child,mother);
console.log(child);
child.lastAge=12;
console.log(Object.getOwnPropertyDescriptor(child,"lastAge"));
console.log(child);
</script>
最后的结果:
能够明显看到三次的打印,child“继承”到了set和get,lastAge数值没发生变化,writable也是false了。
总结:最近在看《javascript权威指南》,总结一点心得,有错误欢迎指正,共同窗习进步~