尝试在其上使用错误的api时可以让Set/Map打我吗? [英] can I make Set/Map slap me when I try to use the wrong api on them?

查看:51
本文介绍了尝试在其上使用错误的api时可以让Set/Map打我吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在javascript中使用SetMap对象时,我总是会说错话:

When I use Set and Map objects in javascript, I chronically say the wrong thing:

  • set.length当我的意思是set.size
  • map.length当我的意思是map.size
  • map.someKeyNamemap['someKeyName'],我的意思是map.get('someKeyName')
  • map.someKeyName=someValuemap['someKeyName']=someValue,我的意思是map.set('someKeyName', someValue)
  • set.length when I mean set.size
  • map.length when I mean map.size
  • map.someKeyName or map['someKeyName'] when I mean map.get('someKeyName')
  • map.someKeyName=someValue or map['someKeyName']=someValue when I mean map.set('someKeyName', someValue)

结果是消极的进攻性undefined或无声地没有做我想做的事,这浪费了我的时间.

The result is a passive-aggressive undefined or silently failing to do what I wanted, which wastes my time.

当我尝试做任何不好的事情时,制作某种稍微改变版本的SetMap并抛出Error会多么困难?

How hard would it be to make some kind of slightly-altered version of Set and Map that throw an Error when I try to do any of those bad things?

推荐答案

以下内容似乎完全符合我的要求(已在Chrome 59上进行了测试). 这主要归功于@TJCrowder的回答

Here's something that seems to do exactly what I want (tested on Chrome 59). Most of it is thanks to @T.J.Crowder 's answer here ; I had to add a special case for the size property for some reason.

注意事项: MDN Maplength属性始终为0.或至少在我正在测试的Chrome 59上是错误的,因此当我访问代理对象上的length属性时,它会失败,并显示没有长度!"如预期的.特殊情况下,无论基础Map是否具有length,都可以保证它按预期失败,这样可能会更安全.

Caveat: MDN says Map has a length property that's always 0. I think it's lying; or, at least, it's wrong on Chrome 59 where I'm testing it, so when I access the length property on my proxy object it fails with "No length for you!" as desired. It would be probably be safer to special case it to guarantee that it fails as desired regardless of whether the underlying Map has a 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)

NOTE: Requires a browser supporting ES2015's Proxy.

这篇关于尝试在其上使用错误的api时可以让Set/Map打我吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆