JavaScript 學習-25.Symbol 型別
前言
Symbol 是 ES6 中新新增的特性,生成一個唯一識別符號,可用於屬性名稱、也可用於屬性值。目的是消除屬性名稱衝突。
Symbol 簡介
JavaScript 提供了7種基本資料型別:Number 、 String 、 Boolean 、 Object、 null 和 undefined ,還有 Symbol
Symbol 是原始資料型別,不是物件,所以Symbol 函式棧不能用 new 命令
建立一個Symbol值
let s = Symbol('hello');
Symbol() 函式接受一個可選引數作為描述, 注意僅僅只是描述,方便閱讀,不會影響它的值。
let s1 = Symbol('hello'); let s2 = Symbol('world'); console.log(s1); // Symbol(hello) console.log(s2); // Symbol(world)
當我們使用console.log()去列印symbol的時候會隱式呼叫symbol的toString()方法
Symbol() 函式每次呼叫會建立一個新的獨一無二的值,所以2個Symbol()的值是不相等的
console.log(Symbol() === Symbol()); // false
兩個引數名稱一樣,得到的值也不一樣(引數僅僅只是描述,方便閱讀)
let s1 = Symbol('hello'); let s2 = Symbol('hello'); console.log(s1); // Symbol(hello) console.log(s2); // Symbol(hello) console.log(s1 === s2) // false
Symbol是原始型別,也不能使用new去建立
let s = new Symbol(); // 這是錯誤的寫法
Symbol 作為物件屬性
物件的屬性只能是字串,並且屬性不能重複,可以用symbol作為物件的鍵
const name = Symbol();
const obj = {
[name]: 'hello',
address: '上海市'
};
console.log(obj); // ['address', Symbol()]
Symbol作為物件屬性名時,不能使用點運算子
const obj = {}; const name = Symbol(); obj[name] = 'hello'; obj.address= '上海市'; console.log(obj); // {address: '上海市', Symbol(): 'hello'} console.log(name in obj); // true console.log(obj[name ]); // hello console.log(Object.keys(obj)); // ['address']
Object.keys()無法獲取到 symbol 型別的鍵, 因為Symbol 是ES6 中新新增的型別。
- Symbol作為物件屬性名時,不能使用點運算子,使用點運算子後,這個屬性名就是一個普通字串了,而不是Symbol型別。
- Symbol屬性名具有隱藏性,是不可列舉屬性,所以這個屬性不能使用for...in、for...of、Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()等方法訪問到
另一個新的 Reflect.ownKeys()方法可以返回所有型別的鍵名,包括常規鍵名和 Symbol 鍵名。
const obj = {};
const name = Symbol();
obj[name] = 'hello';
obj.address= '上海市';
console.log(Reflect.ownKeys(obj)); // ['address', Symbol()]
私有屬性
當多個模組修改物件的同一個屬性時,可能會導致屬性被重新賦值,存在一定的風險,由於JavaScript裡面沒有私有屬性。
Symbol 作為屬性具有唯一性,可以當成是私有屬性。
比如當公共模組有一個person物件
// person 公共模組
const person = {
name: 'hello',
address: '上海市'
};
在其它2個模組都給person物件一個id屬性
function lib1(obj) {
obj.id = 123;
}
function lib2(obj) {
obj.id = 456;
}
lib1(person);
lib2(person);
console.log(person.id); //456
那麼id屬性的值會被覆蓋掉。於是可以用Symbol解決這種問題
function lib1(obj) {
obj[Symbol('id1')]= 123;
}
function lib2(obj) {
obj[Symbol('id1')] = 456;
}
lib1(person);
lib2(person);
Symbol.for()
Symbol.for(key) 方法會根據給定的鍵 key,來從執行時的 symbol 登錄檔中找到對應的 symbol,如果找到了,則返回它,否則,新建一個與該鍵關聯的 symbol,並放入全域性 symbol 登錄檔中。
let x = Symbol("hello");
let x1 = Symbol.for("hello");
console.log(x === x1); // false
let x2 = Symbol.for("hello");
console.log(x1 === x2); // true
為了防止衝突,最好給你要放入 symbol 登錄檔中的 symbol 帶上鍵字首。
Symbol.for("mdn.foo");
Symbol.for("mdn.bar");
Symbol.keyFor()
Symbol.keyFor() 返回一個已登記的 Symbol 型別值的 key ,用來檢測該字串引數作為名稱的 Symbol 值是否已被登記。
let x1 = Symbol.for("hello");
console.log(Symbol.keyFor(x1)); // "hello"
Symbol更多的教程學習https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol