時刻乾爽無懼汗,駱駝速幹短袖 T 恤/短褲 39 元、2 件 68 元
阿新 • • 發佈:2021-06-28
JS繼承
//建構函式
function Person(name){
this.name = name;
this.sayName = function(){
console.log(this.name)
}
}
Person.prototype.age = 10
1.原型鏈繼承
function Per(){ this.name = 'jack' } Per.prototype = new Person() var per1 = new Per() console.log(per1.age,per1.name) //10 jack //10 per1.age->per1.__proto__ === Per.prototype -> Per.prototype = new Person()->例項new Person()的建構函式是Person -> per1.__proto__ 從 Person.prototype中找age = 10 console.log(per1 instanceof Per,per1 instanceof Person,per1 instanceof Object) //true true true //instanceof的判斷邏輯是per的__proto__一層一層往上找 var per2 = new Per() per2.__proto__.__proto__.age = 20 console.log(per1.age) //20
讓新例項的原型等於父類的例項。
缺點:1、新例項無法向父類建構函式傳參。2、繼承單一。3、所有新例項都會共享父類例項的屬性。(原型上的屬性是共享的,一個例項修改了原型屬性,另一個例項的原型屬性也會被修改!)
2.借用建構函式繼承
function Con(name){ Person.call(this,name) } let con1 = new Con(‘jack') console.log(con1.name,con1.age) // jack undefined console.log(con1 instanceof Con,con1 instanceof Person)//true false
用.call()和.apply()將父類建構函式引入子類函式(在子類函式中做了父類函式的自執行(複製))
缺點:1、只繼承了父類建構函式的屬性,沒有繼承父類原型的屬性。2、無法實現建構函式的複用。3、每個新例項都有父類建構函式的副本,臃腫。
call(),apply(),bind()()用法
Fun().call(this,'param1','param2') Fun().apply(this,['param1','param2']) Fun().bind(this,'param1','param2')() //相同點第一個引數都是this的指向物件(一個是函式執行的作用域),上面繼承:是把Person()中的this指向Con()中的this所在的作用域;後面是引數入參方式允許是各種型別,包括函式 、 object 等等
3.組合繼承
function Con(name){
Person.call(this,name)
}
Con.prototype = new Person()//替換Con的prototype為Person的例項
let con1 = new Con('Jack')
console.log(con1.name, con1.age)//Jack 10
console.log(con1 instanceof Con, con1 instanceof Person)//true true
//con1.age->con1.__proto__(Con.prototype中找)->Con.prototype = new Person(),Person例項中沒有->去Person例項的__proto__找(Person.prototype中找)->10
結合了兩種模式的優點,傳參和複用
缺點:呼叫了兩次父類建構函式(一次引用Person,一次引用Person例項),Con.prototype被替換
4.原型式繼承
function content(obj){
function F(){}
F.prototype = obj
return new F()
}
let per = new Person('jack'),
con1 = content(per)
console.log(con1.name,con1.age,con1) //jack 10
console.log(con1 instanceof Person) //true
//函式content返回一個函式F的例項,函式F原型鏈繼承Person
用一個函式包裝一個物件,然後返回這個函式的呼叫,這個函式就變成了個可以隨意增添屬性的例項或物件。object.create()就是這個原理。
缺點:1、所有例項都會繼承原型上的屬性。2、無法實現複用。(新例項屬性都是後面新增的)3、無法向父類建構函式傳參
5.寄生式繼承
function content(obj) {
function F() {}
F.prototype = obj
return new F()
}
let per = new Person()
function subobject(obj) {
let sub = content(obj)
sub.name = 'jack'
return sub
}
let con1 = subobject(per)
console.log(con1.name, con1.age, con1) //jack 10
console.log(con1 instanceof Person) //true
給原型式繼承外面套了個殼子
缺點:沒用到原型,無法複用。
6.寄生組合式繼承(常用)
function content(obj) {
function F() {}
F.prototype = obj
return new F()
}
let per = content(Person.prototype) //F的例項繼承了Person的原型
function Con(name) {
Person.call(this,name)
}
Con.prototype = per //Con的原型為F的例項
per.constructor = Con //per的constructor指向建構函式F(),改為指向Con()
let con1 = new Con('jack')
console.log(con1.name, con1.age, con1) //jack 10
console.log(con1 instanceof Person) //true
修復組合繼承的問題
7.ES6 Class 繼承
class Person { // 定義了一個名字為Person的類
constructor(x, y) { // constructor是一個構造方法,用來接收引數
this.x = x;
this.y = y;
this.z = 1;
this.a = 3;
}
toString() {
return "toString";
}
static staticFun() {
return "static";
}
}
class Son extends Person {
constructor(x, y, color) {
super(x, y); //子類必須在 constructor 方法中呼叫 super 方法,否則新建例項時會報錯。
this.z = 2;
this.a = 4;
super.a = 5;
this.color = color;
console.log(super.a) //undefined
console.log(this.a); // 5
}
// toString() { // 這是一個類的方法,注意前面沒有function
// return this.color + ' ' + super.toString(); // 呼叫父類的toString()
// }
}
let son1 = new Son(1, 1, "red");
console.log(son1.toString(),Son.staticFun())//toString,static
console.log(son1 instanceof Son, son1 instanceof Person) //true true
參考:(侵立刪)
1、js繼承的6種方式
2、js 總結ES6中Class以及繼承