A more refined solution would involve using a switch statement that checks if an object is undefined, then takes the parent's value:
function switchObjects(obj, parent){
return function(keys, value){
keys = keys.split(".");
var element = obj;
var parentElement;
for(var key of keys){
parentElement = element;
element = element[key];
}
if(element === undefined){
var element = parent;
var parentElement;
for(var key of keys){
parentElement = element;
element = element[key];
}
}
if(value){
parentElement[keys[keys.length]] = value;
}
return element;
};}
Usage example:
parent = [0, 1, 3]; //unchangeable
obj = [, 5, ];
callFunction(switchObjects(obj, parent));
function callFunction(el){
//read
el("0"); //0
el("1"); //5
el("2"); //3
//write
el("0", 12); //do not override parent
//also works with multidimensional objects:
el("0.a");
}
This approach represents an enhanced version of prototypes:
var obj={
0:function(){
alert("original prototype");
},
1:5
}
callFunction(Object.create(obj));//...
callFunction(Object.create(obj));//...
With this method, you can access the properties of prototypes that cannot be easily overridden:
function callFunction(arg){
arg[0](); //works as expected
arg[0] = function(){
alert("hi");
}
arg[0](); //hi
}
This extension does not overwrite the prototype; it extends the argument. To override, you can still do:
arg.prototype[0] = function(){
alert("hi prototype");
};