JS第七種數據類型Symbol詳解 點擊打開視頻講解更加詳細 一、什麼是Symbol? Symbol是ES6中引入的一種新的基本數據類型,用於表示一個獨一無二的值。它是JavaScript中的第 七種數據類型,與undefined、null、Number(數值)、String(字元串)、Boolea ...
JS第七種數據類型Symbol詳解
一、什麼是Symbol?
Symbol是ES6中引入的一種新的基本數據類型,用於表示一個獨一無二的值。它是JavaScript中的第
七種數據類型,與undefined、null、Number(數值)、String(字元串)、Boolean(布爾值)、
Object(對象)併列。
Symbol特點:
- Symbol的值是唯一的,用來解決命名衝突問題
- Symbol值不能與其他數據進行運算
- Symbol定義的對象屬性不能使用for...in迴圈遍歷,但是可以使用Reflect.ownKeys來獲取對象的所有鍵名
基本用法:
let a = Symbol("末晨曦吖");
console.log(a); // Symbol(末晨曦吖)
console.log(typeof a); //symbol
// 相同參數 Symbol() 返回的值不相等
let b = Symbol("末晨曦吖");
console.log(a === b); //false
為什麼相同參數 Symbol() 返回的值不相等???
因為使用Symbol()創建一個Symbol類型的值並賦值給a變數後,你就得到了一個在記憶體中獨一無二的值。現在除了通過變數a,任何人在任何作用域內都無法重新創建出這個值。所以就算我們通過相同參數創建的b,結果還是不相等的。
儘管a和b都是使用Symbol()創建出來的,但是它們在記憶體中看起來卻是這樣的:
實際上,a變數拿到了記憶體中某塊記憶體的唯一引用(這裡所說的引用,其實就是該記憶體的地址)。如果不藉助a變數,你不可能再得到這個地址。因此:
a !== b; //a和b持有的是兩塊記憶體的引用
const c = a; //手動把a里保存的地址保存在c變數中
a === c; //c和a現在指向同一塊記憶體,因為它們保存了同樣的地址
這種行為看似難以理解,但其實它與對象遵循相同的規則,如:
let a = {};
let b = {};
a !== b; //a和b各自被分配了不同的記憶體,因此它們保存了不同的地址
//藉助變數a,變數c拿到了a指向的那個對象的地址,因此兩者相等
let c = a;
a === c;
但是對於同為基本數據類型的字元串來說,它不遵循類似的規則。比如:
let a = "123";
let b = "123";
a === b; //返回true。兩者在常量區引用同一個字元串
我們首先通過變數a在記憶體中創建了字元串“123”,然後在不藉助變數a的情況下,又通過var b = "123"拿到了對“123”這個字元串的引用,兩者指向記憶體中的同一塊記憶體地址。
因此我們說,a無法確保別的變數無法拿到它保存的地址(前提是不通過a)。但是對於var a = Symbol()這樣的語句,a變數內保存的值是唯一的,因為除了藉助a變數,你永遠無法得到a中保存的值。這也是Symbol的本質。
作為屬性名的Symbol
let mySymbol = Symbol();
// 第一種寫法
let a = {};
a[mySymbol] = 'Hello!';
// 第二種寫法
let a = {
[mySymbol]: 'Hello!'
};
// 第三種寫法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上寫法都得到同樣結果
a[mySymbol] // "Hello!"
註意,Symbol值作為對象屬性名時,不能用點運算符。
let a = {};
let name = Symbol();
a.name = 'lili';
a[name] = 'lucy';
console.log(a.name,a[name]);//lili,lucy
Symbol值作為屬性名時,該屬性還是公開屬性,不是私有屬性。
二、Symbol中的方法
1、Symbol.for()
我們知道Symbo()創建的兩個變數永遠不會是相同的。那麼如果我們需要重新使用同一個Symbol怎麼辦,總不能需要挨個去進行比較吧。還好,es6為我們提供了Symbol.for()方法。
參數是symbol類型的描述信息,不同於Symbol(),這個而參數只能是字元串或者是undefined,若已經創建了則返回這個symbol,否則就進行創建並將這個新的symbol返回,代碼如下
let name = Symbol.for("末晨曦");
let name1 = Symbol.for("末晨曦");
console.log(name === name1); // true
請註意,我們在使用創建描述信息為"末晨曦"的變數的時候,使用的是for,而不是Symbol(),倘若使用Symbol()進行首次創建,for會再次創建一次,二者不會相等,代碼如下:
let name = Symbol("末晨曦");
let name1 = Symbol.for("末晨曦");
console.log(name === name1); // false
原因在於Symbol.for()會有一個登記機制,使用for只會對通過for創建的symbol進行檢查,不會對Symbol()創建的進行檢查。
2、Symbol.keyFor()
這個方法參數是一個通過Symbol.for()創建的symbol類型變數,返回這個symbol變數的描述信息。
let name = Symbol.for("末晨曦");
console.log(Symbol.keyFor(name)); // "末晨曦"
let name1 = Symbol("末晨曦");
console.log(Symbol.keyFor(name1)); // undefined 不能查找Symbol()創建的變數