es5 原型式繼承

無樣發表於2019-04-13

1. 原型式繼承方法

常規的類繼承實現結果(也就是es6繼承後結果)是:

  1. 子類重寫屬性和方法不影響父類
  2. 父類重寫屬性和方法影響子類
  3. 子類可以自定義繼承父類構造方法

es5 的原型式繼承方式,有如下 3 條:

  1. 子類重寫基本型別的屬性不影響父類,如果是引用屬性,則會影響(這裡說的引用所在記憶體的位置沒有發生變化)
  2. 父類重寫屬性和方法影響子類
  3. 子類可以自定義繼承父類構造方法

es5 繼承最主要的原型式繼承方法,這個函式步驟分為 4 步驟:

  1. 建立一箇中間的建構函式Fn,Fn.prototype = Super.prototype
  2. 例項化 Fn 為 var fn = new Fn(),將 Child.prototype = fn
  3. Child.prototype.constructor = Child
  4. Child 建構函式中封裝一個 super 方法,來繼承父類裡的建構函式。

ps:當然步驟 1 和 2 可用 Object.create() 來替代。

程式碼如下:

function extends (Sup, Sub) {
	// var Fn = function () {}
	// Fn.prototype = Sup.prototype
	// var fn = new Fn()
	// Sub.prototype = fn
	Sub.prototype = Object.cteate(Sup.prototpye)
	Sub.prototype.constructor = Sub
}

function super (Sup) {
	var	args = []
	if (arguments.length > 1) {
		args = Array.protoype.slice.call(arguments, 1)
	}
	Sup.apply(this, args)
}
function Sup (name) {
	this.name = name
}
function Sub (name) {
	super(Sup, name)
}

extends(Sup, Sub)
複製程式碼

記憶體分析:

es5 原型式繼承

需要注意的是:包含引用型別值的屬性始終都會共享相應的值,就像使用原型模式一樣。 這一點和 es6的繼承不同,下列是兩種繼承做對比。

es5

var parent = new Sup('父親')
var child = new Sub('孩子')

console.log('parent.name', parent.name)
console.log('child.name', child.name)
child.name = '女兒'
console.log('修改 child.name = \'女兒\' parent', child.name) // 女兒
console.log('修改 child.name = \'女兒\' parent', parent.name) // 父親

console.log('child.pet.name = xm =============')
parent.pet.name = 'jack'
console.log(parent.pet.name) // jack
console.log(child.pet.name) // jack
複製程式碼

es6

class Sup {
  pet = {
    name: 'mack'
  }
  constructor (name) {
    this.name = name
  }
  say () {
    console.log(`my name is ${this.name} and my pet's name is ${this.pet.name}`)
  }
  changePetName (name) {
    this.pet.name = name
  }
}

class Sub extends Sup {
  constructor (name) {
    super(name)
  }
}

const parent = new Sup('父親')
const son = new Sub('兒子')

// 修改父親寵物的名字
parent.changePetName('jack')
console.log('parent.pet.name', parent.pet.name)
parent.say() // jack
son.say() // mack
複製程式碼

相關文章