[第十七週] JavaScript 進階:物件導向(new、super、封裝)
文章推薦指數: 80 %
物件導向的寫法: ES5 VS ES6. 在ES6 之後,開始有了Class 這個語法糖可以使用,可以比較看看兩種不同版本的物件導向寫法: ...
[第十七週]JavaScript進階:物件導向(new、super、封裝)
物件導向的寫法:ES5VSES6
在ES6之後,開始有了Class這個語法糖可以使用,可以比較看看兩種不同版本的物件導向寫法:
ES6:Class
classDog{
constructor(name){
this.name=name;
}
sayHello(){
console.log(this.name,'Hello');
}
}
consthappy=newDog('happy');
happy.sayHello();
constwhite=newDog('white');
white.sayHello();
ES5:建構函式+prototype
functionDog(name){
this.name=name;
}
Dog.prototype.sayHello=function(){
console.log(this.name,'Hello');
}
consthappy=newDog('happy');
happy.sayHello();
constwhite=newDog('white');
white.sayHello();
new關鍵字:模擬new在背後幫你做的事
在ES5時,通常是把function當成constructor來用,稱為「建構函式」,而共用的method則會放在prototype新增,可以避免在每個instance重複新增內容一樣的method。
而關鍵在於new關鍵字,用new出來的function,JS會在背後幫你做好一連串的機制。
下例是ES5的OOP寫法:
functionDog(name){
this.name=name;
}
Dog.prototype.sayHi=function(){
console.log(this.name,'Hi');
}
constwhite=newDog('white');
用上面這個例子,來描述關鍵字new在背後到底做了什麼?
接下來以一個自己寫的functionnewDog('yello'),來模擬newDog('yello')在做的事:
constyello=newDog('yello');
white.sayHi();
yello.sayHi();
首先目的是通過自己寫的newDog產生一個instanceyello,希望這個instance會有跟用new出來的instancewhite有一樣的屬性跟方法。
所以目標放在如何寫出newDog()來模擬new這個關鍵字背後做的事情。
functionnewDog(name){
constobj={};//1.
Dog.call(obj,name);//2.
obj.__proto__=Dog.prototype;//3.
returnobj;//4.
}
/*
new背後做的事:
1.產生一個新object=>obj
2.把Dog當作constructor,將this指向obj,同時把參數name丟進去
=>因為Dog只有一個參數所以用call,如果是兩個以上的參數就可以用apply放陣列
3.將obj.__proto__指向Dog.prototype
4.回傳obj
*/
繼承:super
在ES6使用繼承時,當要改寫子類別的constructor時,記得要先用super()父類的constructor,不然會跳出錯誤:Mustcallsuperconstructorinderivedclassbeforeaccessing'this'orreturningfromderivedconstructor。
classDog{
constructor(name){
this.name=name;
}
sayHi(){
console.log(this.name,'Hi');
}
}
classTaiwansDogextendsDog{
constructor(name){
super(name);//=>記得要先super()
this.sayHi();
}
}
constwhite=newDog('white');
constblack=newTaiwansDog('black');
練習封裝:實現privateproperty的幾種嘗試
之前這篇筆記:什麼是閉包Closure與實際應用裡,Closure最後一個wallet範例是說明Closure可以達到封裝的目的,讓我想到之前看YT上的JavaScriptOOP教學。
varmoney=100;
functionadd(num){
money+=1;
}
functiondeduct(num){
if(num>10){
num-=10;
}
else{
money-=num;
}
}
add(1);
deduct(30);
console.log(money);//91
在ES5要實現Class中的私有屬性,也是在function(建構函式)內部宣告一個變數,之後再利用用getter&setter去存取privateproperty。
那後來又想著,那到底要如何在ES6中的Class實現private屬性呢?
查了一下PrivatepropertiesinJavaScriptES6classes,第2,3個回答得到不少啟發,尤其是第3個列舉了不同方法跟說明,認識到Symbols類型,雖然不是真正意義上的private,但還是滿酷的!
想說練習一下,直接把wallet範例把多餘的method刪掉,改成以下三種:
ES5-function模擬Class版(realprivate)
ES6-constructor版(realprivate)
ES6-Symbols版(halfprivate)
1.ES5-function模擬Class版(realprivate)
很標準的ES5封裝方法。
functionWallet(init){
letmoney=init;
this.getMoney=function(){
returnmoney;
}
};
constwallet=newWallet(100);
console.log(wallet.getMoney());
console.log(wallet.money);//=>存取不到,真正的private
2.ES6-constructor版(realprivate)
需要存取privateproperty的method都只能放在constructor裡面,是可以正常運作,但感覺不太對勁
classWallet{
constructor(num){
var_money=num;
this.getMoney=()=>_money;
this.setMoney=(newNum)=>_money=newNum;
}
};
constwallet=newWallet(100);
console.log(wallet.getMoney());
console.log(wallet._money);//=>存取不到,真正的private
3.ES6-Symbols版(halfprivate)
就是看著範例用,沒有深究,只覺得新語法很酷
varmoney=Symbol();
classWallet{
constructor(num){
this[money]=num;
}
getMoney(){
returnthis[money];
}
};
constwallet=newWallet(100);
console.log(wallet.getMoney());
console.log(wallet[money]);//=>還是存取得到,不是真正的private
結論
所以在ES6實現privateproperty最方便的寫法是什麼?
沒有。
對,真的就是沒有。
而如果ES7的支援性越來越高,要實現privateproperty就有更方便的#關鍵字可以用,但現在ES6還沒有看到通用的方法,最簡單的方法其實可以再privatepropertyormethod的名稱加上_前綴,同事們可以很簡單看出這是個私有屬性,沒事不要去動它。
(以上內容大部分是程式導師實驗計畫第三期的學習筆記,如有錯誤歡迎糾正,非常感謝🤓)
Writtenon
August
11th,
2019
byYakimshu
Feelfreetoshare!
Youmayalsoenjoy:
[第十七週]JavaScript進階:為什麼要有原形鍊PrototypeChain?
[第十七週]JavaScript進階:出乎意料的this
[第十七週]JavaScript進階:從作用域鍊ScopeChain來理解Closure原理
[第十七週]JavaScript進階:什麼是閉包Closure與實際應用
[第十七週]JavaScript進階:從EC來理解Hoisting
[第十七週]JavaScript進階:打好基礎的第一步,從了解什麼是EC開始
[第十七週]JavaScript進階:Primitive&Object原始類型與物件的差異
延伸文章資訊
- 1[JS] JavaScript 類別(Class) | PJCHENder 未整理筆記
在ES6 中可使用關鍵字 class 和 constructor(self) : ... 透過class field syntax 的寫法,一樣可以用來建立公開(public)或私有(priva...
- 2[第十七週] JavaScript 進階:物件導向(new、super、封裝)
物件導向的寫法: ES5 VS ES6. 在ES6 之後,開始有了Class 這個語法糖可以使用,可以比較看看兩種不同版本的物件導向寫法: ...
- 3JavaScript Class (類別) - Shubo 的程式開發筆記
這篇文章將會解釋JavaScript class 的觀念以及使用方法,包含class ... 及 super 的寫法,以及如何使用static method/class function (靜態...
- 4[JS]類別(class)
[JS]類別(class) [Class 的基本 ... JavaScript ES6 class 關鍵字 ... 都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的...
- 5ES6 class 關鍵字- JavaScript (JS) 教學Tutorial - Fooish 程式技術
JavaScript ES6 class 關鍵字. 在ES6 中,引入了Class (類別) 這個新的概念(如果寫過C++ 或Java 等傳統語言應該非常熟悉),透過 class 這新的關鍵字,...