最近看到了关于js继承的一些东西,在此做个记录,方便日后查阅。
1.属性拷贝继承
解释:就是将对象成员复制一份给需要继承的对象
例子:
//使用对象字面量的方式创建一个对象
var fatherobj={
name:'xiaoli',
age:'18',
showName:function () {
console.log(this.name);
}
};
//创建一个需要继承的子对象
var subObj={};
//属性拷贝
for(var i in fatherobj){
subObj[i]=fatherobj[i];
}
console.log("fatherObj",fatherobj);
console.log("subObj",subObj);
缺点:如果继承过来的成员是引用类型的话,那么这个引用类型的成员在父对象和子对象之间是共享的,也就是说修改了之后, 父子对象都会受到影响
2. 原型式继承
这是一种借用构造函数的原型对象实现继承的方法
例:
SubClass.prototype = SuperClass.prototype;
存在的问题: 父构造函数的原型对象和子构造函数的原型对象上的成员有共享问题, 只能继承父构造函数的原型对象上的成员, 不能继承父构造函数的实例对象的成员
3. 原型链继承
即
子构造函数.prototype = new 父构造函数()
//构造父构造函数
function SuperClass() {
this.name='xiaoli';
this.age=18;
this.showName=function () {
console.log(this.name);
}
}
//设置父构造函数的原型
SuperClass.prototype.langeage=['chinese'];
SuperClass.prototype.showAge=function () {
console.log(this.age);
};
//子构造函数
function SubClass() {
}
//继承的实现
SubClass.prototype=new SuperClass();
// 修改子构造函数的原型的构造器属性
SubClass.prototype.constructor = SubClass;
//实例化一个对象
var p1=new SubClass();
console.log(p1.langeage);
console.log(p1.name);
p1.showAge();
//此时我们改变home的时候,父构造函数的原型对象也会变化
p1.langeage.push('english');
console.log(p1.langeage);
var p2=new SubClass();
console.log(p2.langeage);
问题:不能给父构造函数传递参数,父子构造函数的原型对象之间有共享问题
4.构造函数实现的继承
使用call和apply借用其他构造函数的成员, 可以解决给父构造函数传递参数的问题, 但是获取不到父构造函数原型上的成员.也不存在共享问题
//创建父构造函数
function Person(name) {
this.name=name;
this.sex=['boy','girl'];
this.showName=function () {
console.log(this.name);
}
}
//创建子构造函数
function Student(name) {
//使用call来借用Person的构造函数
Person.call(this,name);
}
//测试
var stu1=new Student("xiaoli");
stu1.showName();
5. 组合继承
使用
构造函数 + 原型式继承
//创建父构造函数
function Person(name) {
this.name=name;
this.sex=['boy','girl'];
this.showName=function () {
console.log(this.name);
}
}
//设置父构造函数的原型对象
Person.prototype.showSex=function () {
console.log(this.sex);
};
//创建子构造函数
function Student(name) {
//使用call来借用Person的构造函数
Person.call(this,name);
}
// 实现继承
Student.prototype=Person.prototype;
Student.prototype.constructor=Student;
//测试
var stu1=new Student("xiaoli");
stu1.showName();
stu1.showSex();
6. 构造函数 + 深拷贝
function deepCopy(obj1, obj2) {
for (var key in obj2) {
// 判断是否是obj2上的实例成员
if (obj2.hasOwnProperty(key)) {
// 判断是否是引用类型的成员变量
if (typeof obj2[key] == 'object') {
obj1[key] = Array.isArray(obj2[key]) ? [] : {};
deepCopy(obj1[key], obj2[key]);
} else {
obj1[key] = obj2[key];
}
}
}
}
//创建父构造函数
function Person(name) {
this.name=name;
this.sex=['boy','girl'];
this.showName=function () {
console.log(this.name);
}
}
//设置父构造函数的原型对象
Person.prototype.showSex=function () {
console.log(this.sex);
};
//创建子构造函数
function Student(name) {
//使用call来借用Person的构造函数
Person.call(this,name);
}
// 使用深拷贝实现继承
deepCopy(Student.prototype,Person.prototype);
Student.prototype.constructor=Student;
//测试
var stu1=new Student("xiaoli");
stu1.showName();
stu1.showSex();