Overview of the Problem
Let me see if I understand you correctly. It sounds like you want properties accessed "together" to be considered part of a single key for controller.get
. Take the following example:
controller.set('App.Foo.Bar', { Zap: 1 });
controller.set('App.Foo.Bar.Zap', 2);
var App = controller.alias('App');
var Bar = App.Foo.Bar;
var Zap = Bar.Zap;
var Zap2 = App.Foo.Bar.Zap;
console.log(Zap, Zap2);
// should log: 1, 2
If the above behavior is what you want, then it's not possible (with that syntax). JavaScript just doesn't distinguish between App.Foo.Bar.Zap
and var Bar = App.Foo.Bar; Bar.Zap
. There's nothing in the language that would allow you to differentiate between properties that were accessed "together" (var Bar = App.Foo.Bar
) and one that was accessed "separately" (Bar.Zap
).
Proposal
You can, however, get close by modifying your syntax. I thought about a few different possibilities, and here's the best I could come up with:
controller.set('App.Foo.Bar', { Zap: 1 });
controller.set('App.Foo.Bar.Zap', 2);
var App = controller.alias('App');
// Use parens to note that we are ending the key name
// and want it to retrieve a value.
var Bar = App.Foo.Bar();
var Zap = Bar.Zap;
var Zap2 = App.Foo.Bar.Zap();
console.log(Zap, Zap2);
// should log: 1, 2
If you add parentheses after a property retrieval, as above, then you can use this syntax as a distinguishing note to your proxy that that means to retrieve the value from the controller.
Implementation
Here's the code that would make that possible:
var Container = (function() {
return function Container() {
var map = { };
this.get = function get(key) {
return map[key];
};
this.set = function set(key, value) {
map[key] = value;
};
this.alias = function alias(name) {
return createAlias(this, name);
};
};
function createAlias(container, aliasName) {
return new Proxy(
function() {
return container.get(aliasName);
},
{
get: function(target, name) {
return createAlias(container, aliasName + '.' + name);
},
set: function(target, name, value) {
container.set(aliasName + '.' + name, value);
}
}
);
}
})();
You can set with =
and retrieve with ()
:
var container = new Container();
container.set('App.Controller.Home.Method.Index', 5);
var App = container.alias('App');
App.Controller.Home.Method = 7;
console.log(
App.Controller.Home.Method(), // => 7
App.Controller.Home.Method.Index() // => 5
);
Final Note
I'm sure you're aware that Proxies are experimental, but I just want to emphasize that this particular feature of ES6 is still quite in flux. It could be that the current direct proxies proposal ends up being included in the language, but it's also very possible that proxies in ES will change significantly over the next year. (There have been vigorous discussions on the ECMAScript mailing list over the past month regarding the proxies proposal.) At least with Node you can just keep using an old version of Node if proxies change dramatically (while you work on updating an old implementation).
Hope this helps!