1. 程式人生 > >JavaScript面向物件之繼承 (上)

JavaScript面向物件之繼承 (上)

原型鏈繼承

我們再通過前幾篇的例子再瞭解下原型鏈繼承

//建立自定義建構函式
function Person() {
    this.name = "姓名";
}
//在當前建構函式的原型鏈上新增屬性hobby
Person.prototype.hobby = "旅遊"

//通過自定義建構函式Person例項化一個物件LJJ
const LJJ = new Person()
console.log(LJJ.hobby) // 旅遊
//通過自定義建構函式Person例項化一個物件YH
const YH = new Person()
console.log(YH.hobby) // 旅遊

從例字中 我們看到,LJJ與YH都從Person那裡繼承到了hobby “旅遊”, 那我們繼續往下看

//建立自定義建構函式
function Person() {
    this.name = "姓名";
}
//在當前建構函式的原型鏈上新增屬性hobby
Person.prototype.hobby = "旅遊"

//通過自定義建構函式Person例項化一個物件LJJ
const LJJ = new Person()
LJJ.hobby = "敲程式碼"
console.log(LJJ.hobby) // 敲程式碼
//通過自定義建構函式Person例項化一個物件YH
const YH = new Person()
console.log(YH.hobby) // 旅遊

對LJJ的hobby重新賦值並沒有影響YH的hobby,然後我們列印下LJJ;
輸出:
在這裡插入圖片描述


LJJ的hobby遮蔽了原型鏈上的hobby,所以LJJ的hobby是"敲程式碼",而YH的hobby仍然是原型上的hobby"旅遊"
我們再換一種寫法,看程式碼:

function Person() {
    this.name = "姓名"
}
Person.prototype.hobby = ["旅遊","看電影"]

const LJJ = new Person()
LJJ.hobby.push("敲程式碼") 
console.log(LJJ.hobby) // ["旅遊", "看電影","敲程式碼"]
const YH = new Person()
//建構函式中的hobby已經被改變
console.log(YH.hobby) // ["旅遊", "看電影","敲程式碼"]

因為在例項LJJ中新增引用型別導致改變了建構函式Person的hobby屬性,因為LJJ與YH是Person的例項,都繼承了Person的屬性,所以Person的屬性改變直接影響了他的例項;因此引入引用型別時應注意,我前面有一篇講到了處理方法,但今天我們用另一種來解決

借用建構函式

借用?就是使用call或者apply改變一下this指向,
就是子類的建構函式內部通過call或者apply呼叫父類的建構函式,如果對call方法有不瞭解的地方,可以翻看昨天的文章

//建立一個建構函式,並新增一些屬性
function Person() {
    this.name = "姓名"
    this.nickName = "暱稱"
    this.hobby = ["愛好"]
}
//建立一個建構函式,並借用了Person的建構函式
function Ljj() {
        Person.call(this)
        this.name = "劉家軍"
        this.hobby = ["旅遊","敲程式碼"]
}
//建立一個建構函式,並借用了Person的建構函式
function Yh() {
    Person.call(this)
    this.name = "袁姮"
    this.hobby = ["旅遊","看電影"]

}
const LJJ= new Ljj();
console.log(LJJ);

const YH = new Yh();
console.log(YH);

輸出:
在這裡插入圖片描述
這樣就避免了原型鏈繼承中,建構函式中的屬性或者方法被其他例項所改變的問題
但要注意一下程式碼執行順序,不要被後面的程式碼覆蓋了前面的程式碼,一般情況我們用到call()方法直接寫在函式的第一行

借用建構函式進行傳參

function Person(name,hobby) {
  this.name = name;
  this.hobby = hobby
}
function Ljj() {
  Person.call(this,"劉家軍",["旅遊","敲程式碼"])
}

function Yh() {
  Person.call(this,"袁姮",["旅遊","看電影"])
}
const LJJ = new Ljj();
console.log(LJJ);

const YH = new Yh();
console.log(YH);

輸出:
在這裡插入圖片描述

組合繼承

將原型鏈和借用建構函式技術組合到一起。
使用原型鏈實現對原型屬性和方法的繼承,用借用建構函式模式實現對例項屬性的繼承。
這樣既通過在原型上定義方法實現了函式複用,又能保證每個例項都有自己的屬性

function Person(name) {
  this.name = name
  this.hobby = ["旅遊","看電影"]
}
function CallThis(name) {
  Person.call(this, name)
}
CallThis.prototype = new Person();

let LJJ = new CallThis("劉家軍")
LJJ.hobby.push("敲程式碼")
console.log(LJJ);
let YH = new CallThis("袁姮")
console.log(YH);

輸出:
在這裡插入圖片描述
我們把這個組合繼承和之前的兩個原型鏈繼承和借用建構函式繼承進行比較
不難發現組合繼承融合了他們的優點,成為javascript中最常用的繼承模式
預知後事如何,且聽下次分解