Symbol的基本使用
Symbol的介紹
????????ES6引入了一種新的原始數據類型Symbol,表示獨一無二的值。它是Javascript語言的第七種數據類型。
????????ES5對象屬性名都是字符串,這容易造成屬性名的沖突。為了解決這個問題引入了Symbol類型來解決命名沖突的問題。
????????Symbol值通過Symbol函數生成,也就是說,對象的屬性名現在可以有兩種形類型,一種是原來就有的字符串,另一種就是新增的Symbol類型。
Symbol的特點
認識Symbol
?Symobol函數可以接受一個字符串作為參數,用來區分或者描述Symbol實例。
// 創建Symbol let x = Symbol('abc') let y = Symbol('123') console.log(x, y); // Symbol(abc) Symbol(123)如果Symbol的參數傳遞的是一個對象,那么它內部會調用toString方法將對象轉為字符串,在生成一個Symbol值。
// 參數傳遞對象 let a = Symbol({a: "a"}) console.log(a); // Symbol([object Object])相同參數創建出來的Symbol值是不相等的
// 相同參數不相等 let b = Symbol("1"); let c = Symbol("1"); console.log(b === c) // false let d = Symbol(); let e = Symbol(); console.log(d === e) // falseSymbol的值不能與其他類型的值進行運算,如果進行運算會報錯。
// 不能與其他類型的值進行運算 let n = Symbol("hello") console.log(n + "world"); // Uncaught TypeError: Cannot convert a Symbol value to a stringSymbol可以顯示轉為字符串。
// Symbol顯示轉為字符串 let f = Symbol("hello wrold") console.log(f.toString()); // Symbol(hello wrold) console.log(typeof f.toString()); // stringSymbol也可以轉為Boolean值
// Symbol也可以轉為Boolean值 let g = Symbol("hello wrold") console.log(Boolean(g)); // trueSymbol作為對象的屬性名
????????前面我們說到每一個Symbol的值都是不相等的,所以我們可以將Symbol的值作為對象的屬性名來使用,這樣就能保證不會出現同名屬性,防止屬性被覆蓋或者改寫。
// 將Symbol作為對象的屬性名使用 let sym = Symbol('sym'),sym1 = Symbol('sym1'),sym2 = Symbol('sym2'); const obj = {[sym]: "hello", } obj[sym1] = "world" Object.defineProperty(obj, sym2, {value: "!!!!"}) console.log(obj); // {Symbol(sym): 'hello', Symbol(sym1): 'world', Symbol(sym2): '!!!!'} console.log(obj[sym], obj[sym1] ,obj[sym2]); // hello world !!!! const fun = Symbol('fun'); const obj1 = {[fun] () {console.log('hello world!');} } obj1[fun]() //hello world!Symbol屬性名的遍歷
????????Symbol 作為屬性名,該屬性不會出現在for in、for of循環中,也不會被Object.keys()、Object.getOwnPropertyNames()返回。但是它也不是私有屬性,有一個Object.getOwnPropertySymbols()方法可以獲指定對象的所有Symbol屬性名。
????????Object.getOwnPropertySymbols()方法返回的是一個數組,成員是當前對象所有用作屬性名的Symbol值
????????Reflect.ownKeys()方法返回所有類型的鍵名,包括常規鍵名和Symbol鍵名。
const a = Symbol('a') const b = Symbol('b') const obj = {a: 'a',b: 'b',[a]: 'a',[b]: 'b' } // // 返回當前對象所有用作屬性名的Symbol值 const objSymbols = Object.getOwnPropertySymbols(obj) console.log(objSymbols); // [Symbol(a), Symbol(b)] // 返回對象內所有類型的鍵名 const objSymbols1 = Reflect.ownKeys(obj) console.log(objSymbols1); // ['a', 'b', Symbol(a), Symbol(b)]Symbol.for() 、Symbol.keyFor()
????????有時候我們想要使用同一個Symbol值,Symbol.keyFor()方法可以做到這一點。它接收一個字符串參數,讓后搜索有沒有以該參數作為名稱的Symbol值,如果有,就返回這個Symbol值,否則就新建一個以該字符串命名的Symbol值。
// 同樣參數使用Symbol.for方法生成的值相同 let sym = Symbol.for('a'); let sym1 = Symbol.for('a'); console.log(sym === sym1); // true????????Symbol.for()和Symbol()這兩種寫法都會生成新的Symbol,它們的區別是,前者會被登記在全局環境中供搜索,而后者不會Symbol.for(),不會在每次調用時都返回一個新的Symbol類型的值,而是先檢查給定的key是否已經存在,如果不存在就會返回一個新值。
Symbol.keyFor()方法返回一個已登記的Symbol類型值的key
let sym = Symbol.for('a'); let sym1 = Symbol('a'); console.log(Symbol.keyFor(sym)); // 'a' console.log(Symbol.keyFor(sym1)); // undefinedsym1屬于為登記的Symbol值,所以返回undefined
注意:Symbol.for()方法為Symbol方法登記的名字是全局的。
內置的Symbol
????????除了定義自己使用的 Symbol 值以外,ES6 還提供了 11 個內置的 Symbol 值,指向語言內部使用的方法。
? ? ? ? 以下屬性不一一舉例說明了,如果需要詳細示例請看ECMAScript 6 標準入門https://es6.ruanyifeng.com/#docs/symbol
Symbol.hasInstance
????????對象的Symbol.hasInstance屬性,指向一個內部方法。當其他對象使用instanceof運算符,判斷是否為該對象的實例時,會調用這個方法。比如,foo instanceof Foo在語言內部,實際調用的是Foo[Symbol.hasInstance](foo)。
class MyClass {[Symbol.hasInstance](foo) {return foo instanceof Array;} } [1, 2, 3] instanceof new MyClass() // true????????上面代碼中,MyClass是一個類,new MyClass()會返回一個實例。該實例的Symbol.hasInstance方法,會在進行instanceof運算時自動調用,判斷左側的運算子是否為Array的實例。
Symbol.isConcatSpreadable
????????對象的Symbol.isConcatSpreadable屬性等于一個布爾值,表示該對象用于Array.prototype.concat()時,是否可以展開。
Symbol.species
對象的Symbol.species屬性,指向一個構造函數。創建造衍生對象時,會使用該屬性。
?
Symbol.match
對象的Symbol.match屬性,指向一個函數。當執行str.match(myObject)時,如果該屬性存在,會調用它,返回該方法的返回值。
Symbol.replace
對象的Symbol.replace屬性,指向一個方法,當該對象被String.prototype.replace方法調用時,會返回該方法的返回值。
Symbol.search
對象的Symbol.search屬性,指向一個方法,當該對象被String.prototype.search方法調用時,會返回該方法的返回值。
Symbol.split
對象的Symbol.split屬性,指向一個方法,當該對象被String.prototype.split方法調用時,會返回該方法的返回值。
Symbol.iterator
對象的Symbol.iterator屬性,指向該對象的默認遍歷器方法。
Symbol.toPrimitive
對象的Symbol.toPrimitive屬性,指向一個方法。該對象被轉為原始類型的值時,會調用這個方法,返回該對象對應的原始類型值。
Symbol.toPrimitive被調用時,會接受一個字符串參數,表示當前運算的模式,一共有三種模式。
- Number:該場合需要轉成數值
- String:該場合需要轉成字符串
- Default:該場合可以轉成數值,也可以轉成字符串
Symbol.toStringTag
對象的Symbol.toStringTag屬性,指向一個方法。在該對象上面調用Object.prototype.toString方法時,如果這個屬性存在,它的返回值會出現在toString方法返回的字符串之中,表示對象的類型。也就是說,這個屬性可以用來定制[object Object]或[object Array]中object后面的那個字符串。
Symbol.unscopables
對象的Symbol.unscopables屬性,指向一個對象。該對象指定了使用with關鍵字時,哪些屬性會被with環境排除。
總結
以上是生活随笔為你收集整理的Symbol的基本使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL老黄牛
- 下一篇: ZT华尔街日报:中国楼市泡沫的破灭预言