用于构造代理对象的JavaScript模式,使用经典继承
作者:互联网
虽然还没有最终确定,但我正在尝试使用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.proxy.为了解决这个问题,我必须包装所有导入的方法,以便返回代理.这看起来很痛苦且容易出错.利用代理抽象涉及大量的连接,这对我来说似乎不太合适.
虽然我喜欢代理概念,但我关注它的实用性.也许我错过了一些更好的实践来实现我的目标?
编辑:
这个例子过于简单,因此无法描述我为什么需要它.
最终,我使用代理的目标是允许多重继承.我希望能够将多个行为(模块)混合到给定的代理对象中.我也希望能够随心所欲地取消混合行为.
通过使用代理,我可以让Proxy对象管理对方法的访问,并根据需要将信息传递给mixin.基本上,这允许改进面向方面的编程.有一个方面,我通常会包装和替换一个函数.有时,给定的方法会被几个方面包装和重新包装. AOP的问题是,一旦你以这种方式修改了一个对象,就不容易删除一个方面,因为这个方面可能已被重新封装所掩盖.
代理不会遇到这个问题.你的mixin可以代替数组.代理处理调度到这些mixin中的方法(甚至多个方法,因此多重继承).然后,取消混合行为就像从该阵列中删除mixin一样简单.
代理的问题在于,虽然方法返回对象本身的引用(为了链接目的)是常见的做法,但实际上并不希望任何原始方法返回对该对象的引用(从而绕过代理),你想要返回代理.
解决方法:
你使用代理创建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关键字实际上是代理.因此,如果目标对象返回它,它实际上返回代理.正是你想要的.
如果您想要绝对确定返回代理对象,您可以包装代理方法,如下所示:
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.
标签:javascript,oop,proxy,prototype,ecmascript-harmony 来源: https://codeday.me/bug/20190709/1410522.html