1. 程式人生 > 其它 >JavaScript 學習-25.Symbol 型別

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