博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS继承之原型继承
阅读量:5024 次
发布时间:2019-06-12

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

 

 许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在ECMAScript中无法实现接口继承。ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的。  
                                             --摘自《JavaScript高级程序设计》

原型继承
原型链是实现原型继承的主要方法,基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法。
 
实现原型链的基本模式:
1
2
3
4
5
6
7
8
9
10
11
12
13
function
SuperType(){
 
this
.property=
true
;
}
 
SuperType.prototype.getSuperValue=
function
(){
  
return
this
.property;
}
 
function
SubType(){
  
this
.subproperty=
false
;
}
 
SubType.prototype=
new
SuperType();
1
SubType.prototype.getSubValue=
function
(){<br>
return
this
.property;<br> }
1
var
instance=
new
SubType();
1
instance.getSuperValue();
//true;

例子中的实例及构造函数和原型之间的关系图:

 

在例子代码中,定义了两个对象,subType和superType。

两个对象之间实现了继承,而这种继承方式是通过创建SuperType的实例并将该实例赋给subType.prototype实现的。实现的本质就是重写了原型对象

这样subType.prototype中就会存在一个指针指向superType的原型对象。也就是说,存在superType的实例中的属性和方法现在都存在于subType.prototype中了。这样继承了之后,又可以为subType添加新的方法和属性。

要注意,这个指针([[prototype]])默认情况下是不可以再被外部访问的,估计是会被一些内部方法使用的,例如用for...in来遍历原型链上可以被枚举的属性的时候,就需要通过这个指针找到当前对象所继承的对象。不过,Firefox、Safari和Chrome在每个对象上都支持一个属性__proto__。

原型继承需要注意的一些问题

1.别忘记默认的类型

我们知道,所有的引用类型都继承了Object,而这个继承也是通过原型链实现的。所以所有的对象都拥有Object具有的一些默认的方法。如

hasOwnProperty()propertyIsEnumerable()toLocaleString()toString()valueOf()。

2. 确定原型和实例的关系

可以通过两种方式来确定原型和实例之间的关系。

①使用instanceof 操作符,只要用这个操作符来测试实例与原型链中出现过的构造函数,结果就会返回true。

②第二种方式是使用isPrototypeOf()方法。同样,只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型,因此isPrototypeOf()方法也会返回true。

例子:

alert(instance instanceof Object); //truealert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true alert(Object.prototype.isPrototypeOf(instance)); //true alert(SuperType.prototype.isPrototypeOf(instance)); //true alert(SubType.prototype.isPrototypeOf(instance)); //true

③子类要在继承后定义新方法

因为,原型继承是实质上是重写原型对象。所以,如果在继承前就在子类的prototype上定义一些方法和属性。那么继承的时候,子类的这些属性和方法将会被覆盖。

如图:

④不能使用对象字面量创建原型方法

这个的原理跟第三点的实际上是一样的。当你使用对象字面量创建原型方法重写原型的时候,实质上相当于重写了原型链,所以原来的原型链就被切断了。

 

⑤注意父类包含引用类型的情况

如图:

这个例子中的SuperType 构造函数定义了一个colors 属性,该属性包含一个数组(引用类型值)。SuperType 的每个实例都会有各自包含自己数组的colors 属性。当SubType 通过原型链继承了SuperType 之后,SubType.prototype 就变成了SuperType 的一个实例,因此它也拥有了一个它自己的colors 属性——就跟专门创建了一个SubType.prototype.colors 属性一样。但结果是什么呢?结果是SubType 的所有实例都会共享这一个colors 属性。而我们对instance1.colors 的修改能够通过instance2.colors 反映出来。也就是说,这样的修改会影响各个实例。

原型继承的缺点(问题)

①最明显的就是上述第⑤点,有引用类型的时候,各个实例对该引用的操作会影响其他实例。

②没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。

 

有鉴于此,实践中很少会单独使用原型继承。

 

最近要回顾一下原生js的一些重要的基础知识点,秋招秋招。。。

 转载自:

转载于:https://www.cnblogs.com/lzbk/p/6263022.html

你可能感兴趣的文章
阿里架构师,讲述基于微服务的软件架构模式
查看>>
Eclipse导入maven项目时,Pom.xml文件报错处理方法
查看>>
01、JAVA开发准备
查看>>
asp.net mvc 错误处理 - 自定义报错处理,生成错误日志
查看>>
Linux centos ssh
查看>>
R语言之避免for循环示例
查看>>
[转]jQuery 选择器和dom操作
查看>>
Jenkins+Maven+SVN快速搭建持续集成环境(转)
查看>>
bootstrap 媒体查询
查看>>
杜教筛
查看>>
《Ext JS模板与组件基本知识框架图----模板》
查看>>
txmpp
查看>>
微信开发时调用jssdk,在安卓设备中成功调用;在ios设备中返回错误消息:config fail,无其他具体错误消息,且接口权限显示获取ok,无法调用...
查看>>
【Github教程】史上最全github使用方法:github入门到精通
查看>>
抽象工厂模式(Abstract Factory)
查看>>
luogu1373 小a和uim之大逃离 (dp)
查看>>
Redis的Pub/Sub客户端实现
查看>>
SQL日常问题和技巧——持续更新
查看>>
springMVC入门(一)------springMVC基本概念与安装
查看>>
Sam做题记录
查看>>