JS 总结之原型继承的几种方式

栏目: JavaScript · 发布时间: 6年前

内容简介:在之前的总结中,我们详细分析了原型以一个父类为前提条件,列举 js 继承的继承方式:缺点:

在之前的总结中,我们详细分析了原型 《JS 总结之原型》 ,原型很大作用用于模拟继承,这一次,我们来聊原型继承的几种方式。

前提

以一个父类为前提条件,列举 js 继承的继承方式:

function Person (age) {
  this.age = age || 18
}
Person.prototype.sleep = function () {
  console.log('sleeping')
}
复制代码

:meat_on_bone: 方式 1:原型链继承(不推荐)

function Programmer() {}

Programmer.prototype = new Person ()
Programmer.prototype.code = function () {
  console.log('coding')
}

let jon = new Programmer()
jon.code() // coding
jon.sleep() // sleeping

jon instanceof Person // true
jon instanceof Programmer // true

Object.getPrototypeOf(jon) // Person {age: 18, code: ƒ}
jon.__proto__ // Person {age: 18, code: ƒ}
复制代码

缺点:

  1. 无法向父类构造函数传参
  2. 父类的所有属性被共享,只要一个实例修改了属性,其他所有的子类实例都会被影响

方式 2:借用构造函数(经典继承)(不推荐)

复制父类构造函数内的属性

function Programmer(name) {
  Person.call(this)
  this.name = name
}
let jon = new Programmer('jon')
jon.name // jon
jon.age // 18

jon.sleep() // Uncaught TypeError: jon.sleep is not a function
jon instanceof Person // false
jon instanceof Programmer // true
复制代码

优点:

  1. 可以为父类传参
  2. 避免了共享属性

缺点:

  1. 只是子类的实例,不是父类的实例
  2. 方法都在构造函数中定义,每次创建实例都会创建一遍方法

:fried_shrimp: 方式 3:组合继承(推荐)

组合 原型链继承借用构造函数继承

function Programmer(age, name) {
  Person.call(this, age)
  this.name = name
}

Programmer.prototype = new Person()
Programmer.prototype.constructor = Programmer // 修复构造函数指向

let jon = new Programmer(18, 'jon')
jon.age // 18
jon.name // jon

let flash = new Programmer(22, 'flash')
flash.age // 22
flash.name // flash

jon.age // 18

jon instanceof Person // true
jon instanceof Programmer // true
flash instanceof Person // true
flash instanceof Programmer // true
复制代码

优点:融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式

缺点:调用了两次父类构造函数

方式 4:原型式继承(不推荐)

function create(o) {
  function F() {}
  F.prototype = o
  return new F()
}

let obj = {
  gift: ['a', 'b']
}

let jon = create(obj)
let xiaoming = create(obj)

jon.gift.push('c')
xiaoming.gift // ['a', 'b', 'c']
复制代码

缺点:共享了属性和方法

:egg: 方式 5:寄生式继承(不推荐)

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

function createObj (o) {
  var clone = Object.create(o)
  clone.sayName = function () {
    console.log('hi')
  }
  return clone
}
复制代码

缺点:跟借用构造函数模式一样,每次创建对象都会创建一遍方法

:shaved_ice: 方式 6:寄生组合继承(最佳)

子类构造函数复制父类的自身属性和方法,子类原型只接受父类的原型属性和方法:

function create(prototype) {
  function Super() {}
  Super.prototype = prototype
  return new Super()
}

function Programmer(age, name) {
  Person.call(this, age)
  this.name = name
}

Programmer.prototype = create(Person.prototype)
Programmer.prototype.constructor = Programmer // 修复构造函数指向

let jon = new Programmer(18, 'jon')
jon.name // jon
复制代码

进阶封装:

function create(prototype) {
  function Super() {}
  Super.prototype = prototype
  return new Super()
}

function prototype(child, parent) {
  let prototype = create(parent.prototype)
  prototype.constructor = child // 修复构造函数指向
  child.prototype = prototype
}

function Person (age) {
  this.age = age || 18
}
Person.prototype.sleep = function () {
  console.log('sleeping')
}

function Programmer(age, name) {
  Person.call(this, age)
  this.name = name
}

prototype(Programmer, Person)

let jon = new Programmer(18, 'jon')
jon.name // jon
复制代码

引用《JavaScript 高级程序设计》中对寄生组合式继承的夸赞就是:

这种方式的高效率体现它只调用了一次 Parent 构造函数,并且因此避免了在 Parent.prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。

:ramen: 方式 7:ES6 extends(最佳)

// 父类
class Person {
  constructor(age) {
    this.age = age
  }
  sleep () {
    console.log('sleeping')
  }
}

// 子类
class Programmer extends Person {
  constructor(age, name) {
    super(age)
    this.name = name
  }
  code () {
    console.log('coding')
  }
}

let jon = new Programmer(18, 'jon')
jon.name // jon
jon.age // 18

let flash = new Programmer(22, 'flash')
flash.age // 22
flash.name // flash

jon instanceof Person // true
jon instanceof Programmer // true
flash instanceof Person // true
flash instanceof Programmer // true
复制代码

优点:不用手动设置原型。

缺点:新语法,只要部分浏览器支持,需要转为 ES5 代码。

:rocket: 参考


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First HTML5 Programming(中文版)

Head First HTML5 Programming(中文版)

埃里克•弗里曼 (Eric Freeman)、伊丽莎白•罗布森 (Elisabeth Robson) / 中国电力出版社 / 2012-9 / 78.00元

《Head First HTML5 Programming(中文版)》内容简介:你可能想创建具有动态性、交互性、包含丰富数据而且互连的Web页面。先等一下,Web页面?为什么不用HTML5创建成熟的Web应用呢?另外,为什么不使用现代技术,像在移动设备上一样轻松地应用到桌面浏览器呢?当然,你肯定希望使用最新的HTML5技术来完成,比如地理定位、视频、2D绘制、Web存储、Web工作线程等,是不是?......一起来看看 《Head First HTML5 Programming(中文版)》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具