JavaScript面向物件之繼承(下)
阿新 • • 發佈:2019-01-07
原型式繼承
這種繼承方式沒有使用嚴格意義上的建構函式,藉助原型還可以基於已有的物件建立新物件,同時還不必因此建立自定義型別
function object(o) {
function Fun() {}
Fun.prototype = o;
return new Fun();
}
在object函式內部,先建立一個臨時性的建構函式Fun,然後將傳入的物件作為這個建構函式的原型,最後返回這個臨時型別的一個新例項。
本質上來說,object對傳入其中的物件執行了一次淺複製。
function object(o) {
function Fun() { }
Fun.prototype = o
return new Fun()
}
const Person = {
name: "姓名",
hobby: ["旅遊","電影"]
}
const LJJ = object(Person)
LJJ.name = "劉家軍"
LJJ.hobby.push("敲程式碼")
const YH = object(Person)
YH.name = "袁姮"
YH.hobby.push("購物")
console.log(LJJ);
console.log(YH);
console.log(Person);
輸出:
ES5新增Object.create規範了原型式繼承
Object.create
Object.create()這個方法我在寫js原型和原型鏈時簡單介紹過了,如果還有什麼不瞭解檢視js權威文件MDN(Object.create)
看下面三種建立物件的方法
console.log(Object.create(null))
console.log(new Object())
console.log({})
輸出:
可以看出第一種建立方法最乾淨;
我們繼續看程式碼:
const Person = {
name: "姓名",
hobby: ["旅遊","看電影"]
};
const LJJ = Object.create (Person, {
private : {
value: "私有的", // private 屬性值
writable:true // 屬性可寫
}
});
LJJ.name = "劉家軍"
LJJ.hobby.push("唱歌")
LJJ.private = "敲程式碼"
console.log(LJJ.private) // 敲程式碼
//--------------------------------------
const Person = {
name: "姓名",
hobby: ["旅遊","看電影"]
};
const YH = Object.create(Person, {
private : {
value: "私有的", // private 屬性值
writable: false // 屬性不可寫
}
});
YH.name = "袁姮"
YH.hobby.push("美食")
YH.private = "購物"
console.log(YH.private) // 私有的
private 的屬性還有很多 詳細請看js權威文件 MDN
區別
1.Object.cerate()繼承指定物件
2.new Object() 繼承內建物件Object
3.可以通過Object.create(null) 建立一個乾淨的物件,也就是沒有原型,而 new Object() 建立的物件是 Object的例項,原型永遠指向Object.prototype。
寄生式繼承
寄生式繼承是與原型式繼承緊密相關的一種思路,它創造一個僅用於封裝繼承過程的函式,在函式內部以某種方式增強物件,最後再返回物件。
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function clone(params) {
const proto= object(params) //通過呼叫函式建立一個新物件
return proto
}
const Person = {
name: "姓名",
hobby: ["旅遊","看電影"]
}
const LJJ = clone(Person);
LJJ.name = "劉家軍"
LJJ.hobby.push("敲程式碼")
console.log(LJJ)
輸出:
寄生式繼承和原型式繼承,方法接近
寄生組合式繼承
組合繼承有個弊端就是會呼叫兩次被繼承者的建構函式,解決方法就是使用寄生組合式繼承。這又是什麼呢?這個相對之前的比較複雜,但是高效的一點是隻呼叫一次被繼承者建構函式,原理就是通過寄生方式建立一個被繼承者的副本,副本和被繼承者共用一個prototype,這樣就解決了之前的問題
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function clone(Children, Person) {
const proto = object(Person.prototype) // 返回Person的一個副本
proto.constructor= Children // 設定constructor指向, 因為新副本的原型物件被重寫
Children.prototype = proto // 副本作為Children的原型物件
}
function Person() {
this.name = "姓名"
}
Person.prototype.sayName = function() {
console.log(this.name)
}
function Ljj() {
Person.call(this)
this.name = "劉家軍"
}
function Yh() {
Person.call(this)
this.name = "袁姮"
}
clone(Ljj, Person)
clone(Yh, Person)
const LJJ = new Ljj()
const YH = new Yh()
LJJ.sayName() // 劉家軍
YH.sayName() // 袁姮