On Nov 16, 2014, at 11:08 PM, Tom Van Cutsem wrote:
> 2014-11-17 3:34 GMT+01:00 Frankie Bagnardi <[email protected]>:
> Consider when Array.isArray would be used. In my experience, checks to see
> if something is an array are used for:
>
> - deciding how to iterate it (for(;;) vs for..in, for example)
>
> This is a good one. Here, again, a typical proxy-for-array would work as
> intended, as the for(;;) loop just queries .length and properties named "0",
> "1", ... via standard [[Get]] access.
>
> Can someone come up with a convincing example where a proxy-for-array would
> *not* work as intended?
> ("convincing" here means it doesn't involve a proxy that blatantly violates
> the Array contract on purpose)
Probably not, because the Array.prototype methods are all carefully coded to
not have any internal slot or this identify dependencies.
But probing through the proxy as has been proposed is a terrible violation of
the MOP API boundary and isn't generalizable to other built-ins that are
dependent upon internal state. While a null handler proxy on a direct instance
of Array would work under that design, a comparable Map.isMap or
Promise.isPromise method would not. Rather than a one-off hack I think we
should use a new pattern that is generalizable:
Here is a proposal:
Array.isArray is redefined equivalently to:
```js
Array.isArray = function (obj) {
let constructor = obj.constructor;
If (typeof constructor != 'function') return false;
return !!constructor[Symbol.isArray];
}
```
and also
```js
Array[Symbol.isArray]] = true; //note, this is a constructor property, not an
Array.prototype property.
```
we also change Array.prototype.concat to do the above Array.isArray test
instead of using @@comcatSpreadable and change JSON.stringify to use this test
where it current checks for an exotic array object.
Then we have the following:
assert(Array.isArray( [ ] )); //just like ES5
assert( ! Array.isArray( Object.create(Array.prototype))); //just like ES5
assert (new class extends Array{}); //ES6 Array subclass instances answer true
unless the subclass over-rides the static @@isArray property
assert(new class extends Array {
constructor() {return {}};
}); // even if the subclass instance isn't an exotic array object (this is an
improvement over the current ES6 spec. which says that
//isArray answers false in this case
assert(new Proxy( [ ], { }); //because it's all done with property access, no
instance inspection required.
assert( ! new Int32Array(10)); //not array-like, just like ES5
However, I think we should experiment with giving %TypedArrau% is true valued
@@isArray property. I'm guessing that this change won't actually break
anything.
the above proposal completely decouples Array.isArray from exotic array object
checking or any other direct instance inspection. Everything works at the
property access level and so is (by default) transparent to proxies and
completely controllable at the ES cod level.
allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss