從新看紅皮書,以爲不少知識多看幾遍確實是能看的更明白些。今天重溫了一下對象建立和繼承,就稍微記下來,鞏固一下。編程
js是面向對象的編程語言,ECMA-262吧對象定義爲:「無序屬性的集合,其屬性能夠包含基本值,對象或者函數」。每一個對象都是基於一個引用類型建立的,這個引用類型能夠是原生類型,也能夠是自定義的。編程語言
一,講講建立對象的幾個方法函數
1. var person = new Object(); 優化
2. var person = {};this
3. 工廠模式prototype
4. 構造函數模式指針
5. 原型模式對象
6. 組合使用構造函數模式和冤案型模式blog
7. 動態原型模式繼承
8.等等......
這裏着重記一下構造模式和原型模式,畢竟以後的模式和繼承方法都是因爲這兩個的優缺點借鑑而來。
4.構造函數模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
console.log(this.name);
};
}
var person1 = new Person('niko','19','FE');
這種方式建立對象,能夠將它的實例化標識爲一中特定類型。及實例能夠經過 instanceof 或者constructor 來檢測對象的類型。缺點是沒法完成方法的複用,即每一個方法都須要在實例化上從新建立。
5.原型模式
咱們天然是但願建立對象時能夠共享某些屬性和方法,搞這個原型模式挺拿手的~~~來露個臉。簡單的說,咱們建立的每一個函數都有一個prototype屬性,這個prototype屬性是一個指針,指向一個對象,這個對象裏面放着建立的這個對象實例的原型對象。原型對象,便是包含全部實例都共享的屬性和方法。默認狀況下,全部原型對象都自動得到一個constructor屬性,這個屬性包含一個指向prototype屬性所在函數的指針。繞來繞去估計就暈了,來個圖解釋一下。
經過原型模式建立對象以後,是能夠順順利利的完成屬性和方法的共享,可是也是有弊端的若是包含引用類型的值,那麼實例化的某一個對象對這個值進行操做,就會修改原型裏的值,這樣問題就比較麻煩了。因此組合模式就出現了,及用構造函數來建立屬性,用原型模式來建立共享方法。
7.動態原型模式,就是把全部信息封裝到函數裏看着會簡潔好多,也是組合了構造函數和原型模式的優勢,在函數內部初始化原型(僅僅在第一次運行時初始化)。
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName!= "function"){
Person.prototype.sayName = function(){
console.log(this.name);
};
}
}
var person1 = new Person('niko','19','FE');
跟組合模式不一樣的是,初始化原型在函數內部,而且若是有多個共享函數時,只判斷一個就好~~看着簡潔那麼一小丟~~對象建立就寫到這,接下來寫一下繼承啦啦啦啦~
二,常見的繼承方式
1.原型鏈
2.借用構造函數
3.組合繼承
4.組合寄生式繼承
5.原型式,寄生式..
挑幾個重要的講吧,重要的就是掌握原型鏈的原理,以及構造函數繼承方式,組合是採起了這兩個優缺點進行優化,組合寄生則是針對組合繼承進行的優化。原型、寄生式是對一個相對的對象來建立另外一個,沒怎麼碰到就不講了。
1.原型鏈
原型鏈的主要思想就是讓一個引用類型繼承另外一個引用類型的實例。原型對象將包含一個指向另外一個原型的指針,另外一個原型中也包含指向另外一個構造函數的指針。層層遞進以後,造成原型鏈。
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function Subtype(){
this.subproperty = false;
}
Subtype.prototype.getSubValue = function(){
return this.subproperty;
}
Subtype.prototype.getSubValue = function(){
return this.subproperty;
};
var instance = new Subtype();
啊,寫到一半忽然要閉館了閉館了閉館了=.=淚奔一下 ,中間詳細就不解釋了,看懂這個圖就沒啥大問題了~原型鏈的問題就是,共享引用類型值的時候,修改一個實例就會修改原型。
2.借用構造函數
這個方法就是在子類構造函數中調用超類的構造函數。
function SuperType(name){
this.name = name;
}
function SubType(){
SuperType.call(this,'niko'); //在this的做用域中調用SuperType()
}
var instance = new SubType();
這種方式不像原型繼承,至關於在子類的做用域中吧超類的屬性完徹底全複製了一份。由於不是引用的指針,因此,即便是引用類型的屬性值,每一個實例都會複製一份屬性值,因此不會有什麼問題噠~~~並且借用構造函數模式能夠在子類中傳參。
3.組合繼承就是兼顧了原型模式和借用構造函數模式的優缺點。既能夠共享方法,也可讓不一樣的實例分別有本身的屬性。
function SuperType(name){
this.name = name;
this.colors = ['red','blue','orange'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
//繼承屬性
SuperType.call(this,name); //第二次調用SuperType()
this.age = age;
}
SubType.prototype.sayAge = function(){
console.log(this.age);
}
//繼承方法
SubType.prototype = new SuprType(); //第一次調用SuperType();
var instance = new Subtype('niko',34);
如圖所示,第一次調超類的時候,SubType.prototype獲得兩個屬性:name,colors。調用Subtype構造函數時,第二次調用超類,在新對象上建立實例屬性:name,colors。這兩個實例屬性屏蔽了原型中的屬性。
這種方法能夠達到既能夠共享方法,也能夠有本身的實例屬性,可是調用兩次超類的構造函數。
4.寄生組合式繼承
爲了解決組合式的缺點,寄生組合式這個超級大Boss上場了。
大致思路仍是借用構造函數來繼承屬性,用原型鏈的混成方法機場方法。與組合 方式不一樣的是,沒有在子類中調用超類,而是取得了一個超類的副本。
function inhertiPrototype(subType,superType){ var prototype = object(superType.prototype); //建立對象 prototype.constructor = subType; //加強對象 subType.prototype = prototype; //指定對象 }