js面向对象继承浅析

前言

js中实现继承的方式只支持实现继承,即继承实际的方法,而实现继承主要是依靠原型链来完成的。

原型链式继承

该方式实现的本质是重写原型对象,代之以一个新类型的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function SuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function(){
return this.property;
}
function SubType(){
this.subproperty=false;
}
SubType.prototype = new SuperType();//继承
SubType.prototype.getSubValue=function(){//额外添加方法
return this.subproperty;
}
var s = new SubType();
console.log(s.getSubValue());//false
console.log(s.getSuperValue());//true

借用纯原型链的问题:如果原型中包含引用类型的值,则实例间对该值的修改会相互影响,这不是我们希望看到的。

借用构造函数

该方式的基本思想是在子类型的构造函数的内部调用超类型构造函数(父函数)

1
2
3
4
5
6
7
8
9
10
11
12
function SuperType(){
this.color=['green','red','black'];
}
function SubType(){
SuperType.call(this)//改变执行环境 实现继承
}
var s = new SubType();
s.color.push('pink');
console.log(s.color);//[ 'green', 'red', 'black', 'pink' ]
var s1 = new SubType();
console.log(s1.color);//[ 'green', 'red', 'black' ]

构造函数的问题:方法都在构造函数内部定义,则函数复用无从谈起。

组合继承

基本思路是使用原型链来实现对原型属性和方法的继承,通过构造函数实现实例属性的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function SuperType(name){
this.name=name;
this.color=['green','red','black'];
}
SuperType.prototype.show=function(){
console.log(this.name,this.color);
}
function SubType(name,age){
SuperType.call(this,name)//改变执行环境 实现实例属性继承
this.age=age;
}
SubType.prototype = new SuperType();//原型属性和方法继承
var s = new SubType('谦龙',100);
s.show();//谦龙 ["green", "red", "black"]
var s = new SubType('雏田',14);
s.show();//雏田 ["green", "red", "black"]

原型式继承

该方法的特点是借助原型可以基于一个已有的对象创建新的对象,同时还不比因此创建自定义类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function object(obj){
function F(){};
F.prototype=obj;
//F.prototype.constructor=F; 有需要还可以修改constructor指向
return new F();
}
var person={
name:'谦龙',
color:['red','green','black']
}
var p1 = object(person);
p1.color.push('pink');
var p2 = object(person);
p2.color.push('grey');
console.log(person.color);//["red", "green", "black", "pink", "grey"]

ES5中的Object.creat()与该方式的行为相同

寄生式继承

该方式的思路是创建一个仅用来封装继承过程的函数,该函数在内部以某种方式来增强对象,最后将该对象返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function object(obj){
function F(){};
F.prototype=obj;
//F.prototype.constructor=F; 有需要还可以修改constructor指向
return new F();
}
function CObject(obj){
var clone=object(obj);
clone.sayHi=function(){
alert('HI');
}
return clone;
}
var person={
name:'谦龙',
color:['red','green','black']
}
var s = CObject(person);
s.sayHi();

寄生组合式继承

思路是通过借用构造函数来继承属性,通过原型链的混合形式来继承方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function SuperType(name){
this.name=name;
this.color=['green','red','black'];
}
SuperType.prototype.show=function(){
console.log(this.name,this.color);
}
function SubType(name,age){
SuperType.call(this,name)//改变执行环境 实现继承
this.age=age;
}
function object(obj){
function F(){};
F.prototype=obj;
//F.prototype.constructor=F; 有需要还可以修改constructor指向
return new F();
}
function inheritPrototype(subType,superType){
var prototype=object(superType.prototype);
prototype.constructor=subType;
subType.prototype=prototype;
}
inheritPrototype(SubType,SuperType);
var s = new SubType('谦龙',100);
s.show();//谦龙 ["green", "red", "black"]

拷贝继承

该方法思路是将另外一个对象的属性和方法拷贝至另一个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function deepCopy(obj){
if(typeof obj !='object'){
console.trace();
return obj;
}
var newObj={};
for(var attr in obj){
newObj[attr]=typeof obj[attr]=='object'?deepCopy(obj[attr]):obj[attr];//使用递归
}
return newObj;
}
var obj={
name:'min',
age:20,
sex:'boy',
json:{
name2:'huihui',
json3:{
name3:'yahui'
}
}
}
var newObj=deepCopy(obj);
console.log(newObj);

图片描述