4

確定ではありませんが、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' キーワードを介して) プロキシ化されたオブジェクトを構築することです。これは、従来の継承チェーンの製品である可能性があります。

次号。Item プロトタイプを Backbone.Events で拡張するとどうなるか考えてみてください。これらのインポートされたメソッドは、this代わりに返されthis.proxyます。これを回避するにthisは、代わりに を返すために、インポートされたすべてのメソッドをラップして返す必要がありproxyます。これは面倒でエラーが発生しやすいようです。Proxy の抽象化を利用するには多くの配線が必要ですが、これは私には適切ではないように思えます。

Proxy のコンセプトは気に入っていますが、その実用性に関心があります。たぶん、目標を達成するためのより良い練習が欠けているのでしょうか?

編集:

この例は単純化しすぎているため、なぜそれが必要なのかを説明できませんでした。

プロキシを使用する最終的な目標は、多重継承を可能にすることです。特定のプロキシ オブジェクトに複数の動作 (モジュール) をミックスインできるようにしたいと考えています。また、気まぐれに動作を簡単に分解できるようにしたいと考えています。

プロキシを使用することで、Proxy オブジェクトでメソッドへのアクセスを管理し、必要に応じて mixin に情報を渡すことができます。基本的に、これによりアスペクト指向プログラミングが改善されます。アスペクトでは、通常、関数をラップして置き換えます。場合によっては、特定のメソッドがいくつかの側面によってラップおよび再ラップされることがあります。AOP の問題点は、この方法でオブジェクトを変更すると、再ラップによってその側面が埋もれてしまう可能性があるため、その側面を 1 つだけ削除するのは容易ではないことです。

プロキシにはこの問題はありません。代わりに、ミックスインを配列に配置できます。プロキシは、これらの mixin で見つかったメソッドへのディスパッチを処理します (複数のメソッド、したがって複数の継承であっても)。その後、アンミックス動作は、その配列から mixin を削除するのと同じくらい簡単です。

プロキシの問題は、メソッドが (連鎖の目的で) オブジェクト自体への参照を返すことは一般的な方法ですが、元のメソッドのいずれかがそのオブジェクトへの参照を返すことを本当に望んでいないことです (したがって、バイパスプロキシ)、代わりにプロキシを返す必要があります。

4

2 に答える 2

1

プロキシを使用してミックスインを作成するという目標は、悪い考えではありません (このブログ投稿を参照してください)。ただし、私が取り上げている問題はあなたの主な質問ですが、実際にはまったく問題ではありません。たとえば、このコード:

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 をオン/オフするための本当に良いユースケースはあまりありません。

于 2013-05-04T14:17:25.977 に答える
0

しかし、$.proxy のようにプロキシ関数を作成したいだけで、jQuery を使用したくない場合は、次のようにすることができます。

var context = this;
something.addSomeListener( function(){ context.myListener.apply( context, arguments ); } );
于 2014-01-16T10:44:58.403 に答える