2017-06-10 2 views
1

JavaScriptで同じターゲットオブジェクトに対して複数のプロキシラッパーを作成しようとしていますが、ラップされた機能がどのように動作するかに影響するわずかなプロパティがあります。これらのプロパティは、setおよびgetハンドラのreceiverオブジェクトに割り当てられ、アクセスされます。しかし、生成されたプロキシを調べると、それらのプロキシはすべて、の最後にプロキシが割り当てられていると予想されるプロパティセットを持っています。同じターゲットの複数のプロキシオブジェクトによる混乱

const obj = {}; 

const proxies = ['one', 'two'].map(name => { 
    console.log(`proxy ${name}`); 

    const proxy = new Proxy(obj, { 
    get: (target, prop, receiver) => { 
     if (prop === 'name') { return receiver.name; } 

     return target[prop]; 
    }, 
    set: (target, prop, val, receiver) => { 
     if (prop === 'name') { 
     console.log(`setting name ${val} on receiver`); 
     Object.defineProperty(receiver, prop, { 
      value: val, 
      configurable: true, 
      enumerable: true} 
     ); 
     } else { 
     console.log(`setting ${prop} ${val} on target`); 
     target[prop] = val; 
     } 

     return true; 
    } 
    }); 

    proxy.name = name; 

    return proxy; 
}); 

console.log(); 
console.log(proxies); 

私の期待する結果:[{name: 'one'}, {name: 'two'}]

実際の結果:[{name: 'two'}, {name: 'two'}]同じに見えても、ではなく、と厳密に同じです。

私はconst objを省略し、new Proxy({}, ...)と私のオブジェクトを作成する場合は、私が期待した結果を得る - 目標基準は、それらの間で共有されていないと思われることから、プロキシoneおよびプロキシtwoを。だから地球上の何ですか?私の理解から、nameを格納するためにreceiverを使用すると、それがターゲットオブジェクトに伝播するのを防ぐべきですが、とにかくそうしているようです。

+0

正確に値が格納されることを期待していますが、「受信者」とは何を期待していますか?ヒント:プロキシ自体に何も格納することはできません。 – Bergi

答えて

2

あなたのスニペット

Object.defineProperty(receiver, prop, { 
    value: val, 
    configurable: true, 
    enumerable: true} 
); 

は、あなたがそれを行うことを期待するもの(と思う)どうするつもりされていません。 receiverはプロキシオブジェクトであるため、プロパティ定義はtargetにプロキシされます。つまり、if/elseのブランチの区別はほとんどありません。各プロキシオブジェクトに一意の名前を格納する場合は、この場合、最も簡単なことはクロージャのスコープを使用することです。

const proxies = ['one', 'two'].map(name => { 
    console.log(`proxy ${name}`); 

    const proxy = new Proxy(obj, { 
    get: (target, prop, receiver) => { 
     if (prop === 'name') { return name; } 

     return Reflect.get(target, prop, receiver); 
    }, 
    set: (target, prop, val, receiver) => { 
     if (prop === 'name') { 
     name = val; 
     return true; 
     } 

     return Reflect.set(target, prop, val, receiver); 
    }, 
    ownKeys: (target) => { 
     return Reflect.ownKeys(target).concat('name'); 
    }, 
    getOwnPropertyDescriptor: (target, prop) => { 
     if (prop === "name") return { enumerable: true, writable: true, configurable: true, value: name }; 

     return Reflect.getOwnPropertyDescriptor(target, prop); 
    }, 
    }); 

    return proxy; 
}); 
+0

または、変数の代わりに、クロージャスコープをハンドラオブジェクトのプロパティとして使用します。 – Bergi

0

これは、プロキシでプロパティを直接設定するときに発生すると思われます。この動作は、複数のプロキシをインスタンス化することとは無関係です。単一のプロキシを作成し、そのnameを設定するとターゲットも汚染されます。

関連する質問に対するthis answerで説明されているように、そのプロトタイプをプロキシに設定した継承オブジェクトを使用しても、プロキシのターゲットは汚染されません。

関連する問題