虽然没有最终确定,但我正在试验ES6 Proxies。我的目标是使用构造函数(利用经典继承,如下所示)来创建具有继承链的代理对象。
function inherit(child, parent){ //a classical inheritance pattern
var F = function(){};
F.prototype = parent.prototype;
child.prototype = new F();
child.parent = parent.prototype;
child.prototype.constructor = child;
return child;
}
以下内容是否合理?我创建一个项目并从构造函数返回代理。任何返回对实例的引用的方法(出于链接目的)必须返回对代理的引用,否则我们会在链接时丢失代理。
function Item(attrs){
this.attrs = attrs;
var proto = this.constructor.prototype;
return this.proxy = Proxy.create(new MyHandler(this), proto);
}
Item.prototype.setStatus = function(status){
//do work
return this.proxy; //we do this everywhere instead of a simple 'this'?
}
function DVD(attrs){
attrs.type = 'DVD';
return Item.call(this, attrs);
}
inherit(DVD, Item);
var negotiator = new DVD({title: 'The Negotiator'}); //returns proxy
目标是构建代理对象(通过'new'关键字),这些对象可能是经典继承链的产品。
下一期。考虑如果我使用Backbone.Events扩展我的Item原型会发生什么。导入的方法将返回this
而不是this.proxy
。为了解决这个问题,我必须将所有导入的方法包装回this
,以便返回proxy
。这看起来很痛苦且容易出错。利用代理抽象涉及大量的连接,这对我来说似乎不太合适。
虽然我喜欢代理概念,但我关注它的实用性。也许我错过了一些更好的实践来实现我的目标?
编辑:
此示例过于简单,因此无法描述我需要它的原因。
最终,我使用代理的目标是允许多重继承。我希望能够将多个行为(模块)混合到给定的代理对象中。我也希望能够随心所欲地取消混合行为。
通过使用代理,我可以让Proxy对象管理对方法的访问,并根据需要将信息传递给mixins。基本上,这允许改进面向方面的编程。有一个方面,我通常会包装和替换一个函数。有时,给定的方法会被几个方面包装和重新包装。 AOP的问题是,一旦你以这种方式修改了一个对象,就不容易删除一个方面,因为这个方面可能已被重新封装所掩盖。
代理不会遇到这个问题。你的mixin可以代替数组。代理处理调度到这些mixin中的方法(甚至多个方法,因此多重继承)。然后取消混合行为就像从该阵列中删除mixin一样简单。
代理的问题在于,虽然方法返回对象本身的引用(为了链接目的)是常见的做法,但实际上并不希望任何原始方法返回对该对象的引用(因此绕过代理),您希望代替返回代理。
答案 0 :(得分:1)
使用代理创建mixins的目标并不是一个坏主意(请参阅此blog帖子)。然而,你指出的问题,我所采取的是你的主要问题,实际上根本不是问题。这段代码例如:
var o, p;
function Obj() { }
Obj.prototype.whoAmI = function() {
console.log("I am the "+ (this == o ? "object" : "proxy"));
return this;
};
o = new Obj();
var p = new Proxy(o, {});
o.whoAmI().whoAmI();
p.whoAmI().whoAmI();
将输出:
I am the object
I am the object
I am the proxy
I am the proxy
正如您所看到的,目标对象中使用的this
关键字实际上是代理。因此,如果目标对象返回this
,它实际上返回代理。正是你想要的。
如果您想完全确定返回代理对象,可以将代理方法包装成这样:
var o, p;
function Obj() { }
Obj.prototype.whoAmI = function() {
console.log("I am the "+ (this == o ? "object" : "proxy"));
return o; // bit of a code smell here
};
o = new Obj();
var p = new Proxy(o, {
get: function(target, name) {
return function() {
var rtnVal = target[name].call(this);
return rtnVal == target ? this : rtnVal;
}
}
});
p.whoAmI().whoAmI();
将输出:
I am the proxy
I am the proxy
这可以确保返回的对象永远不是解包的对象。
所有这些当然不利于方法调用的性能。相反,我建议采用更传统的javascript mixins方法。据我所知,在运行中打开和关闭mixin的用例并不是很多。
答案 1 :(得分:0)
但是如果你只想创建像$ .proxy这样的代理函数,但是不想使用jQuery,你可以这样做:
var context = this;
something.addSomeListener( function(){ context.myListener.apply( context, arguments ); } );