並查集(學習)
阿新 • • 發佈:2021-01-09
建構函式的特點:封裝, 繼承, 多型
繼承: 子類獲取父類的屬性和方法的過程
1. 原型鏈的繼承
讓一個引用型別繼承另一個引用型別的屬性和方法
//父級
//建構函式
function Person(name,sex){
this.name=name; //屬性
this.sex=sex;
this.poop=function(){ //方法
console.log('hi')
}
}
//原型
Person.prototype.hobby=["11","22"]
Person. prototype.say=function(){
console.log('hello')
}
//繼承的子級
function Student(){}
Student.Pertotype=new Person('小白','男')
//例項化物件
var stu1=new Student();
var stu2=new Student();
優點:
可以把父級原型的屬性和方法繼承過來,簡單,易於實現
缺點:
1. 在父級建構函式中繼承過來的屬性值是一樣的,無法實現多繼承
(通過原型來實現繼承時,原型會變成另一個型別的例項,原先的例項屬性變成了現在的原型屬性
該原型的引用型別屬性會被所有的例項共享。)
2. 無法給父級建構函式傳參
(在建立子型別的例項時,沒有辦法在不影響所有物件例項的情況下給超型別的建構函式中傳遞參)
2. 建構函式繼承
在子型別的建構函式中呼叫父型別建構函式
//父級
function Person(name,sex){
this.name=name; //屬性
this.sex=sex;
}
Person.prototype.say=function(){
console.log('hi')
}
function Student(name,sex){
Person.call(this,name,sex)
}
var stu = new Student('小白',18,'男')
console.log(stu)
優點:
可以繼承父級建構函式中的屬性,並可以賦值
(相當於複製父類的例項給子類,沒有用到原型)
缺點:
父級原型的屬性和方法訪問不到
(只能使用父類的屬性和方法,不能繼承原型的屬性和方法)
3. 組合繼承(原型鏈+借用建構函式)
使用原型鏈實現對原型屬性和方法的繼承,通過借用建構函式來實現對例項屬性的繼承
//父級
function Person(name,sex){
this.name=name; //屬性
this.sex=sex;
}
Person.prototype.say=function(){
console.log('hi')
}
//子類
function Student(name, sex){
Person.call(this,name,sex) //建構函式繼承
}
Student.prototype=new Person(); //原型鏈繼承
var stu=new Student('小白',"男") //例項化物件
缺點:
什麼情況都會呼叫兩次超型別的建構函式,一次建立子類原型,一次在子型別建構函式內部
優點:
1. 可以向超類傳遞引數
2. 每個例項都有自己的屬性
3. 實現了程式碼複用
4. 原型式繼承
ES5 通過新增 Object.create()方法規範了原型式繼承
function object(obj) {
//自定義一個建構函式
function Per(){}
//把傳入的obj物件賦給 建構函式的原型
//這樣原型方法中有了共有的屬性
Per.prototype = obj;
return new Per();
}
var Per={
name:'小白',
arr:["11","22","33"]
}
//將Per通過形參傳到object函式中
var aa = object(Per)
console.log(aa)
//列印結果就是
Per {}
__proto__:
arr: (3) ["11", "22", "33"]
name: "小白"
__proto__: Object
缺點:跟原型鏈實現繼承一樣,包含引用型別值的屬性會被所有例項共享
5. 寄生式繼承
是與原型式繼承緊密相關的一種思路,建立一個僅用於封裝繼承過程的函式,
該函式在內部以某種方式來增強物件,最後再返回物件
function object(o){
function F() {}
F.prototype = o;
return new F();
}
function creObj(val){
var clone = object(val); //通過呼叫函式建立一個新物件
clone.say = function () { //以某種方式來增強這個物件
console.log("Hi");
};
return clone; //返回這個物件
}
var person = {
name:"李白",
friends:["杜甫","陸游"]
};
var aa = creObj(person)
aa.say(); //Hi
缺點:
使用寄生式繼承來為物件新增函式,不能做到函式複用而效率低下
含引用型別值的屬性會被所有例項共享
6. 寄生組合式繼承
借用建構函式來繼承屬性,通過原型鏈的混成形式來繼承方法
//父類
function Person(name){
this.category = 'human';
this.legNum = 2;
this.name = name;
}
Person.prototype.sayHello = function(){
console.log('Hi,i am ' + this.name);
}
//定義要繼承的方法
function inherit(subType,superType){
//在new inheritFn 的時候將建構函式指向子類
function inheritFn(){this.constructor = subType}
inheritFn.prototype = superType.prototype;
//將子類的原型指向父類原型的一個副本
subType.prototype = new inheritFn();
}
//定義子類建構函式Pan
function Pan(name,age){
Person.call(this,name); //借用建構函式
this.age = age;
}
//將子類Pan的原型指向父類Person原型的一個副本
//注意:要執行該動作後才能在Pan的prototype上定義方法,否則沒用
inherit(Pan,Person);
Pan.prototype.sayAge = function(){
console.log(this.age);
}
//定義子類建構函式Duan
function Duan(name,hairColor){
Person.call(this,name);
this.hairColor = hairColor;
}
inherit(Duan,Person);
Duan.prototype.showHairColor = function(){
console.log(this.hairColor);
}
優點:
只調用了一次超類建構函式,效率更高
7. ES6 類實現繼承
//class 相當於es5中建構函式
//class中定義方法時,前後不能加function,全部定義在class的protopyte屬性中
//class中定義的所有方法是不可列舉的
//class中只能定義方法,不能定義物件,變數等
//class和方法內預設都是嚴格模式
//es5中constructor為隱式屬性
class P7 extends School1{
constructor(name) {
super(name)
// this.type = "我們都是帥逼"
}
}
var className = new P7('小白')
console.log(className)