编程语言
首页 > 编程语言> > 用于构造代理对象的JavaScript模式,使用经典继承

用于构造代理对象的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