如何在js中扩展一个Map?

4

我正在学习JavaScript并尝试扩展一个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

我在这里犯了什么错误?

3个回答

4

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

但是使用ES6语法扩展是可能的:

function mapExtend(mapInstance) {
  class MapExtend extends Map {}

  return new MapExtend(mapInstance)
}

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


是的,这是可行的 :) 但我想知道为什么不能通过函数实现相同的功能.. :) - batman
@batman如果您可以在MapExtend对象的实例上下文中调用Map的构造函数(Map.apply(this, arguments)),我想它会起作用。我猜它会做一些必要的初始化,但现在我无法确认这个假设。但是调用构造函数不起作用,因为引擎会抱怨构造函数只能使用new来调用。 - t.niese
记录一下:https://medium.com/javascript-scene/how-to-fix-the-es6-class-keyword-2d42bb3f4caf - KooiInc

1
你可以直接扩展原生对象的原型。并非每个人都认为这是良好的实践

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) };
}


扩展本地对象的原型从来不是一个好主意。只有在您想要填充引擎尚未实现但已指定的功能时,才应该这样做。 - t.niese

0

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

let collection =  new Map ();

Map.prototype.customFunc = () => {console.log('customFunc')}

collection.customFunc();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接