JS实现继承的几种方式

一、借用构造函数

1 function Father(val){
2     this.val=val;
3     this.arr=[1];
4 }
5 function Child(val){
6     Father.call(this,val);      
7 }
8 var child1=new Child();
9 console.log(child1.val);

缺点:子类无法继承父类的原型对象,并没有真正的实现继承(部分继承)

如果给上述代码再添加几行:

 1 function Father(val){
 2     this.val=val;
 3     this.arr=[1];
 4     this.fun=function(){
 5         //....
 6     }
 7 }
 8 function Child(val){
 9     Father.call(this,val);      
10 }
11 var child1=new Child(1);
12 var child2=new Child(2);
13 child1.arr.push(2);
14 
15 console.log(child1.val);    //1
16 console.log(child2.val);    //2
17 
18 console.log(child1.arr);    //1,2
19 console.log(child2.arr);    //1
20 
21 console.log(child1.fun === child2.fun);   // false

上面代码中21行报错,是因为无法继承方法,每个子类实例都有一个新的方法,无法实现函数复用

二、原型链

 1 function Father(){    //父类            
 2     this.name='张三';
 3     this.arr=[1];
 4 }
 5 function Child(){       //子类
 6     this.type="hello"
 7 }
 8 Child.prototype=new Father();  //子类的原型等于父类的实例
 9 var child1=new Child();        //实例化一个子类对象
10 console.log(child1.name); 

缺点:原型对象的属性是共享的

如果给上述代码再添加几行:

 1 function Father(){    //父类            
 2     this.name='张三';
 3     this.arr=[1];
 4 }
 5 function Child(){       //子类
 6     this.type="hello"
 7 }
 8 Child.prototype=new Father();  //子类的原型等于父类的实例
 9 
10 var child1=new Child();        //实例化一个子类对象
11 var child2=new Child();        //实例化一个子类对象
12 child1.name='李四'
13 child1.arr.push(2);
14 
15 console.log(child1.name);    //李四
16 console.log(child2.name);    //张三
17 
18 console.log(child1.arr);     //1,2
19 console.log(child2.arr);     //1,2  

此时就出现了一个问题,第13行代码明明是给child1实例添加了属性,为什么第19行代码显示child2也拥有了该属性呢?这就是原型链继承所存在的问题,原型对象的属性是共享的。

三、组合式继承

原型继承+构造函数继承

 1 function Father(){      //父类
 2     this.val=1;         //只在此处声明父类属性
 3     this.arr=[1];
 4 }
 5 Father.prototype.sayHai=function(){    //只在此处声明父类方法
 6     //...
 7 }
 8 function Child(){
 9     Father.call(this);     //构造函数继承
10 }
11 Child.prototype=new Father();     //原型链继承
12 
13 var child1=new Child();
14 var child2=new Child();
15 
16 console.log(child1.sayHai==child2.sayHai);    //true
将实例方法放到原型对象里,以实现函数复用,同时还要保留借用构造函数方式的优点
优点:不存在属性共享问题,函数可复用
 缺点:父类构造函数被调用了两次,代码冗余
四、寄生组合继承
 
posted @ 2018-03-23 20:27  endlessmy  阅读(140)  评论(0编辑  收藏  举报