博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Javascript之继承(其他方式)
阅读量:7070 次
发布时间:2019-06-28

本文共 5464 字,大约阅读时间需要 18 分钟。

1.借用构造函数
在解决原型中包含引用类型值所带来的问题的过程中,我们可以使用一种叫借用构造函数的技术(又称伪造对象或经典继承)。就是在
子类型构造函数的内部调用父类型构造函数,记住,函数只不过是在特定环境中执行代码的对象,可以通过使用apply()和call()方法也可以在(将来)新创建的对象上执行构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function
SuperType(){
    
this
.colors=[
"red"
,
"blue"
,
"green"
];
    
}
      
function
SubType(){
    
//继承了SuperType
    
SuperType.call(
this
);
}
  
var
instance=
new
SubType();
instance.colors.push(
"black"
);  
//"red","blue","green","black"
alert(instance.colors);
  
var
instance2=
new
SubType();
alert(instance2.colors);         
//"red","blue","green"

将SuperType构造函数放到SubType的执行环境中,这样一来,就会在新SubType对象上执行SuperType()函数中定义的所有对象初始化代码,结果,SubType的每一个实例都有一份具有自己colors属性的副本。

(1)传递参数

借用构造函数可以在子类型构造函数中向父类型构造函数传递参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function
SuperType(name){
    
this
.name=name;
    
}
      
function
SubType(){
    
//继承了SuperType,同时传递参数
    
SuperType.call(
this
,
"zxj"
);
      
    
//实例属性
    
this
.age=29;
    
}
  
var
instance=
new
SubType();
alert(instance.name);         
//zxj
alert(instance.age);         
//29

(2)借用构造函数的问题

如果仅仅使用借用构造函数,那么将无法避免构造函数模式存在的问题——方法都在构造函数中定义,函数的复用也无从谈起。所以借用构造函数也很少单独使用。

2.组合继承

组合继承(伪经典继承),指的是将原型链和借用构造函数的技术组合在一块。其思路是使用原型链对原型属性和方法的继承,而通过借用构造函数来实现对实例对象的继承

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
27
28
29
30
31
32
function
SuperType(name){
    
this
.name=name;
    
this
.colors=[
"red"
,
"blue"
,
"green"
];
    
}
      
SuperType.prototype.sayName=
function
(){
    
alert(
this
.name);
    
}
  
function
SubType(name,age){
    
//继承属性
    
SuperType.call(
this
,name);
    
this
.age=age;
}
  
SubType.prototype=
new
SuperType();
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=
function
(){
    
alert(
this
.age);
    
}
  
  
var
instance=
new
SubType(
"zxj"
,29);
instance.colors.push(
"black"
);   
alert(instance.colors);             
//"red","blue","green","black"
instance.sayName();                 
//zxj
instance.sayAge();                  
//29     
  
var
instance2=
new
SubType(
"Greg"
,28);
alert(instance.colors);             
//"red","blue","green","black"
instance2.sayName();                
//Greg    
instance2.sayAge();                 
//28

组合继承避免了原型链和借用构造函数的缺陷,融合了他们的有点,成为JavaScript中追尾常用的继承模式。而且,instanceof和isPrototypeof()也能够用于识别组合继承创建的对象。

3.原型式继承

​借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

1
2
3
4
5
function
object(o){
    
function
F(){};
    
F.prototype=o;
    
return
new
F();
}

在object()函数内部,先创建一个临时性的构造函数,然后将传入的对象作为该构造函数的原型,最后返回这个临时类型的一个新实例。本质上讲,object()对传入其中的对象进行了一次浅复制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function
object(o){ 
    
function
F(){}; 
    
F.prototype=o; 
    
return
new
F(); 
}
var
person={
    
name:
"zxj"
,
    
friends:[
"Shelby"
,
"Court"
,
"Van"
]
};
  
var
anotherPerson=object(person);
antherPerson.name=
"Greg"
;
anotherPerson.friends.push(
"Rob"
);
  
var
yetAnotherPerson=object(person);
yetAnotherPerson.name=
"Linda"
;
yetAnotherPerson.friends.push(
"Brabie"
);
  
alert(person.friends);
//"Shelby,Court,Van,Rob,Brabie"

但包含引用类型值的属性始终后悔共享相应的值,这和原型模式一样的。

4.寄生式继承

寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式类增强对象,最后再像真的是它做了所有工作一眼放回对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function
creteAnother(original){
    
var
clone=object(original);  
//通过调用函数创建一个新对象
    
clone.sayHi=
function
(){      
//以某个方式来增强这个对象
        
alert(
"hi"
);
    
}
    
return
clone;                
//返回这个对象          
}
  
var
person={
    
name:
"zxj"
,
    
friends:[
"Shelby"
,
"Court"
,
"Van"
]
};
  
var
anotherPerson=createAnother(person);
anotherPerson.sayHi(); 
//"hi"

使用寄生式来为对象添加函数,会由于不能做到函数服用而降低效率。

5.寄生组合式继承

 组合继承是JavaScript中最常用的继承模式,但它无论在什么情况下,都会调用两次父类型构造函数:一次在创建子类型原型时,一种在子类型构造函数内部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function SuperType(name){
    
this.name=name;
    
this.colors=[
"red"
,
"blue"
,
"green"
];
    
}
function SubType(name,age){
    
//继承属性
    
SuperType.call(this,name); //第二次调用父类型
    
this.age=age;
}
  
SubType.
prototype
=new SuperType();  //第一次调用父类型
SubType.
prototype
.constructor=SubType;
SubType.
prototype
.sayAge=function(){
    
alert(this.age);
    
}

第一次调用父类型时,SubType.prototype会得到两个属性:name和colors;他们都是SuperType的实例属性,只不过位于SubType的原型中。带调用SubType构造函数时,有一次调用了SuperType构造函数,这一次是在新对象上创建实例属性name和colors,于是这两个属性就屏蔽掉了原型中的两个同名属性,调用过程如图所示。

22202125-f682ba5b510a456399c396a8334ad548.png 

这样就有两组name和colors属性:一组在实例上,一组在SubType的原型中,这就是调用两次SuperType构造函数的结果。

当然,我们可以通过寄生组合是继承来解决这问题,所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链来继承方法。思路:不必为了指定子类型的原型而调用父类型的构造函数,我们只需父类型原型的一个副本。本质上,就是使用寄生式继承来继承父类型的原型,然后将结果指定给子类型的原型,寄生组合式继承的基本模式如下: 

1
2
3
4
5
function
inheritPrototype(subType,superType){
   
var
prototype=object(superType.prototype);  
//创建对象
    
prototype.constructor=subTyoe;             
//增强对象
    
subType.prototype=prototype;               
//指定对象
}

 示例中inheritPrototype()函数实现了寄生组合式继承的最简单形式。这个函数接收两个参数:子类型构造函数和父类型构造函数。在函数内部:第一步是创建父类型原型的一个副本。第二步是为创建的副本调价constructor属性,从而弥补因重写原型而失去默认的constrcutor属性。最后一步,将新创建的对象(即副本)赋值给子类型的原型。这样,我就可以调用inheritPrototype()函数的语句,去替换前面例子中为子类型原型赋值的语句。

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function
object(o){
          
function
F(){}
          
F.prototype = o;
          
return
new
F();
      
}
    
      
function
inheritPrototype(subType, superType){
          
var
prototype = object(superType.prototype);  
//create object
          
prototype.constructor = subType;              
//augment object
          
subType.prototype = prototype;                
//assign object
      
}
                                
      
function
SuperType(name){
          
this
.name = name;
          
this
.colors = [
"red"
,
"blue"
,
"green"
];
      
}
        
      
SuperType.prototype.sayName =
function
(){
          
alert(
this
.name);
      
};
 
      
function
SubType(name, age){  
          
SuperType.call(
this
, name);
            
          
this
.age = age;
      
}
 
      
inheritPrototype(SubType, SuperType);
        
      
SubType.prototype.sayAge =
function
(){
          
alert(
this
.age);
      
};
        
      
var
instance1 =
new
SubType(
"Nicholas"
, 29);
      
instance1.colors.push(
"black"
);
      
alert(instance1.colors); 
//"red,blue,green,black"
      
instance1.sayName();     
//"Nicholas";
      
instance1.sayAge();      
//29
        
       
      
var
instance2 =
new
SubType(
"Greg"
, 27);
      
alert(instance2.colors); 
//"red,blue,green"
      
instance2.sayName();     
//"Greg";
      
instance2.sayAge();      
//27

 

转载地址:http://zhqll.baihongyu.com/

你可能感兴趣的文章
在Kubernetes中运行Spark集群
查看>>
VMware Horzion Workspace POC文档--安装2(集成VIEW)
查看>>
浅谈HDFS的读流程
查看>>
【探索】VS下虚继承实现的方法-1
查看>>
Java基础加密之MD5加密算法
查看>>
盛夏光年
查看>>
Android 沉浸式状态栏(像IOS那样的状态栏与应用统一颜色样式)
查看>>
RHCS集群服务 7.10
查看>>
windows 使用vnc图形化界面远程连接阿里云ubuntu 16.04云服务器
查看>>
linux和CentOS是什么关系;CentOS和RHEL是什么关系
查看>>
samba
查看>>
利用Python网络爬虫抓取微信好友的签名及其可视化展示
查看>>
Linux-Nginx代理
查看>>
计算机的系统组成简介---运维笔记
查看>>
Liunx nginx 的使用方法及模块
查看>>
DBA——表级数据恢复之路(一) 请下载附件查看
查看>>
自定义弹出框
查看>>
如何扩展ESXi虚拟机磁盘容量
查看>>
sqlserver 登录方式修改,由默认的windows账户改为用sa等sql server账户登录
查看>>
Apache+tomcat 快速部署Java环境
查看>>