js继承总共分成5种,包括构造函数式继承、原型链式继承、组合式继承、寄生式继承和寄生组合式继承。

构造函数式继承

首先来看第一种,构造函数式继承,顾名思义,也就是利用函数去实现继承;构造函数继承,使用call和apply两个方法可以实现改变方法中的this

// 父类构造函数
function Parent(color) {
this.color = color;
this.print = function() {
console.log(this.color);
}
}

现在要编写一个子类函数来继承这个父类,如下:

// 子类构造函数
function Son(color) {
Parent.call(this, color);
  • 优点:所有的基本属性独立,不会被其他实例所影响;
  • 缺点:所有希望共享的方法和属性也独立了,没有办法通过修改父类某一处来达到所有子实例同时更新的效果;同时,每次创建子类都会调用父类构造函数一次,所以每个子实例都拷贝了一份父类函数的内容,如果父类很大的话会影响性能;

原型链继承

function Parent() {
this.color = 'red';
this.print = function() {
console.log(this.color);
}
}
function Son() {
}

我们有一个父类和一个空的子类;

Son.prototype = new Parent();
Son.prototype.constructor = Son;

接着我们把子函数的原型属性赋值给了父函数的实例;

var son1 = new Son();
son1.print(); // red

最后新建子类实例,调用父类的方法,成功拿到父类的color和print属性方法;

我们重点来分析一下下面两行代码:

Son.prototype = new Parent();
Son.prototype.constructor = Son;

这段代码中,子函数的原型赋给了父函数的实例,我们知道prototype是函数中的一个属性,js的一个特性就是:如果一个对象某个属性找不到,会沿着它的原型往上去寻找,直到原型链的最后才会停止寻找。

回到代码,我们看到最后实例son成功调用了Print方法,输出了color属性,这是因为son从函数Son的prototype属性上面去找到的,也就是从new Parent这个对象里面找到的;

这种方式也不是真正的继承,因为所有的子实例的属性和方法,都在父类同一个实例上了,所以一旦某一个子实例修改了其中的方法,其他所有的子实例都会被影响,来看下代码:

function Flower() {
this.colors = ['黄色', '红色'];
this.print = function () {
console.log(this.colors)
}
}

function Rose() {}
Rose.prototype = new Flower();
Rose.prototype.constructor = Rose;

var r1 = new Rose();
var r2 = new Rose();

console.log(r1.print()); // [ '黄色', '红色' ]
console.log(r1.print()); // [ '黄色', '红色' ]

r1.colors.push('紫色');

console.log(r1.print()); // [ '黄色', '红色', '紫色' ]
console.log(r2.print()); // [ '黄色', '红色', '紫色' ]

还是刚才的例子,这次Rose子类选择了原型链继承,所以,子实例r1修改了colors之后,r2实例的colors也被改动了,这就是原型链继承不好的地方。

来总结下原型链继承的优缺点:

  • 优点:很好的实现了方法的共享;
  • 缺点:正是因为什么都共享了,所以导致一切的属性都是共享的,只要某一个实例进行修改,那么所有的属性都会变化;

组合式继承

​function Parent(color) {
this.color = color;
}
Parent.prototype.print = function() {
console.log(this.color);
}
function Son(color) {
Parent.call(this, color);
}
Son.prototype = new Parent();
Son.prototype.constructor = Son;

var son1 = new Son('red');
son1.print(); // red

var son2 = new Son('blue');
son2.print(); // blue

上面代码中,在Son子类中,使用了Parent.call来调用父类构造函数,同时又将Son.prototype赋给了父类实例;为什么要这样做呢?为什么这样就能解决上面两种继承的问题呢?
我们接着分析一下,使用Parent.call调用了父类构造函数之后,那么,以后所有通过new Son创建出来的实例,就单独拷贝了一份父类构造函数里面定义的属性和方法,这是前面构造函数继承所提到的一样的原理;

然后,再把子类原型prototype赋值给父类的实例,这样,所有子类的实例对象就可以共享父类原型上定义的所有属性和方法。这也不难理解,因为子实例会沿着原型链去找到父类函数的原型。

因此,只要我们定义父类函数的时候,将私有属性和方法放在构造函数里面,将共享属性和方法放在原型上,就能让子类使用了。

以上就是组合式继承,它很好的融合了构造函数继承和原型链继承,发挥两者的优势之处,因此,它算是真正意义上的继承方式。

javaScript继承的几种实现方式?的更多相关文章

  1. js(javascript) 继承的5种实现方式

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt240 js继承有5种实现方式:1.继承第一种方式:对象冒充  functio ...

  2. javascript继承有5种实现方式

    1.对象冒充 function Parent(username){ this.username = username; this.hello = function(){ alert(this.user ...

  3. JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)

    JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...

  4. 面向面试编程——javascript对象的几种创建方式

    javascript对象的几种创建方式 总共有以下几个模式: 1.工厂模式 2.构造函数模式 3.原型模式 4.混合构造函数和原型模式 5.动态原型模式 6.寄生构造函数模式 7.稳妥构造函数模式 1 ...

  5. JavaScript脚本的两种放置方式

    JavaScript脚本的两种放置方式 1在body里用 script标签引用 2 直接写在<script></script>标签之中

  6. JavaScript继承的几种实现

    0 什么是继承 继承就是获得存在对象已有的属性和方法的一种方式. [2019.4.26 更新]今日又重新学习了一下JS的继承,在这里整理一下以前的笔记并补充一些新的感悟. 1 JS中继承的几种实现方法 ...

  7. javascript继承的三种模式

    javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...

  8. JavaScript 函数的两种声明方式

    1.函数声明的方式 JavaScript声明函数有两种选择:函数声明法,表达式定义法. 函数声明法 function sum (num1 ,num2){ return num1+num2 } 表达式定 ...

  9. javascript中对象两种创建方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. 通过jquery 获取下拉列表中选中的值对应的value

    <div class="col-sm-9"> <select id="device-type" class="form-contro ...

  2. selenium截图功能

    selenium自动化测试完后需要查看值观的结果,或者查操作过程中是否正确,此时需要使用自带的截图功能. 示例1: from time import sleep from selenium impor ...

  3. asp.net core 集成 Prometheus

    asp.net core 集成 prometheus Intro Prometheus 是一个开源的现代化,云原生的系统监控框架,并且可以轻松的集成 PushGateway, AlertManager ...

  4. mysql 优化数据类型

    1.更小的通常更好 选择不会超过范围的最小类型 2.简单就好 例如,整型比字符操作代价更低,因为字符集和校对规则(排序规则)使字符比较比整形比较更复杂. 3.尽量避免null 如果查询中包含可为nul ...

  5. SpringBoot中JPA的学习

    SpringBoot中JPA的学习 准备环境和项目配置 写一下学习JPA的过程,主要是结合之前SpringBoot + Vue的项目和网上的博客学习一下. 首先,需要配置一下maven文件,有这么两个 ...

  6. bootstrap 按钮颜色属性

    bootstrap 按钮颜色属性有几种

  7. MySQL(13)---MYSQL主从复制原理

    MYSQL主从复制原理 最近在做项目的时候,因为部署了 MYSQL主从复制 所以在这里记录下整个过程.这里一共会分两篇博客来写: 1.Mysql主从复制原理 2.docker部署Mysql主从复制实战 ...

  8. 排序--ShellSort 希尔排序

    希尔排序 no 实现 希尔排序其实就是插入排序.只不过希尔排序在比较的元素的间隔不是1. 我们知道插入排序 都是 一个一个和之前的元素比较.发现比之前元素小就交换位置.但是希尔排序可能是和前第n个元素 ...

  9. django和DRF的不同点

    django中封装了drf view 是 父类 class test1(View): def post(self,request): data=request.POST.get('name') ret ...

  10. 单调栈模板 POJ3250

    上次二分st表大法失败以后的又一次尝试233333 封装,封装,封装!!!!!! #include <bits/stdc++.h> using namespace std; #define ...