面向?qū)ο缶幊?/h3>
Paste_Image.png
Paste_Image.png
一段完整的創(chuàng)建類的示例
// 如何創(chuàng)建一個類肪康,包含有:靜態(tài)屬性方法名扛,公有私有屬性方法陈醒?
var Book = (function(){
// 靜態(tài)私有變量
var bookNum = 0;
// 靜態(tài)私有方法
function checkName(name){}
var _book = function(id, newName, newPrice){
// 安全模式抚岗,防止未使用new操作符
if(this instanceof _book){
// 私有變量 方法
var name, price; function checkID(){}
// 共有屬性,方法
this.id = id;
this.getName = function(){ return name; };
this.getPrice = function(){ return price; };
this.setName = function(name){ name = name; };
this.setPrice = function(price){ price = price; };
console.log(++bookNum);
this.setName(newName);
this.setPrice(newPrice);
}
else{
return new _book(id, name, price);
}
};
_book.prototype = {
// 靜態(tài)公有屬性
isJSBook: false,
// 靜態(tài)共有方法
displayName: function(){
console.log(this.getName());
}
};
return _book;
}());
使用關(guān)閉包定義靜態(tài)私有變量與方法鱼鼓,所有實例創(chuàng)建過程中都能訪問到
Paste_Image.png
創(chuàng)建實例時孝常,打印出累加之后的bookNum
當(dāng)替換Book(即_book)的原型之后,之前創(chuàng)建的實例指向的原型并不會改變蚓哩,之后在之后創(chuàng)建Book實例時運用新的原型
Paste_Image.png
觀察b3构灸、b4的原型
當(dāng)在原來的原型上變更之后,通過該原型創(chuàng)建的實例都能應(yīng)用變更之后的原型
Paste_Image.png
這里定義重復(fù)了,原型上的getPrice方法將會被實例自身擁有的getPrice方法掩蓋住
繼承
- 方式一:類式繼承: 通過將子類的原型指定為父類的實例
function SuperClass(){
this.superValue = true;
}
SuperClass.prototype.getSuperValue = function(){
return this.superValue;
};
function SubClass(){
this.subValue = true;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getSubValue = function(){ return this.subValue;};
Paste_Image.png
缺點:
1喜颁、如果父類中存在引用類型屬性稠氮,則會被所有子類共用,一個子類修改之后將會影響到所有子類
2半开、無法在實例化時為父類傳遞初始化參數(shù)
- 方式二: 構(gòu)造函數(shù)繼承: 在子類構(gòu)造函數(shù)中通過call或者apply調(diào)用父類的構(gòu)造函數(shù)隔披,實現(xiàn)繼承父類定義的屬性方法
function SuperClass(id){
this.books = ['js', 'css', 'html'];
this.id = id;
}
SuperClass.prototype.showBooks = function(){
console.log(this.books.join());
};
function SubClass(id){
SuperClass.call(this, id);
}
Paste_Image.png
缺點:
1、子類沒有繼承父類的原型
2寂拆、每個實例化出來的子類對象都會單獨擁有一份父類上定義的屬性方法奢米,無法復(fù)用父類的屬性或者方法
- 方式三: 組合繼承: 方式一與方式二的組合模式
function SuperClass(name){
this.name = name;
this.books = ['js', 'css','html'];
}
SuperClass.prototype.getName = function(){
console.log(this.name);
};
function SubClass(name, time){
SuperClass.call(this, name);
this.time = time;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getTime = function(){ console.log(this.time);}
Paste_Image.png
缺點:
1、父類構(gòu)造函數(shù)執(zhí)行了兩遍
2纠永、子類實例化出來的對象原型中重復(fù)了一次父類構(gòu)造函數(shù)中的屬性方法
- 方式四: 原型式繼承: 使用過渡函數(shù)作為構(gòu)造函數(shù)鬓长,傳入的對象作為過渡函數(shù)的原型
function inheritObject(o){
function F(){}
F.prototype = o;
return new F();
}
缺點:
跟方式一有相同的缺點
- 方式五: 寄生式繼承: 在方式四的基礎(chǔ)上進(jìn)行二次封
function createBook(obj){
var o = inheritObject(obj);
o.getName = function(){
console.log(this.name);
};
return o;
}
Paste_Image.png
- 方式六: 寄生組合式繼承: 寄生式繼承跟夠構(gòu)造函數(shù)繼承的組合
function inheritPrototype(SubClass, SuperClass){
var p = inheritObject(SuperClass.prototype);
p.constructor = SubClass;
SubClass.prototype = p;
}
function SuperClass(name){
this.name = name;
this.books = ['js', 'css','html'];
}
SuperClass.prototype.getName = function(){
console.log(this.name);
};
function SubClass(name, time){
SuperClass.call(this, name);
this.time = time;
}
inheritPrototype(SubClass, SuperClass);
SubClass.prototype.getTime = function(){ console.log(this.time);
}
Paste_Image.png
子類添加原型方法只能在現(xiàn)有原型上一個添加
整個過程:先定義子類及父類與父類原型,然后子類原型引用父類的原型對象尝江,然后子類在添加自己的原型方法涉波,最后調(diào)用父類構(gòu)造函數(shù)