2017-10-19 81 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也是此初始定义的一部分。因此,每一个支持地图系统支持第一种方法,而第二和第三只是丑陋的(关于性能等)