当我在javascript中使用Set
和Map
个对象时,我长期说错了:
set.length
我的意思是set.size
map.length
我的意思是map.size
map.someKeyName
或map['someKeyName']
map.get('someKeyName')
我的意思是{li> map.someKeyName=someValue
或map['someKeyName']=someValue
map.set('someKeyName', someValue)
结果是被动攻击性undefined
或者默默无法做我想要的事情,这浪费了我的时间。
当我尝试做任何这些不好的事情时,制作Set
和Map
稍微改动的版本会引发Error
会有多难?
答案 0 :(得分:1)
这似乎完全符合我的要求(在Chrome 59上测试过)。
其中大部分归功于@ T.J.Crowder的回答here;由于某种原因,我不得不为size
属性添加一个特殊情况。
警告:MDN说Map
的{{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)