当我尝试使用错误的api时,我可以让Set / Map拍我吗?

时间:2017-05-05 09:40:33

标签: javascript javascript-objects

当我在javascript中使用SetMap个对象时,我长期说错了:

  • set.length我的意思是set.size
  • map.length我的意思是map.size
  • 我的意思是{li> map.someKeyNamemap['someKeyName'] map.get('someKeyName') 我的意思是{li> map.someKeyName=someValuemap['someKeyName']=someValue map.set('someKeyName', someValue)

结果是被动攻击性undefined或者默默无法做我想要的事情,这浪费了我的时间。

当我尝试做任何这些不好的事情时,制作SetMap稍微改动的版本会引发Error会有多难?

1 个答案:

答案 0 :(得分:1)

这似乎完全符合我的要求(在Chrome 59上测试过)。 其中大部分归功于@ T​​.J.Crowder的回答here;由于某种原因,我不得不为size属性添加一个特殊情况。

警告:MDNMap的{​​{1}}属性始终为0.我认为它在撒谎;或者,至少,我在测试它的Chrome 59上是错误的,所以当我访问我的代理对象上的length属性时,它失败了,“你没有长度!”如预期的。无论基础length是否具有Map,它都可能更安全地保证它无法按预期失败。

length
// AggressiveMap ctor.
// Like Map but only allows getting properties that exist,
// and doesn't allow setting properties at all.
const AggressiveMap = function(arg) {
  return new Proxy(new Map(arg), {
    // Property getter
    get: function(realThing, name, receiver) {
      if (!(name in realThing)) {
        throw new Error("No "+name+" for you!");
      }
      // No idea why this is necessary, but if I don't special case 'size', I get
      // "Uncaught TypeError: Method Map.prototype.size called on incompatible receiver [object Object]"
      // on Chrome 59.
      if (name === 'size') { return realThing.size; }

      let answer = Reflect.get(realThing, name, receiver);
      if (typeof answer === 'function') {
        // https://stackoverflow.com/questions/43236329/why-is-proxy-to-a-map-object-in-es2015-not-working/43236808#answer-43236808
        answer = answer.bind(realThing);
      }
      return answer;
    },
    // Property setter
    set: function(realThing, name, value, receiver) {
      // Don't allow setting any properties.
      throw new Error("No "+name+" for you!");
      // But here's how to do it if we wanted to allow it.
      return Reflect.set(realThing, name, value, receiver);
    },
  });
};  // AggressiveMap ctor

// Exercise it a bit
const map = AggressiveMap([['a',1],['b',2],['c',3]]);
map.set('d', 4);
map.delete('c');
console.log("map.get('b') = "+JSON.stringify(map.get('b')));
console.log("Iterating:");
for (const [key,value] of map) {
  console.log("  "+JSON.stringify(key)+" -> "+JSON.stringify(value));
}
console.log("map.size = "+JSON.stringify(map.size));
map['moose'] = 'foo';  // No moose for you!
console.log("map['moose'] = "+JSON.stringify(map['moose']));  // No moose for you!  (gets here if you comment out previous line)