JS 总结之原型继续的几种体式格局

《JS 总结之原型继续的几种体式格局》

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

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

🍖 体式格局 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. 要领都在组织函数中定义,每次建立实例都邑建立一遍要领

🍤 体式格局 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']

瑕玷:同享了属性和要领

🍳 体式格局 5:寄生式继续(不引荐)

建立一个仅用于封装继续历程的函数,该函数在内部以某种情势来做加强对象,末了返回对象

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

瑕玷:跟借用组织函数情势一样,每次建立对象都邑建立一遍要领

🍧 体式格局 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。开发人员普遍认为寄生组合式继续是援用范例最理想的继续范式。

🍜 体式格局 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 代码。

🚀 参考

    原文作者:Karon_
    原文地址: https://segmentfault.com/a/1190000017488447
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞