js/javascript 繼承方式主要有哪些?及其優缺點特點

kyyius發表於2020-11-30

大家先看看這之前這篇文章,牢記一些概念。
連結: 建構函式,原型,例項的關係,原型鏈是什麼.

// 1.原型鏈繼承
// 先看個小栗子
function F(){
}
let s = new F()
Object.prototype.x = 1
console.log(s.x) // 1  通過原型鏈獲得的x值
s.x = 2 
console.log(s.x) // 2 自己的x值
/*
// 以上是原型搜尋機制,當以讀取模式訪問一個例項屬性時,
// 先再例項搜尋這個屬性,如果沒有會繼續搜尋原型

// 通過原型鏈實現的繼承的情況下,搜尋過程就可以一直沿著原型鏈繼續找,
// 直到末端Object(原型鏈末端)的預設原型
*/


function Father(){
	this.v = 1
	this.arr = [6,6,6]
}

Father.prototype.func1 = function(){
	console.log('father')
}

function Son(){
	this.v = 2
}

// 繼承
Son.prototype = new Father()
// Son.prototype 是Father的例項,所以獲得了father的所有屬性

// 建立兒子例項
let obj = new Son()

obj.func1() // father
// 方法重寫,本質上是一個在自己身上的方法,不是通過原型鏈使用的父方法
// 另外注意,重寫要在繼承之後,因為原型的指向會發生改變
Son.prototype.func1 = function(){
	console.log('Son')
}

obj.func1() //Son

let obj2 = new Son()
obj2.arr.push(9)
console.log(obj.arr) //[6, 6, 6, 9] 
console.log(obj2.arr) //[6, 6, 6, 9] 

/*
// 可以看出優點是可以簡單實現繼承
// 缺點是引用型別資料,會被不同例項影響
*/

在這裡插入圖片描述
可以先看看這篇文章再理解下面的內容
連結: js簡單理解call(),apply(),bind()和this.

// 2.借用建構函式
function F(x){
	this.arr = [1,1,1]
	this.x = x
}

function S(){
	// 繼承
	F.call(this,'b')
	this.age = 1
}

let z = new S()
console.log(z)	//[1, 1, 1]

let c = new S()
c.arr.push(2) 
console.log(c)	//[1, 1, 1, 2]
/*
	// new 的方式呼叫建構函式實際上會經歷以下4個步驟
	// 1建立一個新物件
	// 2將建構函式的作用域給新物件(使用call或者apply,所以this就指向了這個新物件)
	// 3執行建構函式中的程式碼(為這個新物件新增屬性)
	// 4返回這新物件 給接收的例項變數
	用變數z做例子
	// 首先建立了一個新物件 假設是o
	// 在o的環境中呼叫建構函式,所以建構函式裡面的this都是指向的這個o物件
	// 然後把裡面的屬性都給這個o
	// 返回o的地址給變數z接收
*/


/*
 // 優點可以不影響其他原型的情況下傳遞引數給上級建構函式,
 // 並且解決了引用型別資料的問題
 // 缺點是方法如果都定義在建構函式中的話,函式也就無法複用了,
 // 指的是每次都會在例項上//掛載一個新的function; 
 // 理解成沒有掛載在原型上的方法就行了
*/
// 3.組合繼承 (經典繼承)
function F(x){
	this.x = x
	this.arr = [1,1,1]
}
F.prototype.func = function(){
	console.log(this.x)
}
function S(x,y){
	// 繼承屬性
	F.call(this,x)
	this.y = y
}

// 繼承方法
S.prototype = new F()
S.prototype.func1 = function(){
	console.log(this.y)
}

let o1 = new S('o1',11)
o1.arr.push(2)
console.log(o1.arr) //[1, 1, 1, 2]
o1.func() // o1
o1.func1() // 11

let o2 = new S('o2',22)
console.log(o2.arr) // [1,1,1]
o2.func() // o2
o2.func1() // 22
/*
// 沒有明顯的缺點,是使用比較多的繼承方式,
// 另外還有原型式繼承,寄生式繼承,寄生組合式繼承,有餘力的同學可以瞭解一下
// 優點是解決了上面兩個的缺點
*/

相關文章