That is good news then. I think I have the right expectations of proxies now.
Sharing one handler is easy too. All you need to do is map both the `proxy` and its `target` to the same data. `receiver` is actually the proxy but the argument is no longer important here. ```js var priv = new WeakMap(); var handler = { get: (target, property, receiver) => property in priv.get(target) ? priv.get(target)[property] : target[property], set: (target, property, value, receiver) => property in priv.get(target) ? priv.get(target)[property] = value : target[property] = value, has: (target, property) => property in priv.get(target) || property in target }; function A() { let proxy = new Proxy(this, handler); let store = {secret: 4}; priv.set(this, store).set(proxy, store); return proxy; } A.prototype.getSecret = function () { return priv.get(this).secret; }; var a = new A(); a.getSecret(); // 4 a.secret; // 4 a.secret = 5; a.secret; // 5 a.getSecret(); // 5 'secret' in a; // true ``` (sorry for any dupes, new to mailing lists...) On Thu, Mar 17, 2016 at 5:46 AM, Michael Theriot < michael.lee.ther...@gmail.com> wrote: > I feel like it should, or I am misunderstanding something fundamental. I > made a basic scenario to explain: > > ```js > var arrays = new WeakMap(); > > function ArrayView(array) { > arrays.set(this, array); > > return new Proxy(this, { > set: (target, property, value) => (arrays.has(this) && property in > arrays.get(this)) ? arrays.get(this)[property] = value : target[property] > = value, > get: (target, property) => (arrays.has(this) && property in > arrays.get(this)) ? arrays.get(this)[property] : target[property], > has: (target, property) => (arrays.has(this) && property in > arrays.get(this)) || property in target > }); > } > > ArrayView.prototype = Object.create(Array.prototype, { > arrayLength: { > get() { > return arrays.get(this).length; > } > } > }); > ``` > > When `new ArrayView(somearray)` is called the reference to `somearray` is > stored in the `arrays` weak map and a proxy is returned that allows you to > manipulate indices on it, or fallback to the object for other properties. > > This could be simplified by putting the proxy on the prototype chain to > reduce overhead and actually return a genuine `ArrayView` object instead: > > ```js > var arrays = new WeakMap(); > > function ArrayView2(array) { > arrays.set(this, array); > } > > var protoLayer = Object.create(Array.prototype, { > arrayLength: { > get() { > return arrays.get(this).length; > } > } > }); > > ArrayView2.prototype = new Proxy(protoLayer, { > set: (target, property, value, receiver) => (arrays.has(receiver) && > property in arrays.get(receiver)) ? arrays.get(receiver)[property] = value > : Reflect.set(target, property, value, receiver), > get: (target, property, receiver) => (arrays.has(receiver) && > property in arrays.get(receiver)) ? arrays.get(receiver)[property] > : Reflect.get(target, property, receiver), > has: (target, property) => (arrays.has(target) && > property in arrays.get(target)) || Reflect.has(target, property) > }); > ``` > > Under this setup `target` refers to the protoLayer object which is useless > here, but we can use the `receiver` argument in its place to access the > weak map, and replace our set/get operations with Reflect.set/Reflect.get > calls to the target (protoLayer) using a receiver (the instance) to pass > the correct `this` value to the `arrayLength` getter and prevent infinite > recursion. > > One problem - handler.has() lacks a receiver argument. So in this scenario > when using the `in` operator it will always fail on array properties > because we cannot check the weak map by passing in the instance. > > ```js > var arr = [0, 1]; > > var a = new ArrayView(arr); > a.arrayLength; // 2 > 'arrayLength' in a; // true > '0' in a; // true > '1' in a; // true > '2' in a; // false > > var b = new ArrayView2(arr); > b.arrayLength; // 2 > 'arrayLength' in b; // true > '0' in b; // false > '1' in b; // false > '2' in b; // false > ``` > > Without a receiver argument on handler.has(), it is practically useless > for proxies used as a prototype. You can't reference the instance calling > it and your target is simply the parent prototype. > > Is there a reason the handler.has() trap should not obtain the receiver > when used on the prototype chain? I can understand why Reflect.has() > wouldn't have a receiver argument (that wouldn't make sense) but this seems > like a legitimate use for it. Otherwise I don't see a reason to use the > handler.has() trap at all on prototype proxies except for bizarre behaviors > that have nothing to do with the instance. It will always have the same > behavior across all instances since you can't differentiate them. >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss