六種基本數據類型
undefined
null
string
boolean
number
symbol(ES6)
一種引用類型
Object
為什么要引入 Symbol?
ES5的對象中的屬性名是字符串,容易造成屬性名的沖突,如果有一種機制,保證每個屬性的名字都是獨一無二的,就可以從根本上防止屬性名的沖突。
Symbol怎么生成?
symbol值通過Symbol函數生成,生成的symbol是一個類似於字符串的原始類型的值
const sym = Symbol(param); // param 可以為字符串或者對象
知識點:
1.使用new命令會報錯,這是因為生成的Symbol是一個原始類型的值,不是對象,不能添加屬性。
2.如果傳入的參數為對象,會調用toString方法,再轉為字符串
3.Symbol的值不能與其他的值進行運算,Symbol可以顯式的轉為字符串、布爾值,但不能轉為數值。
4.Symbol函數的參數只是表示對當前 Symbol 值的描述,因此傳入的參數不同,Symbol
的返回值也是不相等的。
Symbel值作為對象屬性名時,怎樣使用?
let mySymbol = Symbol(); // 第一種寫法 let a = {}; a[mySymbol] = 'Hello!'; // 第二種寫法 let a = { [mySymbol]: 'Hello!' }; // 第三種寫法 let a = {}; Object.defineProperty(a, mySymbol, { value: 'Hello!' }); // 以上寫法都得到同樣結果 a[mySymbol] // "Hello!"
注意:Symbol
每一個值都是不相等的,意味着可以作為標識符,用於對象的屬性名,能保證不會出現同名的屬性,注意作為屬性名時不能使用點運算符。
const mySymbol = Symbol(); const a = {}; a.mySymbol = 'Hello!'; a[mySymbol] // undefined a['mySymbol'] // "Hello!" // a的屬性名實際上是一個字符串而不是Symbol的值。
屬性值的遍歷
JSON.stringify
是在序列化過程中會自動轉換成對應的原始值;Object.getOwnPropertySymbols
方法返回一個數組,成員是當前對象的所有用作屬性名的 Symbol 值;Object.getOwnPropertyNames(obj)
一個對象,其自身的可枚舉和不可枚舉屬性的名稱被返回。keys
方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用[for...in
]循環遍歷該對象時返回的順序一致 。Reflect.ownKeys
方法可以返回所有類型的鍵名,包括常規鍵名和 Symbol 鍵名。
obj // {ccc: "aaa", Symbol(a): "hello", Symbol(b): "world"}; JSON.stringify(obj) // "{"ccc":"aaa"}" Object.getOwnPropertyNames(obj) // ["ccc"] Object.keys(obj) // ["ccc"] Object.getOwnPropertySymbols(obj); // (2) [Symbol(a), Symbol(b)] Reflect.ownKeys(obj) // (3) ["ccc", Symbol(a), Symbol(b)]
如果我希望使用同一個Symbol值?
let s1 = Symbol.for('foo'); let s2 = Symbol.for('foo'); s1 === s2 // true
Symbol.for()
與Symbol()
這兩種寫法,都會生成新的 Symbol
。它們的區別是,前者會被登記在全局環境中供搜索,后者不會。
let s1 = Symbol.for("foo"); Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo"); Symbol.keyFor(s2) // undefined
Symbol.keyFor
方法返回一個已登記的 Symbol 類型值的key。
注意:
- 需要注意的是,Symbol.for為 Symbol 值登記的名字,是全局環境的,可以在不同的 iframe 或 service worker 中取到同一個值。
內置的 Symbol 值?
Symbol.hasInstance
對象的Symbol.hasInstance屬性,指向一個內部方法。當其他對象使用 instanceof
運算符,判斷是否為該對象的實例時,會調用這個方法。比如, foo instanceof Foo
在語言內部,實際調用的是Foo[Symbol.hasInstance](foo)
。
class MyClass { [Symbol.hasInstance](foo) { return foo instanceof Array; } }
Symbol.isConcatSpreadable
對象的Symbol.isConcatSpreadable屬性等於一個布爾值,表示該對象用於Array.prototype.concat()時,是否可以展開。
下面代碼說明,Symbol.isConcatSpreadable默認等於 undefined
,可以展開。Symbol.isConcatSpreadable
= true
|| undefined
=> 展開Symbol.isConcatSpreadable
= false
=> 不展開
let arr1 = ['c', 'd']; ['a', 'b'].concat(arr1, 'e') // ['a', 'b', 'c', 'd', 'e'] arr1[Symbol.isConcatSpreadable] // undefined let arr2 = ['c', 'd']; arr2[Symbol.isConcatSpreadable] = false; ['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']
類似數組的對象正好相反,默認不展開。它的Symbol.isConcatSpreadable屬性設為true,才可以展開。
let obj = {length: 2, 0: 'c', 1: 'd'}; ['a', 'b'].concat(obj, 'e') // ['a', 'b', obj, 'e'] obj[Symbol.isConcatSpreadable] = true; ['a', 'b'].concat(obj, 'e') // ['a', 'b', 'c', 'd', 'e']
Symbol.species
對象的Symbol.species屬性,指向一個構造函數。創建衍生對象時,會使用該屬性。