js继承的几种方法和es6继承方法
一、原型链继
1.基本思想
利用原型链来实现继承,超类的一个实例作为子类的原型
2、具体实现
1 function F() {} 2 //原型属性,原型方法: 3 F.prototype.name="drago";
4 F.prototype.age=33; 5 F.prototype.run=function(){ 6 return this.name+" "+this.age+" running"; 7 } 8 var f = new F(); 9 console.log(f.name);//Lee 10 console.log(f.run());//Lee 33 running
3.优缺点
1)优点
简单明了,容易实现
实例是子类的实例,实际上也是父类的一个实例
父类新增原型方法/原型属性,子类都能访问到
2)缺点
所有子类的实例的原型都共享同一个超类实例的属性和方法
无法实现多继承
在创建子类的实例时 不能向父类的构造函数传递参数
二、构造函数继承
1。基本思想
通过使用call、apply方法可以在新创建的对象上执行构造函数,用父类的构造函数来增加子类的实例
2、具体实现
1 function F() { 2 // 属性 3 this.name = 'dragon'; 4 // 实例方法 5 this.sleep = function(){ 6 console.log(this.name + '正在睡觉!'); 7 } 8 } 9 function C(name){ 10 F.call(this);//1 11 this.name = name || 'Tom'; 12 //F.call(this); //2 13 } 14 var c=new C() 15 console.log(c.name);//1 Tom 2 dragon 16 console.log(c.sleep());//1 Tom正在睡觉! 2 dragon正在睡觉!
3.优缺点
1)优点
简单明了,直接继承超类构造函数的属性和方法
2)缺点
无法继承原型链上的属性和方法
三、实例继承
1.基本思想
为父类实例添加新特性,作为子类实例返回
具体实现
1 function F() { 2 // 属性 3 this.name = 'Animal'; 4 // 实例方法 5 this.sleep = function () { 6 console.log(this.name + '睡觉'); 7 } 8 } 9 10 function C(name) { 11 var instance = new F(); 12 instance.name = name || 'Tom'; 13 return instance; 14 } 15 16 var c = new C(); 17 console.log(c.name);//Tom 18 console.log(c.sleep());//Tom睡觉
特点:
1. 不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
1. 实例是父类的实例,不是子类的实例
2. 不支持多继承
四、组合继承
1.基本思想
利用构造继承和原型链组合
2.具体实现
1 function F() { 2 // 属性 3 this.name = 'dragon'; 4 // 实例方法 5 this.sleep = function () { 6 console.log(this.name + '正在睡觉!'); 7 8 } 9 10 } 11 12 function C(name) { 13 14 F.call(this);//构造函数继承 15 16 this.name = name || 'Tom'; 17 18 } 19 20 C.prototype = new F();//原型继承 21 22 var q = new C(); 23 24 console.log(q.name);//Tom 25 26 console.log(q.sleep());//Tom正在睡觉!
3.优缺点
1)优点
解决了构造继承和原型链继承的两个问题
2)缺点
实际上子类上会拥有超类的两份属性,只是子类的属性覆盖了超类的属性
五、原型式继承
1.基本思想
采用原型式继承并不需要定义一个类,传入参数obj,生成一个继承obj对象的对象
2、具体实现
1 var obj = { 2 3 name: "qw", 4 5 age: "12", 6 7 ada: "asd" 8 9 } 10 11 12 function F(o) { 13 function C() {} 14 C.prototype = o; 15 return new C(); 16 17 } 18 19 var q = F(obj) 20 21 console.log(q.name);//qw 22 23 console.log(q.age);//12
3.优缺点
1)优点:
直接通过对象生成一个继承该对象的对象
2)缺点:
不是类式继承,而是原型式基础,缺少了类的概念
六、寄生式继承
原型式+工厂模式
解决了组合继承两次调用构造函数的问题
1.基本思想
创建一个仅仅用于封装继承过程的函数,然后在内部以某种方式增强对象,最后返回对象
2、具体实现
//临时中转函数 function obj(o) { function F() {} F.prototype = o; return new F(); } //寄生函数 function create(o) { var q = obj(o); //可以对F进行扩展 q.sleep = function () { return this.name + "睡觉"; } return q; } var box = { name: 'dragon', age: 100, family: ['Dad', 'Mom', 'Sister'] }; var box1 = create(box); console.log(box1.name);//dragon console.log(box1.run());//dragon睡觉
3.优缺点
1)优点:
* 原型式继承的一种拓展
2)缺点:
* 依旧没有类的概念
七、寄生组合继承
通过调用构造函数来继承属性,通过原型链混成形式继承方法,与组合继承不同之处在于子类型只继承了超类型原型的一个副本,并未继承其构造函数。因此只需要调用一次超类型构造函数。
1.基本思想
结合寄生式继承和组合式继承,完美实现不带两份超类属性的继承方式
2.具体实现
//临时中转函数 function obj(o) { function F() { } F.prototype = o; return new F(); } //寄生函数 function create(subType, superType){ // var protoType = Object.create(superType.prototype); //创建对象 var protoType = obj(superType.prototype); //创建对象 protoType.constructor = subType; //增强对象 subType.prototype = protoType; //指定对象 } function Sup(name, age) { this.name = name; this.age = age; } Sup.prototype.run = function () { return this.name + " " + this.age + " running..." } function Sub(name, age) { Sup.call(this, name); this.age = age; } create(Sub,Sup);//替代D.prototype=new B(); Sub.prototype.sayAge = function(){ return this.name + " " + this.age + " Sub..." } var d= new Sub('dragon',100); console.log(d.run());//dragon 100 running... console.log(d.sayAge());//dragon 100 Sub...
3.优缺点
1)优点:
完美实现继承,解决了组合式继承带两份属性的问题
2)缺点:
过于繁琐,故不如组合继承
Es6. 继承
class father{ constructor(name){ this.name=name this.names=[1,2,3] } getname(){ console.log(this.name); } } class child extends father{ constructor(name){ super(name); } sayHello(){ console.log("Hello"); } static hh(){ console.log("hh") } } var cc=new child("dragon"); cc.sayHello();//Hello cc.getname(); //dragon child.hh(); //hh cc.names.push("wqwq"); var c1=new child("sasasa"); console.log(c1.names) //[1,2,3]
后续。。。。。。