Why are ES6 class methods not automatically bound to the instance?
Mark S. Miller
erights at google.com
Wed Feb 10 16:24:42 UTC 2016
On Wed, Feb 10, 2016 at 7:11 AM, Sam Gluck <sdgluck at gmail.com> wrote:
> Hi all,
>
> Hope this is the right place for a purely out-of-interest query - if not,
> apologies, please ignore!
>
> Why are methods on an ES6 class not automatically bound to their instance?
> Is there any public documentation/conversation, or reasoning, that can
> explain this decision? (I couldn't find any on esdiscuss.org.)
>
That is an excellent question. Several of the early class proposals did so,
as they were starting with the semantics of es5 objects-as-closures and
classes as compositions-of-instance-traits.
http://wiki.ecmascript.org/doku.php?do=search&id=traits
The idea was that language support would make this semantics efficient,
avoiding the need to eagerly allocate a closure per method per instance.
However, for reasons I understand, these failed to gain traction. Instead,
we moves towards sugar for the dominant es5 pattern of encoding classes
into prototype inheritance. Initially, we tried to have this purely be
sugar, so that people could painlessly refactor code in that dominant
pattern into classes.
As we wrestled with the detailed semantics around super and construction,
es6 classes deviated from being pure sugar. But this deviation only
prevents painless refactoring from es6 classes into the dominant es5
pattern. Practically, it remains painless to refactor from the es5 pattern
into es6 classes.
At <https://github.com/zenparsing/es-function-bind/issues/17> we realized
we could still have had methods bind on extraction -- accounting for the
behavior by decreeing that methods are installed on the prototype as
accessors whose getter binds. However, this realization came too late for
es6. Since it would have made the refactoring into classes more hazardous
-- more of a semantic change -- it is not clear it would have flown even if
we had thought of it in time. Instead, under all variations of the
decorator designs, one can write such a decorator so that decorated methods
are bind-on-extraction, by explicitly creating this accessor property.
However(!), if implemented as a user-land decorator, this has much worse
performance than objects-as-closures!! Objects-as-closures have higher
allocation cost when allocating the object.
http://jsperf.com/creating-stateful-objects
But are quite efficient at using the object once the object is created:
http://jsperf.com/strict-where-state
(Note that jsperf is misidentifying Edge 28.14257.1000.0 as Chrome
46.0.2486. This is worth noting because Edge uses the transposed
representation for WeakMaps, and so WeakMap-based usage of private state
has much less penalty on Edge. Though this is besides the point of this
thread.)
To make a decorator for binding-on-extraction efficient, an implementation
would need some kind of special case somewhere to avoid the allocation when
the method is being immediately invoked, rather than being observably
extracted. The only thing TC39 needs to do to enable this is to standardize
such a decorator so that implementations can provide it as a builtin that
they recognize.
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160210/5c7ca7e7/attachment.html>
More information about the es-discuss
mailing list