js实现继承的多种方式

1. 原型链继承

  1. function Parent() {
  2. this.name = 'xwk'
  3. }
  4. Parent.prototype.getName = function() {
  5. console.log(this.name)
  6. }
  7. function Child() {}
  8. Child.prototype = new Parent()
  9. var child = new Child()
  10. console.log(child.getName()) // xwk

缺点:

  1. 引用类型的属性被所有实例共享,举个例子:
  1. function Parent () {
  2. this.names = ['kevin', 'daisy'];
  3. }
  4. function Child () {}
  5. Child.prototype = new Parent();
  6. var child1 = new Child();
  7. child1.names.push('yayu');
  8. console.log(child1.names); // ["kevin", "daisy", "yayu"]
  9. var child2 = new Child();
  10. console.log(child2.names); // ["kevin", "daisy", "yayu"]
  1. 在创建Child的实例时,不能向Parent传参数
  2. 实例丢失了自己的construct属性

2. 经典继承(借用构造函数(使用call))

  1. function Parent() {
  2. this.names = ["kevin", "daisy"]
  3. }
  4. Parent.prototype.getName = function() {
  5. console.log(this.names)
  6. }
  7. function Child() {
  8. Parent.call(this)
  9. }
  10. var child1 = new Child()
  11. child1.names.push('yayu');
  12. console.log(child1.names); // ["kevin", "daisy", "yayu"]
  13. var child2 = new Child();
  14. console.log(child2.names); // ["kevin", "daisy"]

缺点:Parent原型上的属性和方法不能被继承

优点:

  1. 在继承的时候可以向Parent传参
  2. 可以避免引用类型的属性被不同实例所共享

3. 组合继承

原型链继承 + 经典继承

  1. function Parent(name) {
  2. this.name = name
  3. this.colors = ['red','blue']
  4. }
  5. Parent.prototype.getName = function() {
  6. console.log(this.name)
  7. }
  8. function Child(name, age) {
  9. Parent.call(this, name)
  10. this.age = age
  11. }
  12. Child.prototype = new Parent()
  13. Child.prototype.constructor = Child
  14. var child1 = new Child('kevin', '18');
  15. child1.colors.push('black');
  16. console.log(child1.name); // kevin
  17. console.log(child1.age); // 18
  18. console.log(child1.colors); // ["red", "blue", "green", "black"]
  19. var child2 = new Child('daisy', '20');
  20. console.log(child2.name); // daisy
  21. console.log(child2.age); // 20
  22. console.log(child2.colors); // ["red", "blue", "green"]

分析下上述代码:

  1. Parent.call(this, name) ,解决了传参问题,并且将Parent构造函数内的属性复制到Child里,可以避免引用类型被共享;
  2. Child.prototype = new Parent() 同时使用原型链继承,可以保证Parent原型上的属性和方法能被Child继承到。

4. 原型式继承 (Object.create)

  1. function createObj(obj) {
  2. function F() {}
  3. F.prototype = obj
  4. return new F()
  5. }

上述代码,其实就是ES5 Object.create 方法的实现,将传入的对象作为一个新对象的原型返回。

缺点:和原型链继承的缺点一样,引用类型的属性会被子实例所共享

  1. var person = {
  2. name: 'kevin',
  3. friends: ['daisy', 'kelly']
  4. }
  5. var person1 = createObj(person);
  6. var person2 = createObj(person);
  7. person1.name = 'person1';
  8. console.log(person2.name); // kevin
  9. person1.friends.push('taylor');
  10. console.log(person2.friends); // ["daisy", "kelly", "taylor"]

5. 寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来增强对象,最后返回对象。

  1. function createObj (o) {
  2. var clone = Object.create(o);
  3. clone.sayName = function () {
  4. console.log('hi');
  5. }
  6. return clone;
  7. }

缺点:和经典模式一样,方法都在构造函数中定义,每次创建实例都会创建一遍方法。

6. 寄生组合继承

其实就是对组合继承的优化,

我们可以看组合继承的代码,发现一共掉了两次Parent构造函数,

一次是Child.prototype = new Parent(),

一次是Child构造函数中,Parent.call(this,name),

这样导致的结果就是Child和Child.prototype中都有colors属性。

那么怎么优化呢,避免这一次重复调用呢?

如果我们不使用 Child.prototype = new Parent() ,而是间接的让 Child.prototype 访问到 Parent.prototype 呢?

  1. function Parent(name) {
  2. this.name = name
  3. this.colors = ['red','blue']
  4. }
  5. Parent.prototype.getName = function() {
  6. console.log(this.name)
  7. }
  8. function Child(name, age) {
  9. Parent.call(this, name)
  10. this.age = age
  11. }
  12. Child.prototype = Object.create(Parent.prototype)
  13. Child.prototype.constructor = Child
  14. var child1 = new Child('kevin', '18');
  15. child1.colors.push('black');
  16. console.log(child1.name); // kevin
  17. console.log(child1.age); // 18
  18. console.log(child1.colors); // ["red", "blue", "green", "black"]
  19. var child2 = new Child('daisy', '20');
  20. console.log(child2.name); // daisy
  21. console.log(child2.age); // 20
  22. console.log(child2.colors); // ["red", "blue", "green"]

注意️:

使用 Child.prototype = Object.create(Parent.prototype) 替换

Child.prototype = new Parent()

虽然目的都是一样,让Child.prototype 的原型对象 指向 Parent.prototype,

但是使用后者会把Parent构造函数内部的多余属性也继承过来,前者不会。

基础3:js实现继承的多种方式的更多相关文章

  1. js原生继承几种方式

    js原生继承 js本身并没有继承和类的概念,本质上是通过原型链(prototype)的形式实现的. 1.先写两个构造函数Parent和Child,用于将Child继承Parent function P ...

  2. 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数

     上章链接: 22.C++- 继承与组合,protected访问级别 继承方式 继承方式位于定义子类的”:”后面,比如: class Line : public Object //继承方式是publi ...

  3. JavaScript是如何实现继承的(六种方式)

    大多OO语言都支持两种继承方式: 接口继承和实现继承 ,而ECMAScript中无法实现接口继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现,下文给大家技术js实现继承的 ...

  4. 基础2:js创建对象的多种方式

    js创建对象的多种方式 1. 工厂模式 function createPerson(name) { var o = new Object() 0.name = name return o } var ...

  5. 【编程题与分析题】Javascript 之继承的多种实现方式和优缺点总结

    [!NOTE] 能熟练掌握每种继承方式的手写实现,并知道该继承实现方式的优缺点. 原型链继承 function Parent() { this.name = 'zhangsan'; this.chil ...

  6. js实现继承的5种方式 (笔记)

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

  7. js实现继承的方式总结

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

  8. js实现继承的5种方式

    js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承有以下通用的几种方式1.使用对象冒充实现继承(该种实现 ...

  9. JS中继承方式总结

    说在前面:为了使代码更为简洁方便理解, 本文中的代码均将"非核心实现"部分的代码移出. 一.原型链方式关于原型链,可点击<深入浅出,JS原型链的工作原理>,本文不再重复 ...

随机推荐

  1. Go微服务框架go-kratos实战02:proto 代码生成和编码实现步骤

    在上一篇 kratos quickstart 文章中,我们直接用 kratos new 命令生成了一个项目. 这一篇来看看 kratos API 的定义和使用. 一.kratos 中 API 简介 1 ...

  2. 《HALCON数字图像处理》第五章笔记

    目录 第五章 图像运算 图像的代数运算 加法运算 图像减法 图像乘法 图像除法 图像逻辑运算(位操作) 图像的几何变换 图像几何变换的一般表达式 仿射变换 投影变换 灰度插值 图像校正 我在Gitee ...

  3. 使用 Nocalhost 开发 Rainbond 上的微服务应用

    本文将介绍如何使用 Nocalhost 快速开发 Rainbond 上的微服务应用的开发流程以及实践操作步骤. Nocalhost 可以直接在 Kubernetes 中开发应用,Rainbond 可以 ...

  4. BUUCTF-隐藏的钥匙

    隐藏的钥匙 通过16进制打开发现flag,其中告知编码为base64,解密后加上flag{}即可 flag{377cbadda1eca2f2f73d36277781f00a}

  5. SAP setting and releasing locks

    REPORT demo_transaction_enqueue MESSAGE-ID sabapdocu. TABLES sflight. DATA text(8) TYPE c. DATA ok_c ...

  6. SpringBoot整合RocketMQ

    1.RocketMQ的下载与配置 到官网选择想要的版本下载即可,https://rocketmq.apache.org/release_notes/ 下载速度会比较慢,这里提供目前最新版本4.9.3的 ...

  7. Python收集这些视频只是单纯的想做做壁纸,大家不要误会

    首先澄清一下,我用Python收集这些视频,绝不是想做别的什么,真的只是用来做动态壁纸,大家不要误会!我不是那样的人~ 这样的不过份吧 (这个动图看不看的到就看有没有缘分了 ) 阅读本文你需要准备 1 ...

  8. EasyExcel导出添加批注

    直接看代码.根据个人需要做改动 注:POI也可以做批注,文章链接https://www.cnblogs.com/qq1445496485/p/15622664.html /** * 导出(批注) * ...

  9. 卸载office密钥

    一.管理员身份运行命令提示行: 二.命令提示行上输入: cd C:\Program Files\Microsoft Office\Office16 弹出如下内容: C:\Program Files\M ...

  10. Vmware虚拟机硬件兼容性

    All virtual machines have a hardware version. The hardware version indicates which virtual hardware ...