Skip to content

Instantly share code, notes, and snippets.

@HerringtonDarkholme
Created April 25, 2014 18:24
Show Gist options
  • Save HerringtonDarkholme/11298712 to your computer and use it in GitHub Desktop.
Save HerringtonDarkholme/11298712 to your computer and use it in GitHub Desktop.
Infinite default dictionary in Javascript ES6
function handlerMaker(obj) {
return {
getOwnPropertyDescriptor: function(name) {
var desc = Object.getOwnPropertyDescriptor(obj, name);
// a trapping proxy's properties must always be configurable
if (desc !== undefined) { desc.configurable = true; }
return desc;
},
getPropertyDescriptor: function(name) {
var desc = Object.getPropertyDescriptor(obj, name); // not in ES5
// a trapping proxy's properties must always be configurable
if (desc !== undefined) { desc.configurable = true; }
return desc;
},
getOwnPropertyNames: function() {
return Object.getOwnPropertyNames(obj);
},
getPropertyNames: function() {
return Object.getPropertyNames(obj); // not in ES5
},
defineProperty: function(name, desc) {
Object.defineProperty(obj, name, desc);
},
delete: function(name) { return delete obj[name]; },
fix: function() {
if (Object.isFrozen(obj)) {
var result = {};
Object.getOwnPropertyNames(obj).forEach(function(name) {
result[name] = Object.getOwnPropertyDescriptor(obj, name);
});
return result;
}
// As long as obj is not frozen, the proxy won't allow itself to be fixed
return undefined; // will cause a TypeError to be thrown
},
has: function(name) { return name in obj; },
hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
get: function(receiver, name) { return obj[name]; },
set: function(receiver, name, val) { obj[name] = val; return true; }, // bad behavior when set fails in non-strict mode
enumerate: function() {
var result = [];
for (var name in obj) { result.push(name); };
return result;
},
keys: function() { return Object.keys(obj); }
};
}
function defaultDict(fn) {
var innerObj = {};
var handler = handlerMaker(innerObj);
handler.get = function(recv, key) {
console.log('get ' + key);
return key in innerObj ? innerObj[key] : (innerObj[key] = fn());
};
handler.set = function(recv, key, value) {
console.log('set ' + key);
innerObj[key] = value;
}
return Proxy.create(handler);
}
function infinite() {
return defaultDict(infinite)
}
var y = infinite()
console.log(y.a.b.c.d = 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment