2017-10-19 85 views
1

我有一個簡單的例子:一個ES6 Map,我需要添加自定義get()set()它。如何正確擴展ES6映射

Map是一個內置對象,所以我不確定是否會有這樣的警告。我試圖搜索子類Map是否正確,並得到了不一致的結果:目前尚不清楚規範是否允許,瀏覽器/ node.js版本支持它,以及哪些副作用是可能的蓋上測試)。

據我所知,有延長Map功能三種主要的方法:

1)子類它。我已經做了,它似乎喜歡它的作品。

class CustomMap extends Map{ 
    get(key){ 
     super.get(key); 
    } 
    set(key, value){ 
     super.set(key, value); 
    } 
} 

問題在於:互聯網上的很多文章指出,您可能會遇到擴展內置對象的麻煩。大多數是2016年初,現在是2017年後期,在Chrome 61上進行測試。也許現在它是一種安全且支持的方式呢?

2)做一個包裝對象

const Wrapper = function(){ 
    this._map = new Map(); 
    this.get = (key) => {return this._map.get(key);} 
    this.set = (key, value) => {this._map.set(key, value);} 
    ... everything else 
} 

最小優雅的解決方案,因爲我需要實現不只是getset,但所有的地圖功能。另外,Wrapper不是Map的實例。

3)使用ES6代理

const ProxyMap = function(){ 
    return new Proxy(new Map(), { 
     get(target, key){ 
      return target.get(key) 
     } 
     set(target, key, value){ 
      target.set(key, value); 
     } 
    } 
} 

與擴展一個類,這是不妥當的申請Proxy一些內置類型。但是,自從引入Proxy規格以來,又過了很多時間;也許現在Map可以通過代理在現代瀏覽器?

所以,問題是:什麼方式擴展Map是一個在2017年的正確和強大的方式?

+0

*「互聯網上的很多文章指出,您可能會遇到擴展內置對象的麻煩」*您可能指的是在Babel中不支持擴展內置對象,因爲ES5不支持不支持它。 –

+0

*有人在互聯網上*是有幫助*有人告訴我昨天不吃巧克力*,這可能並不意味着巧克力不好吃 –

+0

關於*擴展內置對象*的警告是關於添加東西到'陣列。原型','Object.prototype'等等內置對象。 – pawel

回答

5

目前還不清楚是否它通過規範

這是允許的。自ES6以來,所有內置類型都可以使用class語法進行擴展

目前還不清楚瀏覽器/節點。js版本支持它

他們需要本地支持ES6類和Map。使用轉譯器通常會破壞它。

1)子類。我已經完成了,它看起來像是有效的。

是的,那是正確的做法。

大量互聯網上的文章指出,您可能會遇到擴展內置對象的麻煩。大部分是2016年初,而現在是2017年後期,在Chrome測試61

我不知道,主要的參考http://perfectionkills.com/extending-native-builtins/是從2011年開始與這些文章通過「推內建」意味着不同的事情:修改其原型對象與自定義對象,例如Map.prototype.getWithDefault = function(…) { … };。他們沒有提到class … extends …

做一個包裝對象

這應該是罰款爲好。我不認爲你一定需要你的實例是instanceof Map,如果你確實需要遵循Liskov substitution principle。並非所有鍵值集合的「擴展」都適合這一點。

3)使用ES6代理 - 將Proxy應用於某些內置類型是不可取的。

確實,this doesn't work或至少是累贅的。

+0

_不是所有關鍵值集合的「擴展」都適合這個._你對「擴展」有什麼意思? k/v集合是否意味着字典(例如'Map {Number:Boolean}'類型)? – ftor

+0

@ftor是的,字典/地圖/哈希/ accociative-arrays /無論你想要打電話給他們。我可以想象自定義的實現不遵循LSP。例如。多圖不應該是地圖的子類。 – Bergi

0

重寫方法怎麼樣?

m = new Map() 
m.set('x', 2) 
m.get('x') 
=> 2 
Map.prototype.get = (x) => 'lalala' 
m.get('x') 
=> lalala 
+0

*正確和強大的方式* ...不,這不是一個 –

2

第一個是要走的路。 ES6支持類語法,以及Maps和擴展Maps也是此初始定義的一部分。因此,每一個支持地圖系統支持第一種方法,而第二和第三隻是醜陋的(關於性能等)