目录
1. 原型链继承:
2. 构造继承:在子类的构造函数中调用父类函数
3. 组合继承:
4. 寄生组合式继承:
子类构造函数的原型对象指向父类构造函数的实例
缺点: 1.子类的实例会共享父类的引用类型的属性
2. 调用父类方法的时候无法向父类传递参数
// 父类
function SuperClass() {
// 引用属性
this.books = ['javaScript', 'css世界', 'html'];
// 普通属性
this.superValue = true;
}
SuperClass.prototype.getBooks = function() {
return this.books;
}
// 子类
SuperClass.prototype.superName = 'super';
function SubClass(name) {
this.name = name
this.subValue = false;
}
SubClass.prototype = new SuperClass();
// 子类自己的方法
SubClass.prototype.getSubValue = function() {
return this.subValue;
}
// 测试例子
var instance1 = new SubClass('instance1');
var instance2 = new SubClass('instance2');
console.log(instance1.books); //["javaScript", "css世界", "html"]
console.log(instance2.books); //["javaScript", "css世界", "html"]
instance1.books.push('数据结构');
console.log(instance1.books); //["javaScript", "css世界", "html", "数据结构"]
console.log(instance2.books); //["javaScript", "css世界", "html", "数据结构"]
// instanceof 判断一个对象是否是一个类的实例,或一个对象是否继承一个类
console.log(instance1 instanceof SubClass); // true
console.log(instance1 instanceof SuperClass); // true
console.log(SubClass instanceof SuperClass); // false
console.log(SubClass.prototype instanceof SuperClass); // true
console.log(instance1.superName); //super
缺点: 1. 无法继承父类的原型属性和原型方法
优点: 1. 解决了原型继承中子类实例共享父类引用属性的问题; 2. 调用父类构造函数时无法传递参数的问题
*/
// 父类
function SuperClass(id) {
// 引用属性
this.books = ['javaScript', 'css世界', 'html'];
// 普通属性
this.superValue = true;
this.id = id;
}
SuperClass.prototype.getBooks = function() {
return this.books;
}
SuperClass.prototype.name = 'super'
// 子类
function SubClass(id) {
this.subValue = false;
SuperClass.call(this, id);
}
// 测试例子
var instance1 = new SubClass('instance1')
var instance2 = new SubClass('instance2')
console.log(instance1.books); //["javaScript", "css世界", "html"]
console.log(instance2.books); //["javaScript", "css世界", "html"]
console.log(instance2.getBooks); //undefined
console.log(instance2.superName); //undefined
instance1.books.push('数据结构');
console.log(instance1.books); //["javaScript", "css世界", "html", "数据结构"]
console.log(instance2.books); //["javaScript", "css世界", "html"]
console.log(instance1.id); //instance1
console.log(instance2.id); //instance2
/*
原型继承+构造继承(即在子类的构造函数中执行父类构造函数,将子类的原型对象指向为父类的实例)
优点: 1. 可以向父类构造函数中传递参数; 2. 子类的实例不会共享父类的引用属性; 3. 子类可以继承父类的原型属性和原型方法
缺点:父类构造函数执行了两次
// 父类
function SuperClass(name) {
this.name = name;
this.books = ['javaScript', 'CSS世界', 'html布局大全'];
}
// 父类原型方法
SuperClass.prototype.getName = function() {
return this.name;
}
SuperClass.prototype.superValue = true;
// 子类
function SubClass(name, price) {
SuperClass.call(this, name); //第二次调用父类构造函数(在新对象上创建了实例属性,会屏蔽掉原型上同名的属性)
this.price = price;
}
SubClass.prototype = new SuperClass(); //第一次调用父类构造函数(此时父类的实例属性和原型属性均会在子类的原型上)
// 修改子类的原型对象破坏了constructor属性,所以对constructor重新赋值
SubClass.prototype.constructor = SubClass;
// 测试例子
var instance1 = new SubClass('instance1', 65.6);
console.log(instance1.getName()); //instance1
console.log(instance1.books); //["javaScript", "CSS世界", "html布局大全"]
instance1.books.push('数据结构');
console.log(instance1.books); //["javaScript", "CSS世界", "html布局大全", "数据结构"]
console.log(instance1.superValue); //true
var instance2 = new SubClass('instance2', 86.8);
console.log(instance2.getName()); //instance2
console.log(instance2.books); //["javaScript", "CSS世界", "html布局大全"]
console.log(instance2.superValue); //true
/*
寄生式继承 + 构造继承
优点: 1. 父类构造函数只需要执行一次;2. 解决父类实例属性即在子类的原型上存在,又在子类的实例属性上存在;
// 创建一个空的过渡函数,让其继承父类构造函数,并返回过渡函数的一个实例
// 目的: 用于继承父类原型属性和原型方法
function inheriteObject(obj) {
function F() {}
F.prototype = obj;
return new F();
}
/*
寄生式继承,继承原型
**/
function inheritPrototype(subClass, superClass) {
var p = inheriteObject(superClass.prototype);
// 原本的 p.constructor === SuperClass
p.constructor = subClass;
subClass.prototype = p;
}
// 父类
function SuperClass(name) {
this.name = name;
this.books = ['javaScript','css世界','html布局大全'];
}
SuperClass.prototype.getName = function() {
return this.name;
}
// 子类
function SubClass(name, price) {
// 构造函数式继承,(继承父类的实例属性和实例方法)
SuperClass.call(this, name);
this.price = price;
}
inheritPrototype(SubClass, SuperClass);
// 测试例子
var instance1 = new SubClass('css世界', 45)
console.log(instance1.books); //["javaScript", "css世界", "html布局大全"]
instance1.books.push('数据结构与算法')
console.log(instance1.books); // ["javaScript", "css世界", "html布局大全", "数据结构与算法"]
var instance2 = new SubClass('javaScript设计模式', 55)
console.log(instance2.books); //["javaScript", "css世界", "html布局大全"]