【问题标题】:How to extend a Map in js?如何在js中扩展地图?
【发布时间】:2018-08-25 08:14:25
【问题描述】:

我正在尝试学习 js 并尝试扩展 Map。我做到了:

function mapExtend(mapInstance) {
  function MapExtend(){
  }

  MapExtend.prototype = Object.create(Map.prototype);
  MapExtend.prototype.constructor = MapExtend;

  return new MapExtend(mapInstance)
}

我这样做了:

const b = new Map()
mapExtend(b).get(1)

我收到以下错误:

Uncaught TypeError: Method Map.prototype.get called on incompatible receiver #<MapExtend>
    at MapExtend.get (<anonymous>)
    at <anonymous>:1:14

我在这里犯了什么错误?

【问题讨论】:

    标签: javascript dictionary


    【解决方案1】:

    我现在不能给你解释,因为我需要先验证我的假设。

    但是使用 ES6 语法可以进行扩展:

    function mapExtend(mapInstance) {
      class MapExtend extends Map {}
    
      return new MapExtend(mapInstance)
    }
    
    const b = new Map()
    mapExtend(b).get(1)

    【讨论】:

    • 是的,这是可行的 :) 但是想知道为什么不能通过函数实现相同的功能.. :)
    • @batman 我想如果你可以在MapExtend 对象实例的上下文中调用Map 的构造函数(Map.apply(this, arguments)),它会起作用。我猜它做了一些必要的初始化,但我现在无法确认这个假设。但是调用构造函数不起作用,因为这样引擎会抱怨只能使用new调用构造函数。
    【解决方案2】:

    您可以直接扩展原生对象的原型。不是每个人都认为good practice

    Map.prototype.reportSize = function () {
        return `This map contains ${this.size} ${this.size === 1 ? "entry" : "entries"}`;
    };
    
    var x = new Map();
    console.log(x.reportSize());
    x.set(3, "three");
    console.log(x.reportSize());

    或者,您可以创建自定义函数,在其中使用扩展。这样你就不必扩展Mapprototype

    const MapWithExtensions = map => {
      return {
        map: map,
        reportSize: function () {
         return `This map contains ${this.map.size} ${
          this.map.size === 1 ? "entry" : "entries"}`; 
        }
      };
    };
    const myMap = MapWithExtensions(new Map);
    console.log(myMap.reportSize());
    myMap.map.set(9, "nine");
    console.log(myMap.reportSize());
    console.log(myMap.map.get(9));

    最后,这可能是一种无需扩展 Map 原型即可创建扩展 Map 的方法(实际上,它将 Map.prototype 键映射到扩展 Map 中的方法)。

    const xMap = MapFactory({
      mySize: function() {return `Hi. My size is currently ${this.size}`}
    });
    const myMap = xMap.Create();
    console.log(myMap.mySize());
    console.log("setting [5, \"five\"]")
    myMap.set(5, "five");
    console.log(myMap.mySize());
    console.log(myMap.entries().next().value);
    
    function MapFactory(extensions = {}) {
      const proto = new Map;
      const mappings = Object.getOwnPropertyNames(Map.prototype)
        .reduce( (reduced, key) => { 
          if (proto[key].constructor !== Function) {
            reduced.localProps.push(key);
          } else {
            reduced.proto[key] = function (...args) { return this.map[key](...args); };
          }
          return reduced;
        },
        { localProps: [], proto: {} }
      );
      const XMap = function (map) {
          this.map = map;
          mappings.localProps.forEach( prop =>
            Object.defineProperty(this, prop, { get() {return this.map[prop]; }}) 
          );
      };
      XMap.prototype = {...mappings.proto, ...extensions};
      return { Create: (map = new Map) => new XMap(map) };
    }

    【讨论】:

    • 扩展原生对象的原型从来都不是一个好主意。仅当您想要填充已指定但引擎未实现的功能时,您才应该这样做。
    【解决方案3】:

    你也可以直接操作map的原型,像这样:

    let collection =  new Map ();
    
    Map.prototype.customFunc = () => {console.log('customFunc')}
    
    collection.customFunc();

    【讨论】:

      猜你喜欢
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多