2017-05-05 57 views
0

当我使用的JavaScript SetMap对象,我长期讲错话:当我尝试使用错误的api时,我可以让Set/Map拍我吗?

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

结果是被动进取undefined或者默默无法做我想做的事,这浪费了我的时间。

做一些SetMap的某种稍微改变的版本,在我尝试做这些坏事时会抛出Error有多难?

+0

我猜你将不得不与额外的属性 – Pete

+0

@Pete扩展对象类型是什么额外的属性?等等,你在想我想让他们理解那些错误的名字吗? Noooooooooo,我希望他们在使用它们的时候抛出一个错误! –

+0

如果你将它们映射为额外的属性,你可以让这些属性在使用时抛出一个异常 - 这是你能够让它们在脸上可以这么说,但不扩展初始对象的唯一方法,你可以不能进入这些propeties,他们将永远不明确 – Pete

回答

1

以下是我想要的东西(在Chrome 59上测试)。 大部分是感谢@ T.J.Crowder的回答here;出于某种原因,我不得不为size属性添加一个特例。

注意:MDNMap有一个length属性总是0.我认为它是撒谎;或者至少在我测试它的Chrome 59上是错误的,所以当我访问我的代理对象上的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)
NOTE: Requires a browser supporting ES2015's Proxy.

相关问题