2021-03-09【阿里面試】有關symbol的一些知識(2)-實例

相關文章:【阿里面試】有關symbol的一些知識(1)-基礎知識
【阿里面試】有關symbol的一些知識(2)-實例
【阿里面試】有關symbol的一些知識(3)-內置方法

實例:消除魔術字符串

魔術字符串指的是,在代碼之中多次出現、與代碼形成強耦合的某一個具體的字符串或者數值。風格良好的代碼,應該儘量消除魔術字符串,改由含義清晰的變量代替。

function getArea(shape, options) {
  let area = 0;

  switch (shape) {
    // 字符串Triangle就是一個魔術字符串。
    // 它多次出現,與代碼形成“強耦合”,不利於將來的修改和維護。
    case "Triangle":
      area = 0.5 * options.width * options.height;
      break;
    /* ... more code ... */
  }

  return area;
}

getArea("Triangle", { width: 100, height: 100 }); // 魔術字符串

常用的消除魔術字符串的方法,就是把它寫成一個變量。

// 把Triangle寫成shapeType對象的triangle屬性,這樣就消除了強耦合。
const shapeType = {
  triangle: "Triangle",
};

function getArea(shape, options) {
  let area = 0;
  switch (shape) {
    case shapeType.triangle:
      area = 0.5 * options.width * options.height;
      break;
  }
  return area;
}

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

如果仔細分析,可以發現 shapeType.triangle 等於哪個值並不重要,只要確保不會跟其他 shapeType 屬性的值衝突即可。因此,這裏就很適合改用 Symbol 值。

const shapeType = {
  triangle: Symbol(),
};

實例:模塊的 Singleton 模式

Singleton 模式指的是調用一個類,任何時候返回的都是同一個實例。

對於 Node 來說,模塊文件可以看成是一個類。怎麼保證每次執行這個模塊文件,返回的都是同一個實例呢?

很容易想到,可以把實例放到頂層對象 global

// mod.js
function A() {
  this.foo = "hello";
}

if (!global._foo) {
  global._foo = new A();
}

module.exports = global._foo;
// 變量a任何時候加載的都是A的同一個實例。
const a = require("./mod.js");
console.log(a.foo);

但是,這裏有一個問題,全局變量 global._foo 是可寫的,任何文件都可以修改。

// 會使得加載mod.js的腳本都失真
global._foo = { foo: "world" };

const a = require("./mod.js");
console.log(a.foo);

爲了防止這種情況出現,我們就可以使用 Symbol

// mod.js
const FOO_KEY = Symbol.for("foo");

function A() {
  this.foo = "hello";
}

if (!global[FOO_KEY]) {
  global[FOO_KEY] = new A();
}

module.exports = global[FOO_KEY];

上面代碼中,可以保證 global[FOO_KEY] 不會被無意間覆蓋,但還是可以被改寫。

global[Symbol.for("foo")] = { foo: "world" };

const a = require("./mod.js");

如果鍵名使用 Symbol 方法生成,那麼外部將無法引用這個值,當然也就無法改寫。

// mod.js
const FOO_KEY = Symbol("foo");

// 後面代碼相同 ……

上面代碼將導致其他腳本都無法引用 FOO_KEY。但這樣也有一個問題,就是如果多次執行這個腳本,每次得到的 FOO_KEY 都是不一樣的。雖然 Node 會將腳本的執行結果緩存,一般情況下,不會多次執行同一個腳本,但是用戶可以手動清除緩存,所以也不是絕對可靠。

原文:# ECMAScript 6 入門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章