首先,為什么說叫所謂呢?因為在2007年之前Js給予我們typeof解析數據類型的一共有六種(一直有爭議,但是我們暫時就按typeof來算)

'function'
'Number'
'Object'
'boolean'
'String'
'undefined'
但當我們去 typeof Symbol () 的時候,會驚奇的發現,返回了一個‘symbol’
首先肯定要有疑問,這貨是啥?當然第一種想法其實就是肯定很強大。因為前六種已經強大的一種地步了,這貨肯定也一定非常強大。首先我們先帶著我們的好奇心一步一步來看看這個鬼東西。首先先驗證一下它是不是對象。通過我先說一下我對對象研究的他有三種機制:只要是對象就可以引用。
只要是對象都可以賦予私有屬性。
對象都不相等。
var s1 = Symbol.for('abc');
var s2 = Symbol.for('abc');
Symbol() === Symbol() //false
s1 === s2 //true
Symbol.keyFor(s1)// 'abc'
當然這兩個看起來比較容易 似乎就是一個賦予一個值然后就會把原來的值吐出來,當然真是原來的值么?帶著這樣的疑問我又繼續做了一些實驗。var s1 = Symbol.for([1,2,3]);
Symbol.keyFor(s1); // "1,2,3" 字符串的 1,2,3
var s1 = Symbol.for(function (){});
Symbol.keyFor(s1); "function (){}" 字符串的fn;
你會發現這貨你存的東西只會以字符串的東西吐出來。當然這個東西官方說由于每一個 Symbol 值都是不相等的,這意味著 Symbol 值可以作為標識符,用于對象的屬性名,就能保證不會出現同名的屬性。這對于一個對象由多個模塊構成的情況非常有用,能防止某一個鍵被不小心改寫或覆蓋。也就是說可以作為存在 json 中讓 key 永遠不相等。OK ,那么就完全可以這樣: var a = {};
a[Symbol()]= 'Hello!';
a[Symbol()]= 'Hello!';
a[Symbol()]= 'Hello!';
console.log(a);
Object
Symbol(): "Hello!"
Symbol(): "Hello!"
Symbol(): "Hello!"
__proto__: Object
你會發現出現了連續的三個 a的屬性 都是hello 并且沒有覆蓋 。也就是說這么寫的話可以有效的防止其json重名問題,不過拿起來就非常費勁了。 for(var i in a){
console.log(i +',' +a[i]) //沒有任何的東西
}
當然這就比較可以可疑了,json 用 symbol 存上東西了,但是又用 for in 拿不到。也就說如果直接這么賦值 json 認,但是 for in 循環不認,而且咱們也拿不到。但是換一種方式就沒問題了。用變量存的話,雖然雖然 for in 拿不到,但是咱們可以拿到值。var a = Symbol('aaa');
b = {};
b[a] = 10 ;
console.log(b[a])//10
輕松拿到值。其實不難看出來 Symbol 對 for in 不是很友好,但是 對 json 很友好。這時如果使用別的方法拿值呢?顧名思義,Object.getOwnPropertyNames() 是拿對象私有屬性的的方法,我們來試試。 let b = {};
b[Symbol()]=10;
b[Symbol()]=15;
Object. getOwnPropertyNames(b) //
可以理解為:其實 Symbol 不作為 b 的私有屬性存在。拿能不能拿到呢?其實也能拿到。他提供了一個 getOwnPropertySymbols 方法可以讓我找到存在內存里的 Symbol 。例如: let a = {};
a[Symbol()]=10;
a[Symbol()]=15;
Object.getOwnPropertySymbols(a) //[Symbol(),Symbol()] //這里面以數組的形式返回了 咱們使用的兩個Symbol();
Object.getOwnPropertySymbols(a)[0]//Symbol() 第一個Symbol()
a[Object.getOwnPropertySymbols(a)[0]]//10 拿到存在的這個值。
其實知道是數組后 我們就可以循環? obj.getOwnPropertySymbols(a) 這個東西 然后輸出值了。其實說回來只是換了一種方法拿值,存值。而這種方法更安全更隱蔽而已。而Symbol還有一些比較特殊的特性。js中的~(按位非) 是一個比較強勢的轉換number的東西。例如:~NaN //-1
~function (){}//-1
~undefined //-1
var a = function (){};
~a() //-1
~new a() //-1
基本任何東西都能轉成number,而:~Symbol //-1
~Symbol() //報錯
似乎說明了 其跟function 有著本質的區別,另外呢,Symbol值不能與其他類型的值進行運算,會報錯。var sym = Symbol('My symbol');
"your symbol is " + sym // TypeError: can't convert symbol to string es5之前的報錯
`your symbol is ${sym}` // TypeError: can't convert symbol to string es6字符串照樣的報錯
另外,Symbol值也可以轉為布爾值,但是不能轉為數值。這些都是Symbol的一些小特性。var sym = Symbol();
Boolean(sym) // true
!sym // false
Number(sym) // TypeError
sym + 2 // TypeError
其實來說Symbol作為一個新的數據類型 最強的而不是干以上的這些事而是一些配合原型方法的一些開關,可以強化方法的使用。比如說 Symbol.isConcatSpreadable 這個方法,咱們都知道 正常的數組concat方法是連接字符串。let arr = ['c', 'd'];
['a', 'b'].concat(arr2,'e') //['a','b','c','d','e'];
而我們一旦把開關打開后會發現一些意想不到的結果。let arr2 = ['c', 'd'];
arr2[Symbol.isConcatSpreadable] = false;
['a', 'b'].concat(arr2, 'e') //['a','b',['c','d'],'e']
會發現以數組的形式插入到里面了。當然他還包括了一些別的方法,例如,他可以測試 ES6 新增的內置對象方法 Symbol.toStringTag 。JSON[Symbol.toStringTag]:'JSON'
Math[Symbol.toStringTag]:'Math'
Module對象M[Symbol.toStringTag]:'Module'
ArrayBuffer.prototype[Symbol.toStringTag]:'ArrayBuffer'
DataView.prototype[Symbol.toStringTag]:'DataView'
Map.prototype[Symbol.toStringTag]:'Map'
Promise.prototype[Symbol.toStringTag]:'Promise'
Set.prototype[Symbol.toStringTag]:'Set'
%TypedArray%.prototype[Symbol.toStringTag]:'Uint8Array'等
WeakMap.prototype[Symbol.toStringTag]:'WeakMap'
WeakSet.prototype[Symbol.toStringTag]:'WeakSet'
%MapIteratorPrototype%[Symbol.toStringTag]:'Map Iterator'
%SetIteratorPrototype%[Symbol.toStringTag]:'Set Iterator'
%StringIteratorPrototype%[Symbol.toStringTag]:'String Iterator'
Symbol.prototype[Symbol.toStringTag]:'Symbol'
Generator.prototype[Symbol.toStringTag]:'Generator'
GeneratorFunction.prototype[Symbol.toStringTag]:'GeneratorFunction'
不過,用 ES5 之前的方法依然也可以檢驗出來內置對象,所以 Symbol 就是更規范化而已,就用 map 舉例。Object.prototype.toString.call(new Map())//'[object Map]'
別的內置對象也是同理。Symbol.unscopables 也是Symbol一個比較有意思的東西。可以找到對象內哪些屬性被with排除。Object.keys(Array.prototype[Symbol.unscopables])//['copyWithin', 'entries', 'fill', 'find', 'findIndex', 'keys']
以數組的形式返回 也就是說 這些屬性會被with排除。其實這些只是Smybol的冰山一角,更多的是Symbol是服務于ES6中。讓我們繼續慢慢探索好了。
