博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
原型链的理解
阅读量:5903 次
发布时间:2019-06-19

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

此贴用于记录原型链相关的一些东西。

函数都有prototype,对象都有__proto__,一个函数的prototype和一个对象的__proto__就是原型,原型其实也是一个对象。
一个函数的prototype和这个函数的示例对象的__proto__是同一个引用,即:

function A(){}let a = new A();console.log(a.__proto__ === A.prototype); //返回的是true

当调用某一个对象的方法的时候,如果找不到这个对象的方法,则会去找这个对象的原型里的方法,如果再找不到,则继续找原型的原型的方法,一直往上找,这个就是原型链,如果都找不到,则会报错。

在引入es6的extends之前,函数的继承就是通过原型来实现的。下面记录一下我理解的继承,下面的继承参考的是[JS继承的实现方式

][1],他那里有完整的继承方法。

一. 原型链继承

function A(name) {  this.name = name;  this.f1 = function () {    console.log(this.name + '正在做f1');  }}A.prototype.f2 = function () {  console.log(this.name + '正在做f2');}function B(name) {  this.name = name;}B.prototype = new A('');let b = new B('test');b.f1();b.f2();console.log(b.__proto__ === B.prototype); //trueconsole.log(b instanceof A);//trueconsole.log(b instanceof B);//true

优点:

1.简单,实现容易
2.能访问父类所有的方法和属性
3.实例是当前类的实例,也是父类的实例

缺点:

1.要给B的prototype新增方法必须要在 new A('');之后
2.无法实现多继承
3.没法向父类的构造函数传递参数

二. 构造继承

function A(name){  this.name = name;  this.f1 = function(){    console.log(this.name + '正在做f1');  }}A.prototype.f2 = function(){  console.log(this.name + '正在做f2');}function B(name) {  A.call(this, name);}let b = new B('test');b.f1();// b.f2();// 会报错console.log(b instanceof A);//falseconsole.log(b instanceof B);//true

优点:

1.可以使用父类的属性和方法
2.可以实现多重继承,即可以call多个函数
3.实例对象是当前类的实例,不是父类的实例
缺点:
1.无法获取A的prototype的属性和方法
2.只是子类的实例,不是父类的实例
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能(此处应该是调用call的时候会生成父类的实例副本,具体的还得再研究研究)

三. 组合继承

function A(name){  this.name = name;  this.f1 = function(){    console.log(this.name + '正在做f1');  }}A.prototype.f2 = function(){  console.log(this.name + '正在做f2');}function B(name) {  A.call(this, name);}B.prototype = new A('');//要修正prototype的constructor,为什么要修正还有待研究B.prototype.constructor = B;let b = new B('test');b.f1();b.f2();console.log(b instanceof A);//trueconsole.log(b instanceof B);//true

优点:

1.包含了原型链继承和构造继承的优点
2.解决了原型链继承的无法实现多继承和没法向父类的构造函数传递参数的缺点
3.解决了构造继承无法获取A的prototype的属性和方法还有只是子类的实例,不是父类的实例的问题
缺点:
1.调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

四.寄生组合继承

function A(name){  this.name = name;  this.f1 = function(){    console.log(this.name + '正在做f1');  }}A.prototype.f2 = function(){  console.log(this.name + '正在做f2');}function B(name) {  A.call(this, name);}(function(){  // 创建一个没有实例方法的类  var Super = function(){};  Super.prototype = A.prototype;  //将实例作为子类的原型,这样就可以只获取A的prototype的属性了  B.prototype = new Super();  //  B.prototype.constructor = B;})();let b = new B('test');b.f1();b.f2();console.log(b instanceof A);//trueconsole.log(b instanceof B);//true

优点:

1.在组合继承的基础上,只生成了一份父类的实例,prototype也只继承了父类的prototype,没有继承私有的属性
缺点:
1.实现复杂

顺便加一个知识点,当使用new关键字来创建对象的时候,也用到了原型相关的知识,所以也记在了这里;

假设有一个function A(name){ this.name = name; };使用new关键字创建一个A的实例对象let a = new A();
new关键字主要做了以下几个步骤:
(1)创建一个空的对象
var obj = {};
(2)将这个对象的原型__proto__指向A的prototype
obj.__proto__ = A.prototype
(3)函数A的this指向obj;接着执行A函数
(4将obj返回,变量a指向obj

本文主要是参考了别人的文章,写一些自己的理解,如果有什么写错的地方欢迎大神来指正一下

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

你可能感兴趣的文章
Tomcat的设置4——Tomcat的体系结构与设置基于端口号的虚拟主机
查看>>
三种判断端口存活的方法和链接200的判断方法
查看>>
我的友情链接
查看>>
ftp协议基础
查看>>
顺时针打印矩阵
查看>>
JAXB
查看>>
端口聚合配置
查看>>
访问共享经常中断
查看>>
当你有一个锤子,你看什么都像钉子
查看>>
一个很实用的samba案例
查看>>
人生的交易
查看>>
TP5中关联模型的使用详解
查看>>
springMVC注解之入门
查看>>
不用花钱!Android模拟器让你在电脑上免费体验谷歌手机
查看>>
MySql
查看>>
算法分析与设计——贪心法实验报告
查看>>
js时间戳与日期格式的相互转换
查看>>
POJ - 1062 昂贵的聘礼(Dijkstra)
查看>>
Java多态和动态绑定是如何实现的
查看>>
sql server 下载安装标记
查看>>