[JS] Symbols 的使用| PJCHENder 未整理筆記

文章推薦指數: 80 %
投票人數:10人

ES6 引入了一種新的原始數據(primitive type)類型 Symbol ,表示獨一無二的值。

它是JavaScript 語言的第七種數據類型,前六種是: Undefined ... Skiptomaincontent這個網站放置的是未發佈或未完整整理的筆記內容,若想檢視正式的筆記內容請到PJCHENder那些沒告訴你的小細節。

PJCHENderOfficialDocsBlogGitHubFacebookLinkedin🌜🌞SearchOnthispageletuniqueSymbol=Symbol('');letsharedSymbol=Symbol.for('');Symbol.keyFor('');//取得該Symbol的KeyCopy觀念​ES6引入了一種新的原始數據(primitivetype)類型Symbol,表示獨一無二的值。

它是JavaScript語言的第七種數據類型,前六種是:Undefined、Null、Boolean、String、Number、Object。

透過symbol建立的值都是獨特的(unique),因此可以作為獨特不重複的物件屬性名稱。

以Symbol為鍵的物件屬性與陣列元素類似,不能被類似obj.name的點運算符存取,你必須使用方括號[]訪問這些屬性。

Symbol作為屬性名,該屬性不會出現在for...in、for...of迴圈中,也不會被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。

但是,它也不是私有屬性,有一個Object.getOwnPropertySymbols方法,可以獲取指定對象的所有Symbol屬性名。

另一個新的API,Reflect.ownKeys方法可以返回所有類型的鍵名,包括常規鍵名和Symbol鍵名。

由於以Symbol值作為名稱的屬性,不會被常規方法遍歷得到。

我們可以利用這個特性,為對象定義一些非私有的、但又希望只用於內部的方法。

建立Symbol​建立Symbol不需要new。

:letsymbol=Symbol('');console.log(typeofsymbol);//symbolCopySymbol(),Symbol.for(),Symbol.keyFor()​我們希望重新使用同一個Symbol值,Symbol.for方法可以做到這一點Symbol():內部會建立一個獨特的id(uniqueid),兩個相同key的Symbol是不同的,且無法透過Symbol.keyFor()找到。

Symbol.for():一樣都會生成新的Symbol,但兩個相同key的Symbol會是相同的(reusedid),且可以透過Symbol.keyFor()找到。

Symbol.keyFor()方法返回一個已登記的Symbol類型值的key。

/***Symbol()每次都是新的,兩次生成的並不"相同",無法在全域被搜尋。

*Symbol.for()兩次生成的會是相同的,可以在全域被Symbol.keyFor()搜尋到。

**/leta=Symbol('SymbolA');letaa=Symbol('SymbolA');letb=Symbol.for('SymbolB');letbb=Symbol.for('SymbolB');a===aa;//falseb===bb;//trueCopy透過Symbol.keyFor()取得某登記過的symbol鍵名/***使用Symbol.keyFor()查看某一變數的Symbol**/Symbol.keyFor(a);//undefinedSymbol.keyFor(aa);//undefinedSymbol.keyFor(b);//SymbolBSymbol.keyFor(bb);//SymbolBCopySeethePenES6SymbolDemoCodebyPJCHEN(@PJCHENder)onCodePen.給予物件Symbol​varmySymbol=Symbol();//第一種寫法vara={};a[mySymbol]='Hello!';//第二種寫法vara={[mySymbol]:'Hello!',};//第三種寫法vara={};Object.defineProperty(a,mySymbol,{value:'Hello!'});//以上寫法都得到同樣結果a[mySymbol];//"Hello!"Copy取得物件中的Symbol​Symbol是無法透過疊代的方式(例如for...in)或getOwnPropertyNames,Object.keys()取得可以使用Object.getOwnPropertySymbols(obj)或Reflect.ownKeys()取得物件的Symbol:varobj={name:'Aaron',};vara=Symbol('aaa');varb=Symbol('bbb');obj[a]='Hello';obj[b]='World';/***obj*{*name:"Aaron",*Symbol(aaa):"Hello",*Symbol(bbb):"World"*}**//***可以取得Symbols的方式**///使用Object.getOwnPropertySymbols()取得物件的SymbolObject.getOwnPropertySymbols(obj);//[Symbol(a),Symbol(b)]//使用Reflect.ownKeys()取得物件所有的keyReflect.ownKeys(obj);//["name",Symbol(aaa),Symbol(bbb)]/***無法取得Symbols的方式**///無法使用Object.keys()取得SymbolObject.keys(obj);//無法使用for...in取得Symbolfor(letpropinobj){console.log(`${prop}:${obj[prop]}`);//name:Aaron}//無法使用Object.getOwnPropertyNames()取得SymbolObject.getOwnPropertyNames(obj);//['name']CopySeethePenES6SymbolDemoCode-2byPJCHEN(@PJCHENder)onCodePen.使用範例​sharedSymbol​/***SharedSymbols**/letsymbolGlobal=Symbol.for('shared');/***透過dynamicproperty的方法把symbol設成key**/letperson={firstName:'Aaron',lastName:'Chen',};functionregisterMember(memberObj){//在function中設定的symbol一樣可以影響到外層的letsymbolScope=Symbol.for('shared');memberObj[symbolScope]='secret';person[symbolGlobal];//secretperson[symbolScope];//secret}registerMember(person);person[symbolGlobal];//secretperson[symbolScope];//symbolScopeisnotdefinedCopyDemoCode@JSFiddleSymbolinJavaScript​在JavaScript有許多內建好的Symbol,這些Symbol通常包含JS中內建好的方法,我們可以到MDN中看這些方法WellKnownSymbols。

如果我們修改內建Symbol所提供的方法,將可以變更原生的方法:/***ChangeOriginalFunctionofJavaScript**/letnumber=[1,2,3];number[Symbol.toPrimitive]=function(){return999;};console.log(number+1);//原本會回傳"1,2,31";在修改後會回傳1000Copy參考資料​ECMAScript6入門Symbol@MDNPrevious«[JS]switchcaseNext[JS]tips»觀念建立SymbolSymbol(),Symbol.for(),Symbol.keyFor()給予物件Symbol取得物件中的Symbol使用範例SymbolinJavaScript參考資料



請為這篇文章評分?