Dan*_*iel 3 javascript service-locator proxies node.js ecmascript-harmony
我正在尝试使用 Harmony Proxies (Node.js) 获取用 JavaScript 编写的动态服务定位器。基本上你会创建一个新容器:
var container = new Container();
Run Code Online (Sandbox Code Playgroud)
然后,您将能够像传统服务定位器一样设置和获取值:
container.set('FM', {});
container.get('FM');
container.get('FM', function(FM) {
});
Run Code Online (Sandbox Code Playgroud)
您甚至可以拥有充当子对象的名称空间:
container.set('FM.Object', {});
Run Code Online (Sandbox Code Playgroud)
问题出在动态别名上。
var App = container.alias('App');
Run Code Online (Sandbox Code Playgroud)
创建别名时,它会创建一个新的代理对象,您可以在其中像传统对象一样操作它,但它是 和get()方法的别名set()。
代替:
container.get('App.Hello');
Run Code Online (Sandbox Code Playgroud)
使用别名,您可以使用:
App.Hello
Run Code Online (Sandbox Code Playgroud)
问题在于深层命名空间。假设您正在尝试访问App.Hello.World.Controller,因为它一次通过代理一个命名空间,而不是一次全部通过(就像完整的命名空间一样)。我如何知道用户是否正在调用App.Hello以检索服务定位器中存储的值,或者用户是否想要继续访问更深的命名空间?你不能(根据我的尝试)。
还有什么其他方法可以实现这一目标?
App.Hello.World如果要访问更深的命名空间,则具有返回代理或存储在服务定位器中的值的语法。
var App = container.alias('App');
App.Controller.Home.Method.Index
// It would go through:
App -> Proxy
App.Controller -> Proxy or Value?
App.Controller.Home -> Proxy or Value?
App.Controller.Home.Method -> Proxy or Value?
App.Controller.Home.Method.Index -> Proxy or Value?
Run Code Online (Sandbox Code Playgroud)
现在,我已经制定了一个处理这两个选项的约定。您可以使用单数名称来检索值,使用复数名称来返回代理。这只是一个快速的“黑客”,因为它不是很有效。
(如果您需要澄清或更多信息,请告诉我)
让我看看我的理解是否正确。听起来您希望“一起”访问的属性被视为controller.get. 举个例子:
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
Run Code Online (Sandbox Code Playgroud)
如果上述行为是您想要的,那么这是不可能的(使用该语法)。JavaScript 只是不区分App.Foo.Bar.Zap和var Bar = App.Foo.Bar; Bar.Zap。该语言中没有任何内容可以让您区分“一起”访问的属性 ( var Bar = App.Foo.Bar) 和“单独”访问的属性 ( Bar.Zap)。
但是,您可以通过修改语法来接近。我考虑了几种不同的可能性,这是我能想到的最好的:
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
Run Code Online (Sandbox Code Playgroud)
如果您在属性检索后添加括号(如上所述),那么您可以使用此语法作为代理的区别注释,这意味着从控制器检索值。
这是使这成为可能的代码:
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);
}
}
);
}
})();
Run Code Online (Sandbox Code Playgroud)
您可以使用以下命令设置=和检索():
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
);
Run Code Online (Sandbox Code Playgroud)
我相信您知道代理是实验性的,但我只是想强调 ES6 的这一特殊功能仍然在不断变化。目前的直接代理提案可能最终会被包含在该语言中,但 ES 中的代理也很可能在明年发生重大变化。(过去一个月,ECMAScript 邮件列表上就代理提案进行了激烈的讨论。)至少对于 Node,如果代理发生巨大变化(当您致力于更新旧的实现时),您可以继续使用旧版本的 Node。
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
2121 次 |
| 最近记录: |