1. 程式人生 > >js 繼承(一)之原型鏈、借用建構函式、組合繼承

js 繼承(一)之原型鏈、借用建構函式、組合繼承

前言 …

Just we

原型鏈

基本思想利用原型讓一個引用型別繼承另一個引用型別的屬性和方法

function Father() {
    this.last_name = '張'
}
Father.prototype.sayLast_Name = function () {
    console.log('我的姓:' + this.last_name)
}
function Son() {
    this.first_name = '三'
}
Son.prototype = new Father()
Son.prototype.sayFirst_Name = function (
) { console.log('我的名字:'+ this.first_name) } var son = new Son() son.sayLast_Name() son.sayFirst_Name()

以上程式碼定義了兩個型別:Father 和 Son 。每個型別有一個屬性和一個方法。Son 繼承了 Father,該繼承是通過建立 Father 例項,將該例項賦給 Son.prototype 實現。實現的本質是重寫 Son 原型物件,代之以 Father 的例項

這個例子中的例項以及建構函式和原型之間的關係如下圖

在這裡插入圖片描述

原型鏈的問題

function Father() {
    this
.hobbies = ['吃飯', '睡覺', '打豆豆'] } function Son() { } Son.prototype = new Father() var son_1 = new Son() son_1.hobbies.push('學習') console.log(son_1.hobbies) // ["吃飯", "睡覺", "打豆豆", "學習"] var son_2 = new Son() console.log(son_2.hobbies) // ["吃飯", "睡覺", "打豆豆", "學習"]
  • 在原型物件上定義的屬性,會被所有例項共享
  • 在建立子型別 Son 的例項時,不能向超型別 Father 的建構函式中傳遞引數

借用建構函式

借用子型別建構函式的內部呼叫超型別的建構函式

function Father(last_name) {
    this.last_name = last_name
    this.hobbies = ['吃飯', '睡覺', '打豆豆']
}

function Son(last_name, first_name) {
    Father.call(this, last_name)
    this.first_name = first_name
}

var son_1 = new Son('張', '三')
son_1.hobbies.push('學習')
console.log(son_1.hobbies)  // ["吃飯", "睡覺", "打豆豆", "學習"]
var son_2 = new Son('張', '五')
console.log(son_2.hobbies)  // ["吃飯", "睡覺", "打豆豆"]

通過呼叫 call 方法,在建立的 Son 的例項環境下呼叫了 Father 的建構函式,這樣一來,我們在建立 Son 的例項物件就可以執行 Father 的定義的所有物件的初始化程式碼。Son 的每個例項物件就會擁有自己的 hobbies 屬性,以上程式碼也可以看出建立子型別 Son 的例項時,可以向超型別 Father 的建構函式中傳遞引數。

借用建構函式問題

function Father() {
}

Father.prototype.sayHello = function () {
    console.log('Hello JavaScript')
}

function Son() {
    Father.call(this)
}
 
var son = new Son()
son.sayHello()  //error

方法和函式都在建構函式中定義,所用型別只能使用建構函式模式,沒有函式複用

組合繼承

組合繼承結合上述原型鏈和借用建構函式的優點,避免他們的缺陷

直接上程式碼

function Father(last_name) {
    this.last_name = last_name
    this.hobbies = ['吃飯', '睡覺', '打豆豆']
}

Father.prototype.sayName = function () {
    console.log(this.last_name + this.first_name)
}

function Son(last_name, first_name) {
    Father.call(this, last_name)
    this.first_name = first_name
}

Son.prototype = new Father()
var son_1 = new Son('張', '三')
son_1.hobbies.push('學習')
console.log(son_1.hobbies)  // ["吃飯", "睡覺", "打豆豆", "學習"]
var son_2 = new Son('張', '五')
console.log(son_2.hobbies)  // ["吃飯", "睡覺", "打豆豆"]
son_1.sayName() // 張三