[每日一題]ES6中為什麼要使用Symbol?

saucxs發表於2020-12-26

關注「鬆寶寫程式碼」,精選好文,每日面試題

加入我們一起學習,day day up

作者:saucxs | songEagle

來源:原創

一、前言

2020.12.23日剛立的flag,每日一題,題目型別不限制。

點選下面圖片,檢視第1道「一道面試題是如何引發深層次的靈魂拷問?」

公眾號「鬆寶寫程式碼」每日一題

或者個人站點連結:

一道面試題是如何引發深層次的靈魂拷問

接下來是第2道:ES6中為什麼要使用Symbol?

二、ES6中為什麼要使用Symbol?

1、簡述ES6中Symbol的概念

ES6中已經有6種資料型別:

  • Undefined
  • Null
  • 布林值
  • 字串
  • 數值
  • 物件

但是在ES6種新加入一種新的資料型別Symbol。

Symbol表示獨一無二的值。

// 沒有引數的情況
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false

// 有引數的情況
var s1 = Symbol('saucxs');
var s2 = Symbol('saucxs');
s1 === s2 // false

需要說明一下:這裡的字元'saucxs'是該Symbol的一個描述,但是並非兩個引數都是'saucxs'。

2、簡述Symbol的特性

  • 特性1:Symbol 值通過 Symbol 函式生成,使用 typeof,結果為 "symbol"
var a = Symbol();
console.log(typeof a); // "symbol"
  • 特性2:Symbol 函式前不能使用 new 命令,否則會報錯。這是因為生成的 Symbol 是一個原始型別的值,不是物件。

  • 特性3:instanceof 的結果為 false

var a = Symbol('foo');
console.log(a instanceof Symbol); // false
  • 特性4:Symbol 函式可以接受一個字串作為引數,表示對 Symbol 例項的描述,主要是為了在控制檯顯示,或者轉為字串時,比較容易區分。
var a = Symbol('saucxs');
console.log(a); // Symbol(saucxs)
  • 特性5:如果 Symbol 的引數是一個物件,就會呼叫該物件的 toString 方法,將其轉為字串,然後才生成一個 Symbol 值。
const obj = {
  toString() {
    return 'abc';
  }
};
const a = Symbol(obj);   // Symbol(abc)
  • 特性6:Symbol 函式的引數只是表示對當前 Symbol 值的描述,相同引數的 Symbol 函式的返回值是不相等的。
// 沒有引數的情況
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false

// 有引數的情況
var s1 = Symbol('saucxs');
var s2 = Symbol('saucxs');
s1 === s2 // false
  • 特性7:Symbol 值不能與其他型別的值進行運算,會報錯。
var a = Symbol('saucxs');

console.log(`I am ${a}`); // TypeError: can't convert symbol to string
  • 特性8:Symbol 值可以顯式轉為字串。
const f = Symbol('saucxs')
f.toString()    // "Symbol(saucxs)"
String(f)       // "Symbol(saucxs)"
  • 特性9:Symbol 值可以作為識別符號,用於物件的屬性名,可以保證不會出現同名的屬性。
var mySymbol = Symbol();

// 第一種寫法
var a = {};
a[mySymbol] = 'Hello!';

// 第二種寫法
var a = {
  [mySymbol]: 'Hello!'
};

// 第三種寫法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上寫法都得到同樣結果
console.log(a[mySymbol]); // "Hello!"
  • 特性10:Symbol 作為屬性名,該屬性不會出現在 for...in、for...of 迴圈中,也不會被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 返回。但是,它也不是私有屬性,有一個 Object.getOwnPropertySymbols 方法,可以獲取指定物件的所有 Symbol 屬性名。
var obj = {};
var a = Symbol('a');
var b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

var objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols);
// [Symbol(a), Symbol(b)]
  • 特性11:使用同一個 Symbol 值,可以使用 Symbol.for。它接受一個字串作為引數,然後搜尋有沒有以該引數作為名稱的 Symbol 值。如果有,就返回這個 Symbol 值,否則就新建並返回一個以該字串為名稱的 Symbol 值。
var s1 = Symbol.for('saucxs');
var s2 = Symbol.for('saucxs');

console.log(s1 === s2); // true
  • 特性12: Symbol.keyFor 方法返回一個已登記的 Symbol 型別值的 key。
var s1 = Symbol.for("saucxs");
console.log(Symbol.keyFor(s1)); // "saucxs"

var s2 = Symbol("saucxs");
console.log(Symbol.keyFor(s2) ); // undefined

3、為什麼要使用Symbol?

比如有這樣一種場景,我們想區分兩個屬性,其實我們並不在意,這兩個屬性值究竟是什麼,我們在意的是,這兩個屬性絕對要區分開來!
例如:

const shapeType = { triangle: 'Triangle'};
function getArea(shape, options) { 
    var area = 0; 
    switch (shape) { 
      case shapeType.triangle:
      area = .5 * options.width * options.height; 
      break; 
    } 
    return area;
}

getArea(shapeType.triangle, { width: 200, height: 200 });

這個時候,我們僅僅是想區分各種形狀,因為不同的形狀用不同的計算面積的公式。
這裡使用的是triangle的名字叫做‘Triangle’,而是事實上我們不想對triangle去特地取個名,我們只想要區分triangle這個形狀不同於任何其他形狀,那麼這個時候Symbol就派上用場啦!

const shapeType = {
   triangle: Symbol()
};

也就是說,我們不用非要去給變數賦一個字串的值,去區分它和別的變數的值不同,因為去給每個變數取個語義化而又不同的值是一件傷腦子的事,當我們只需要知道每個變數的值都是百分百不同的即可,這時候我們就可以用Symbol。

還有可以運用在類的私有變數和私有方法中。

福利

1、內推福利

回覆「校招」獲取內推碼

回覆「社招」獲取內推

回覆「實習生」獲取內推

後續會有更多福利

2、學習資料福利

回覆「演算法」獲取演算法學習資料

3、每日一題

「鬆寶寫程式碼」每日一題

或者個人站點連結:

一道面試題是如何引發深層次的靈魂拷問

The End

songEagle開發知識體系構建,技術分享,專案實戰,實驗室,每日一題,帶你一起學習新技術,總結學習過程,讓你進階到高階資深工程師,學習專案管理,思考職業發展,生活感悟,充實中成長起來。問題或建議,請後臺留言。

相關文章