纵有疾风起
人生不言弃

构造函数与实例、原型与原型链、继承

一、构造函数、实例

在JavaScript中,new关键字可以让一个函数变得与众不同,如下:

构造函数与实例、原型与原型链、继承插图
new改变了this的指向

这时我们称Person为一个构造函数,p1是构造函数Person的实例。

二、原型

在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。

构造函数与实例、原型与原型链、继承插图1
构造函数与原型

当我们在创建对象时,可以根据自己的需求,选择性的将一些属性和方法通过prototype属性,挂载在原型对象上。每一个new出来的实例,都有一个__proto__属性,该属性指向构造函数的原型对象。通过这个属性,让实例对象也能够访问原型对象上的方法。因此,当所有的实例都能够通过__proto__访问到原型对象时,原型对象的方法与属性就变成了共有方法与属性。

而每个原型都有一个constructor属性,指向该关联的构造函数。

构造函数与实例、原型与原型链、继承插图2
构造函数、实例、原型

当我们访问实例对象中的属性或者方法时,会优先访问实例对象自身的属性和方法,如果实例对象自身没有对应的属性和方法,则访问其原型或者原型的原型的对象和方法(向上查找)。

构造函数与实例、原型与原型链、继承插图3
代码示例

三、原型链

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。

构造函数与实例、原型与原型链、继承插图4
原型链

例如:p1是Person的实例,Person是Function对象的实例。而Function的原型对象同时又是Object的实例。

四、继承

原型链继承:

将父类的实例作为子类的原型

构造函数与实例、原型与原型链、继承插图5
原型链继承

缺点:

    引用类型的属性被所有实例共享,每个实例都有相同的属性,属性的继承无意义

    在创建Child 的实例时, 不能向Person传参

构造函数继承:

在子类的内部调用父类,通过call改变父类中this的指向,等于是复制父类的实例属性给子类

构造函数与实例、原型与原型链、继承插图6
构造函数继承

优点:

    可以实现多继承,避免了引用类型的属性被所有实例共享

    创建子类实例时,可以向父类传递参数。可以在Child中向Parent传参

缺点:

    实例只是子类的实例,不是父类的实例

    无法继承原型中的方法

组合继承

使用原型链实现对原型方法的继承,而通过借用构造函数来实现对实例属性的继承。是JavaScript中最常用的继承模式

构造函数与实例、原型与原型链、继承插图7
组合继承

优点:

    实例既是子类的实例,也是父类的实例

    可以向父类传参

    可以继承原型中的方法

缺点:调用了两次父类构造函数(组合继承最大的问题是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部)

文章转载于:https://www.jianshu.com/p/82e3fa21a6fd

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » 构造函数与实例、原型与原型链、继承
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录