原始數據類型
- undefined
- null
- 布爾值(Boolean)
- 字符串(String)
- 數值(Number)
- Symbol
引用數據類型
- 對象(Object)
Symbol
ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。
創建方式
- Symbol()
- Symbol(參數)
注意
- Symbol函數前不能使用new命令,否則會報錯。這是因爲生成的 Symbol 是一個原始類型的值,不是對象。也就是說,由於 Symbol 值不是對象,所以不能添加屬性。基本上,它是一種類似於字符串的數據類型。
- Symbol函數可以接受一個字符串作爲參數,表示對 Symbol 實例的描述,主要是爲了在控制檯顯示,或者轉爲字符串時,比較容易區分。
由來
ES5 對象屬性名 都是 字符串 容易造成屬性名的 衝突 。
var obj = { info:'Hello' };
obj.info = 'World';
console.log(obj.info); # World
console.log(obj['info']); # World
可見info屬性被重寫。
凡是屬性名屬於 Symbol 類型,就都是獨一無二的,可以保證不會與其他屬性名產生衝突。
Symbol() === Symbol() # false
Symbol('info') === Symbol('info') # false
應用
注意
- Symbol 值不能與其他類型的值進行運算,會報錯。
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
- 作爲屬性名的Symbol
let sym = Symbol('My symbol');
let obj = {};
obj.name = 'Hello';
obj[sym] = 'World';
console.log(obj); # { name: 'Hello', [Symbol(My symbol)]: 'World' }
- Symbol值作爲對象屬性名時,不能用點運算符。
let name = Symbol('My symbol');
let obj = {};
obj.name = 'Hello';
obj[name] = 'World';
console.log(obj); # { name: 'Hello', [Symbol(My symbol)]: 'World' }
console.log(obj.name); # Hello
console.log(obj[name]); # World
console.log(Object.keys(obj)); # [ 'name' ]
console.log(Object.getOwnPropertyNames(obj)); # [ 'name' ]
console.log(Object.getOwnPropertySymbols(obj)); # [ Symbol(My symbol) ]
- 可以看到Object.keys()和Object.getOwnPropertyNames()無法獲取到Symbol屬性
- 可以通過Object.getOwnPropertySymbols()方法獲取Symbol屬性
Reflect.ownKeys
新的 API,Reflect.ownKeys()方法可以返回所有類型的鍵名,包括常規鍵名和 Symbol 鍵名。
for(let key of Reflect.ownKeys(obj)){
console.log(key,obj[key]);
}
# name Hello
# Symbol(My symbol) World
- 通過鍵名我們可以獲取到Symbol爲屬性名對應的屬性值
Symbol.for()
Symbol.for()與Symbol()這兩種寫法,都會生成新的 Symbol。
它們的區別是,前者會被登記在全局環境中供搜索,後者不會。
Symbol.for()不會每次調用就返回一個新的 Symbol 類型的值,而是會先檢查給定的key是否已經存在,如果不存在纔會新建一個值。
比如,如果你調用Symbol.for(“cat”)30 次,每次都會返回同一個 Symbol 值,但是調用Symbol(“cat”)30 次,會返回 30 個不同的 Symbol 值。
Symbol.for("bar") === Symbol.for("bar")
// true
Symbol("bar") === Symbol("bar")
// false
- 由於Symbol()寫法沒有登記機制,所以每次調用都會返回一個不同的值。
- Symbol.for()爲 Symbol 值登記的名字,是全局環境的,不管有沒有在全局環境運行。
function foo() {
return Symbol.for('bar');
}
const x = foo();
const y = Symbol.for('bar');
console.log(x === y); // true
- Symbol.for(‘bar’)是函數內部運行的,但是生成的 Symbol 值是登記在全局環境的。所以,第二次運行Symbol.for(‘bar’)可以取到這個 Symbol 值。
Symbol.keyFor()
Symbol.keyFor()方法返回一個已登記的 Symbol 類型值的key。
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
- 變量s2屬於未登記的 Symbol 值,所以返回undefined。