关于继承 (二)
非构造函数的继承
非构造函数的继承即对已经封装好的,而没有构造函数的对象进行继承,就像下面的两个对象:
var MyFriend = {
rel : 'friend',
toBefriend : function(){
alert('Hello?');
}
}
var BeautyPerson = {
name : 'qi',
sex : 'girl',
year : 22
}
如果我们想要让 BeatyPerson 继承 MyFriend 的属性和方法,这时候就需要利用非构造函数的继承。
object() 继承
object() 通过建立一个空的构造函数,重写子对象:
// 创建空构造函数 使父对象成为其原型对象
function object(o){
function F(){};
F.prototype = o;
return new F();
}
var BeautyPerson = object(MyFriend);
// 添加子对象属性
BeautyPerson.name = 'qi';
BeautyPerson.sex = 'girl';
BeautyPerson.year = 22;
console.log(BeautyPerson.rel) // friend
这种方式能够获取到父对象的原型链,继承的比较完备,但是它的缺点也是很明显的。对后面子对象的属性添加来说,它不能使用对象字面量的方式进行重写(对象字面量会指向新的对象)。更谈不上封装了。
拷贝
那我们只能执行另外的一种思路,即拷贝,也就是伪继承。拷贝可以分为浅拷贝和深拷贝。这里我们直接写深拷贝。深拷贝相对于浅拷贝来说就是完全复制对象属性中的值,防止拷贝指针,导致子对象对父对象篡改的可能性。而实现的方式也很简单,就是根据数据类型判断结果,递归调用浅拷贝。
function deepCopy(Super,Sub){
var Sub = Sub || {};
for(var key in Super){
if(typeof Super[key] === 'object'){
Sub[key] = (Super[key].constructor === Array) ? [] : {} ;
deepCopy(Super[key],Sub[key]);
}else{
Sub[key] = Super[key];
}
}
Sub.uber = Super;
return Sub;
}
BeautyPerson = deepCopy(MyFriend,BeautyPerson);
console.log(BeautyPerson);
BeautyPerson.toBefriend();
这种方式可以解决 object() 出现的封装问题,但是这种方法并没有继承父对象的原型链,而是将父对象所有的可遍历属性和方法进行拷贝。for in 遍历效率较低,当原型链较长的时候耗费时间严重。