属性访问器与地图集方法

时间:2019-04-01 16:14:46

标签: javascript

下面的代码是否可以通过

  1. m[k] = v
  2. 上引发错误
  3. 拨打电话m[k] = v自动转换为m.set(k, v)

如果可能的话,我希望使用解决方案1。

// Imagine I write that somewhere
const m = new Map();
m.set("a", "alice");

// And at some point someone else write:
m["b"] = "bob";    // m = Map { 'a' => 'alice', b: 'bob' }
// Expecting "bob" to appear here: 
for (const [k, v] of m){
    console.log(k, v);
}

请注意,当我说其他人时,这个人在不久的将来可能就是我。理想情况下,我希望有一个仅修改实例const m = new Map()的解决方案。例如const m = safe(new Map())之类的。

3 个答案:

答案 0 :(得分:1)

要防止添加属性,可以使用:

 Object.freeze(map);

但是,这不会引发错误。为了能够在属性访问中引发错误,您必须使用Proxy,但是由于它不能直接在Maps上运行(因为它们的内部属性无法通过Proxy反映出来),因此您必须镜像所有方法在一个对象中,并在该对象上使用Proxy:

 function safe(map) {
  return new Proxy({
    get(k) { return map.get(k); },
    set(k, v) { return map.set(k, v); }
    // .... others
 }, {
   set() { throw new Error("property setter on Map"); }
 });
}

您还可以捕获Proxies吸气剂以直接链接到地图(尽管不确定副作用):

function safe(map) {
  return new Proxy({ }, {
   set() { throw new Error("property setter on Map"); },
   get(target, prop, receiver) {
    return typeof map[prop] === "function" ? map[prop].bind(map) : map[prop];
   }
  });
}

答案 1 :(得分:0)

您可以使用proxy

let m = new Map();
m["a"] = "alice";

m = new Proxy(m, {      
  set(target, name, receiver) { throw "Setting values is forbidden!"; }
});

console.log(m["a"]);  // you can read value

m["b"] = "bob";       // setting value will throw exception

答案 2 :(得分:0)

您可以使用Proxy对象。将第一个参数实例化为您想要的任何Map的实例。

const m = new Proxy(new Map(), {
    get(target, name, receiver) {
        return target.get(name);
    },
    set(target, name, receiver) {
        // 1. Comment in to allow error to be thrown.
        // throw new Error(`Cannot set property for ${name}`);

        // 2. Comment in to allow setting via bracket syntax.
        // target.set(name, receiver);
    }
});