2017-07-21 34 views
4

babel-preset-stage-0,我們可以聲明靜態類變量如下:ES6安全使用靜態類變量作爲Map的關鍵?

class Constants { 
    static COUNTRY = Object.freeze({ 
     NAME: 'Germany', 
     DESCRIPTION: 'placeholder', 
    }) 
} 

是可以安全使用Constants.COUNTRY作爲一個ES6 MapSet的關鍵?

例如。

const map = new Map(); 
map.add(Constants.COUNTRY, something); 

能夠保證所有的map.get(Constants.COUNTRY)總是返回something

性能和使用字符串一樣好嗎? NavItem也可以使用Constants.COUNTRY作爲eventKey(引導組件屬性)嗎?

將它聲明爲一個變量而不是一個類也更合適嗎? 即

const Constants = Object.freeze({ 
    COUNTRY: Object.freeze({ 
     NAME: 'Germany', 
     DESCRIPTION: 'placeholder', 
    }) 
}) 
+1

只有當Constants.COUNTRY的值永遠不會改變,並且沒有人從地圖中移除該鍵時,才能保證始終返回您的數據。一個類的靜態只是一個變量,與你的'Constants'變量替代物無異。 – jfriend00

+0

'Object.freeze'可以防止'Constants.COUNTRY'以任何方式被修改,但是可以將它重新分配給靜態類變量......所以我想後面的版本把它聲明爲一個常量Object比聲明更好它作爲一個班級。 – Avery235

+0

'Object.freeze()'防止對象發生變化(這對地圖無關緊要,因爲它仍然是同一個對象)。 'Object.freeze()'不會阻止'Constants.COUNTRY =「hello」'這在訪問'map.get(Constants.COUNTRY)'時很重要。 – jfriend00

回答

2

能夠保證所有的map.get(Constants.COUNTRY)將始終返回的東西嗎?

對於map.get(Constants.COUNTRY)要始終返回您的原始值,幾件事情必須是真實的。

  1. 你必須確保Constants.COUNTRY永遠不能被分配不同的值或者是因爲.COUNTRY財產被再分配或者因爲Constants對象與別的東西,有不同的.COUNTRY屬性值替換。

  2. 您必須確保沒有人能夠從map對象中移除該密鑰。

如果你可以保證這兩件事,那麼yes map.get(Constants.COUNTRY)將始終返回你想要的值。但是,如果其中任何一個不一定是真的,那麼你不能保證總是從地圖上獲得你的價值。

您可以通過凍結Constants對象或將該屬性設置爲可配置爲無法刪除或寫入來確保無法更改Constants.COUNTRY。爲確保Constants對象不能被替換,最好將它作爲const,就像在第二個代碼塊中一樣。

我不知道有一種方法可以確保沒有人可以撥打map.delete(Constants.COUNTRY),但將map對象保持爲私有狀態,以便外部代碼無法訪問它。

如果您有任何理由想要阻止枚舉地圖中的密鑰(使其難以讓某人發現某個密鑰),那麼您可以使用WeakMap而不是Map

性能與使用字符串作爲關鍵一樣好嗎?

你必須測試一個特定的Javascript實現來確保性能。沒有必要的實施原因,其中一個或另一個應該更快 - 它將取決於實施的內部。

我創建了一個jsPerf test case來比較字符串查找與對象查找。歡迎您提供反饋,以改進測試/測量方式,但使用當前的方案,我在地圖中創建10,000個字符串鍵和10,000個對象鍵,然後比較每個鍵的1000個訪問鍵,我發現結果不盡相同。

Chrome is ~20% slower to access the object keys. 
Firefox is ~20% slower to access the string keys. 
Edge is ~27% slower to access the string keys. 

是不是也更適合其聲明爲一個變量,而不是一類?

正如所討論的,您的第二個const窗體的優點是Constants不能被重新分配。

+0

在字符串鍵與對象鍵上添加了性能測量數據。 – jfriend00

+0

剛剛發現一個缺點,把它聲明爲'const'(如果我沒有錯的話就要提起):我無法在引用'Constants.COUNTRY'的'Constants'中添加一個新的變量/函數,所以我必須在'Constants'之前聲明'COUNTRY',然後將它添加到不是DRY的'Constants'。我想上課會更好,那麼任何決定導入課程並重新分配課程的人都不應該編寫代碼。 – Avery235

+0

@ Avery235 - 'const Constants'只意味着'Constants'不能被重新分配。它與爲'Constants'對象分配屬性無關。由於你的'Object.freeze()'你被阻止了。完成構建後,可以凍結對象。 – jfriend00

0

您可以使用WeakMapCOUNTRY爲重點,並作爲something價值。用const聲明的變量不能被刪除。隨着你使用的Object.freeze()wm.get(COUNTRY)應該總是返回something

const wm = new WeakMap; 
 

 
    const COUNTRY = Object.freeze({ 
 
    NAME: 'Germany', 
 
    DESCRIPTION: 'placeholder', 
 
    }); 
 

 
    wm.set(COUNTRY, "something"); 
 

 
    // error when "use strict" 
 
    delete wm; 
 
    delete COUNTRY; 
 

 
    COUNTRY.NAME = 123; 
 

 
    console.log(
 
    wm.get(COUNTRY) 
 
); 
 
    
 
    console.log(
 
    COUNTRY 
 
); 
 
    
 
    console.log(
 
    wm 
 
);


如果要求是不能被刪除或更改,您可以使用const看到Is it possible to delete a variable declared using const?JSON

變量

"use strict"; 
 

 
// `Constants` cannot be changed or deleted 
 
const Constants = `{ 
 
    "NAME": "Germany", 
 
    "DESCRIPTION": "placeholder" 
 
}`; 
 

 
console.log(
 
    JSON.parse(Constants) 
 
); 
 

 
// delete Constants; 
 
/* 
 
Error: { 
 
    "message": "Uncaught SyntaxError: Delete of an unqualified identifier in strict mode." 
 
} 
 
*/

+0

在這種情況下,弱地圖比常規地圖有什麼優勢? – jfriend00

+0

@ jfriend00無法枚舉密鑰,如果這可以被描述爲一個優點;取決於OP最初試圖用第一種模式實現的內容。 OP也可以使用'const'而不是'class',儘管Answer的部分不應該影響'WeakMap'或'Map'的使用。 OP提到了「性能」,垃圾收集。 – guest271314

+0

它是作爲一個需求,甚至希望不能枚舉'map'中的密鑰? – jfriend00