David Herman wrote:
Now the cascade:
array.{
pop()
pop()
};
That looks like `with`, it acts like `with`,
No, it doesn't, and it would be really helpful if you would try to
understand why it doesn't.
So the key here is prototype chain vs. scope chain. 'with' extends the
scope chain:
with (array) {
pop()
pop()
};
so the two chains look like this:
Object.prototype <---------------+
^ \
| \
Array.prototype :
^ :
| |
HEAD -> array -- next-outer-scope --> global
where HEAD is the head of the scope chain. The [[Prototype]]-linked
chain points upward, the scope chain left-to-right. Of course there is
no next-outer-scope intrinsic property of array, that would make a
pigeon-hole problem (with (array) (function () { with (array) {...} }),
e.g.)
Cascades do nothing to the scope chain and desugar
array.{
pop()
pop()
};
to
array.pop();
array.pop();
For the example, with pop the method on Array.prototype, of course there
is no difference. Even if a custom 'pop' property were added to just
array, shadowing Array.prototype.pop, no difference. But the crucial
difference is when array is not even an array, or there's a typo:
array.{
pop()
flop()
};
Unlike the 'with' case, flop() in the cascade is desugared to
array.flop(), so there's a type error trying to invoke the undefined
value, absent any 'flop'-named property with a callable value in array
itself, or on its prototype chain.
In the 'with' case, a global
var flop = function () { return "haha"; }
assigned before the 'with' will make the equivalent 'with'-based code
compile and run -- but probably not as intended.
This may seem not much of a difference, but it's major not only due to
the typo and array-not-an-Array-instance cases. The scope chain
extension is costly and forces deoptimization in common implementations.
And of course 'with' is banned in strict mode.
Dave, any other differences to spell out?
/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss