Js继承的实现方式
继承是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
原型链继承
通过将子类的原型对象指向父类的实例,实现继承访问父类属性方法等
// 定义父类
function Parent(){
this.name = "parent";
this.say = function(){
console.log(this.name);
}
}
// 定义子类
function Child(){
this.name = "child";
}
Child.prototype = new Parent(); // 将子类的原型对象指向父类的实例
Child.prototype.construce = Child; // 修复constructor使符合原型链规定
var child = new Child(); // 实例化子类
child.say(); // child // 此时子类能够访问父类的say方法,在查找name属性的时候首先在自身属性中查找成功所以不再向上查找,若子类没有name成员,则会打印parent
console.log(child instanceof Parent); // true // 判断child的构造函数Child的prototype对象是否在Parent的原型链上
特点
不足
构造函数继承
当子类构造函数被调用时,借助call
或者apply
调用父类构造方法实现对于this
的拓展
// 定义父类
function Parent(from){
this.name = "parent";
this.say = function(){
console.log(this.name);
}
this.from = from;
}
// 定义子类
function Child(from){
Parent.call(this,from); // 调用父类构造函数并绑定this来拓展Child实例成员方法,可以传递参数
this.name = "child";
}
var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child
特点
不足
实例继承
// 定义父类
function Parent(from){
this.name = "parent";
this.say = function(){
console.log(this.name);
}
this.from = from;
}
// 定义子类
function Child(from){
var instance = new Parent(from);
instance.name = "child";
return instance;
}
var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child
特点
不足
拷贝继承
// 定义父类
function Parent(from){
this.name = "parent";
this.say = function(){
console.log(this.name);
}
this.from = from;
}
// 定义子类
function Child(from){
var instance = new Parent(from);
for(let item in instance) Child.prototype[item] = instance[item];
this.name = "child";
}
var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child
特点
不足
原型式继承
通过共享原型对象实现继承
// 定义父类
function Parent(){}
Parent.prototype.name = "parent";
Parent.prototype.say = function(){ console.log(this.name); }
// 定义子类
function Child(from){
this.name = "child";
}
Child.prototype = Parent.prototype; // 共享原型
Child.prototype.construce = Child;
var child = new Child("child"); // 实例化子类
child.say(); // child
特点
不足
组合继承
组合原型链继承和借用构造函数继承,结合了两种模式的优点,传参和复用
// 定义父类
function Parent(from){
this.name = "parent";
this.say = function(){
console.log(this.name);
}
this.from = from;
}
// 定义子类
function Child(from){
Parent.call(this,from);
this.name = "child";
}
Child.prototype = new Parent();
Child.prototype.construce = Child;
var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child
特点
不足
寄生组合继承
通过寄生方式,砍掉父类的实例属性,在调用两次父类的构造的时候,就不会初始化两次实例方法和属性,避免的组合继承的缺点
// 定义父类
function Parent(from){
this.name = "parent";
this.say = function(){
console.log(this.name);
}
this.from = from;
}
// 定义子类
function Child(from){
Parent.call(this,from);
this.name = "child";
}
var f = function(){}; // 创建一个没有实例方法的类
f.prototype = Parent.prototype; // 浅拷贝父类原型
Child.prototype = new f(); // 实例化f,此时没有实例化方法调用,同时将原型链建立
Child.prototype.construce = Child;
var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child
特点
- 比较完善
不足
- 相对比较复杂
参考
https://www.jianshu.com/p/b76ddb68df0e
https://www.cnblogs.com/ranyonsue/p/11201730.html
https://www.cnblogs.com/humin/p/4556820.html#!comments
原文链接:https://www.f2er.com/js/992921.html