7天搞懂JS進階議題(day05)-getter & setter: 屬性描述器
文章推薦指數: 80 %
7天搞懂JS進階議題(day05)-getter & setter: 屬性描述器. February 27, 2020. 本系列文章討論JS 物件導向設計相關的特性。
不含CSS,不含HTML! 建議先有些JS基礎再 ...
本系列文章討論JS物件導向設計相關的特性。
不含CSS,不含HTML!建議先有些JS基礎再繼續閱讀。
你也可以看看從零開始遲來的Web開發筆記雖然是「7天寫作松」挑戰,但同樣可以視為系列後續文章NoCSS!NoHTML!NoBrowser!Justneedprogramminglanguage有了物件然後呢?今天來說說關於成員(field/attribute/member)背後的屬性。
getter&setter有一個家族–神崎家,生了一個小孩叫アリア,但生下後被りこ偽裝,被發現後重新命名為アリア。
如有雷同存屬巧合var神崎家=class{
constructor(name){
this.__name=`神崎・${name}`;
}
staticborn(name){
returnnew神崎家(name)
}
setname(new_name){
this.__name=`神崎・${new_name}`;
}
getname(){
letfirst_name=this.__name.substr(0,2),
last_name=this.__name.substr(3,this.__name.length+1);
return`${first_name}・H・${last_name}`
}
introduce(){
console.log(`Hi~Mynameis${this.name}`)
}
rename(new_name){
this.name=new_name;
returnthis.name;
}
}
vararia=神崎家.born("アリア");
aria.introduce();//=>Hi~Mynameis神崎・H・アリア
aria.rename("りこ");//=>神崎・H・りこ
aria.introduce();//=>Hi~Mynameis神崎・H・りこ
aria.name="アリア";
aria.introduce();//=>Hi~Mynameis神崎・H・アリア
console.log(aria.name);//=>神崎・H・アリア
上例中,アリア的家族名是神崎,中間名是H。
而且アリア一生下來就會自我介紹。
並且可以看到,有著get描述器的函式,可以像是一般屬性一樣被存取;set可以在賦予值時做加工。
透過只給get不給set,還可以做到唯讀(readonly)屬性。
Object.defineProperty(神崎家.prototype,"first_name",{
get(){return"神崎"},
configurable:true,//僅為了之後測試方便
});
console.log(aria.first_name);//=>神崎
aria.first_name="遠山";
console.log(aria.first_name);//=>神崎
aria.__proto__.first_name="遠山";
console.log(aria.first_name);//=>神崎
沒人可以亂改家族名!為什麼我要加在神崎家.prototype上呢?不懂嗎?去看看關於PrototypeChain繼承作業-更靈活的first_name你做得到嗎?注意到一開始把"神崎"寫死,成了一個魔術數字(magicnumber)了嗎?你有辦法把上面例子改的更靈活更有彈性吧?透過改寫和Object.defineProperty加點工看看吧!部份程式碼可能如下:很顯眼?絕對不是因為我懶得刪程式碼是要給你提示拉!Object.defineProperty(神崎家.prototype,"first_name",{
get(){returnthis.__first_name||"神崎";},
set(v){this.__first_name=v;},
configurable:true,//僅為了之後測試方便
});
accessor除了getter和setter,還可以直接設定accessor,不過關鍵字是value:Object.defineProperty(aria,"weapons",{
value:["雙槍","雙劍"],
writable:true,
configurable:true,//僅為了之後測試方便
});
console.log(aria.weapons);//=>['雙槍','雙劍']
其實也差不多就等於:aria.rivals=["峰理子"];//對...就上面偽裝過アリア的人
defineProperty&getOwnPropertyDescriptor上面例子應該夠你使用Object.defineProperty了,還是不懂嗎?去參考一下更正式的文件吧!這以小節主要用Object.getOwnPropertyDescriptor1來看看上面設定的屬性。
首先看看一般直接設定的結果和accessor:Object.getOwnPropertyDescriptor(aria,"weapons");//=>
(點我看關於屬性描述器中的enumerable補充)再來看看getter和setter。
就不多J4了。
Object.getOwnPropertyDescriptor(aria.__proto__,"first_name");//=>
Object.getOwnPropertyDescriptor(aria,"weapons");//=>
不過可以先來看看Object.keys()的結果:console.log(Object.keys(aria));
//=>['__name','rivals']
可以看到並沒有weapons,因為enumerable:false。
既然keys()找不到,也大概可以理解為什麼迭代時找不到他了。
來用for-in試試:for(keyinaria){
console.log(`${key}:${aria[key]}`);
}
/*Output:
__name:神崎・アリア
rivals:峰理子
*/
不過有個例外:當key是symbol時,不管如何都無法迭代:Object.defineProperty(aria,Symbol("super_power"),{
value:["超級推理"],
writable:true,
enumerable:true,
configurable:true,//僅為了之後測試方便
});
s=Object.getOwnPropertySymbols(aria)
console.log(s);//=>[Symbol(super_power)]
console.log(aria[s[0]]);//=>['超級推理']
for(keyinaria){
console.log(`${key}:${aria[key]}`);
}
/*Output:
__name:神崎・アリア
rivals:峰理子
*/
雖然可以找得到這個屬性,但是迭代裡不會出現,也不會出現在keys()裡。
參考資料MDN:Object.getOwnPropertyDescriptor↩︎jsjavascriptECMAScriptcommentspoweredbyDisqus相關內容7天搞懂JS進階議題(day04)-Class&Constructor:吃語法糖別噎到7天搞懂JS進階議題(day03)-Function&Object:關於PrototypeChain繼承7天搞懂JS進階議題(day02)-new&factory:如何建立一個新物件7天搞懂JS進階議題(day01)-This&Bind:你不能不知道的7天搞懂JS進階議題(day00)-Oh...開始了......
延伸文章資訊
- 1setter - JavaScript - MDN Web Docs
最少要有一個參數(請參見Incompatible ES5 change: literal getter and setter functions must now have exactly ze...
- 2Property getters and setters - The Modern JavaScript Tutorial
Getters and setters ... Accessor properties are represented by “getter” and “setter” methods. In ...
- 3属性的getter 和setter - 现代JavaScript 教程
访问器属性由“getter” 和“setter” 方法表示。在对象字面量中,它们用 get 和 set 表示:. let obj = { get propName() { // 当读取obj.p...
- 4JS Getter 與Setter DAY71 - iT 邦幫忙::一起幫忙解決難題
Setter 與Setter Getter: 取得特定值的方法Setter: 存值的方法Getter var wallet = { total: 100, set save(price){ th...
- 5getter - JavaScript - MDN Web Docs
最少要有零個參數(請參見Incompatible ES5 change: literal getter and setter functions must now have exactly ze...