2017-05-05 42 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.