基本上动知,ES6 的class可以看作只是一個(gè)語法糖,它的絕大部分功能员辩,ES5 都可以做到盒粮,新的class寫法只是讓對(duì)象原型的寫法更加清晰、更像面向?qū)ο缶幊痰恼Z法而已奠滑。
借助構(gòu)造函數(shù)實(shí)現(xiàn)繼承
- 缺點(diǎn):無法繼承原型鏈上的屬性和方法
function Person () {
this.name = 'person1'
}
Person.prototype.sex = '10'
Person.prototype.sayName = function () {
alert(this.name)
}
function Man () {
Person.call(this)
this.age = '24'
}
var m1 = new Man()
console.log(m1) // Man {name: "person1", age: "24"} (注意:實(shí)例自身不存在sex屬性和
sayName方法)
// m1.sayName() // 報(bào)錯(cuò) (因?yàn)樵玩溕弦膊淮嬖冢?
借助原型鏈實(shí)現(xiàn)繼承
- 缺點(diǎn):子類共享父類的引用屬性
function Father () {
this.Farr = [1, 2, 3]
}
function Child () { }
Child.prototype = new Father()
var c1 = new Child()
var c2 = new Child()
console.log(c1.Farr) // [1, 2, 3]
console.log(c2.Farr) // [1, 2, 3]
c1.Farr.push(4)
console.log(c1.Farr) // [1, 2, 3, 4]
console.log(c2.Farr) // [1, 2, 3, 4]
組合繼承
- 優(yōu)點(diǎn):子類不會(huì)共享父類中的屬性丹皱,缺點(diǎn):Mother構(gòu)造函數(shù)被執(zhí)行兩次,無法確定實(shí)例直接父類了
function Mother () {
console.log('init Mother...')
this.Marr = ['a', 'b', 'c']
}
function Daughter () {
Mother.call(this) // 執(zhí)行一次Mother構(gòu)造函數(shù)
}
Daughter.prototype = new Mother() // 再執(zhí)行一次Mother構(gòu)造函數(shù)
var d1 = new Daughter()
var d2 = new Daughter()
console.log(d1.Marr) // ["a", "b", "c"]
console.log(d2.Marr) // ["a", "b", "c"]
d1.Marr.push('d')
console.log(d1.Marr) // ["a", "b", "c", "d"]
console.log(d2.Marr) // ["a", "b", "c"]
console.log(d2.__proto__.constructor === Mother) // true(期望值是false宋税,因?yàn)镈aughter才是d2的直接父類)
組合繼承優(yōu)化(一)
- 優(yōu)點(diǎn):防止調(diào)用兩次構(gòu)造函數(shù)摊崭,缺點(diǎn):依舊無法確定實(shí)例直接父類
function Animal () {
console.log('init Animal...')
}
function Cat () {
Animal.call(this) // 執(zhí)行一次Animal構(gòu)造函數(shù)
}
Cat.prototype = Animal.prototype
var cat = new Cat()
console.log(cat.__proto__.constructor === Animal) // true(期望值是false,因?yàn)镃at才是cat的直接父類)
組合繼承優(yōu)化(二)
- 解決無法確定實(shí)例直接父類問題
function God () {
console.log('init Final...')
this.name = 'god'
}
God.prototype.todo = function () {
alert('todo')
}
function Son () {
God.call(this)
}
// Son.prototype = God.prototype
Son.prototype = Object.create(God.prototype) // Object.create()方法創(chuàng)建一個(gè)新對(duì)象杰赛,使用現(xiàn)有的對(duì)象來提供新創(chuàng)建的對(duì)象的__proto__
console.log(God.prototype)
console.log(Object.create(God.prototype))
Son.prototype.constructor = Son
var s = new Son // 無參數(shù)時(shí)呢簸,小括號(hào)可以省略
console.log(s)
console.log(s.__proto__.constructor === Son) // true (與期望值一直,完美淆攻!)
console.log(s.__proto__.constructor) // true (與期望值一直阔墩,完美!)
為什么要用Object.create()方法
- Object.create()方法創(chuàng)建一個(gè)新對(duì)象瓶珊,使用現(xiàn)有的對(duì)象來提供新創(chuàng)建的對(duì)象的proto
- 使用這個(gè)方法啸箫,傳入null可以創(chuàng)建一個(gè)無任何屬性的對(duì)象(原型上也沒有)
- 使用這個(gè)方法,會(huì)將現(xiàn)有對(duì)象放到proto屬性中伞芹,會(huì)隱藏現(xiàn)有對(duì)象原型上的默認(rèn)屬性和方法忘苛,僅僅保留用戶自己定義的。
// 普通方法創(chuàng)建對(duì)象的對(duì)象
console.log({})
// 使用Object.create創(chuàng)建的對(duì)象
console.log(Object.create(null))
// 使用Object.create唱较,會(huì)將現(xiàn)有對(duì)象放到__proto__屬性中
function God () {
console.log('init Final...')
this.name = 'god'
}
God.prototype.todo = function () {
alert('todo')
}
function Son () {
God.call(this)
}
// Son.prototype = God.prototype
Son.prototype = Object.create(God.prototype)
Son.prototype.constructor = Son
console.log(Son.prototype)
-
普通方法創(chuàng)建對(duì)象的對(duì)象
-
使用Object.create創(chuàng)建的對(duì)象
-
使用Object.create()方法實(shí)現(xiàn)繼承
-
不使用Object.create()方法實(shí)現(xiàn)繼承
本篇完扎唾。