ECMAScript Stage-0 Proposal. J. S. Choi, 2021.
- Formal specification
- Babel plugin: Not yet
Function.prototype.bind
is very common in object-oriented JavaScript code.
It is a useful method that allows us to extract object methods
into bound functions that are not dependent on a particular this
value
and which may be used in any object environment.
bind
serves as an important link between
object-oriented and functional APIs in JavaScript.
Why then would an operator that does the same thing? Because there is an important difference.
When we run our code in an untrusted environment, global objects may be modified.
In particular, Function.prototype.call
…
JHD: Want to delete Function.prototype.call and things still work
JHD: Because then I'm not relying on the .call API. It's not super common to be robust against things like this, but that doesnt mean its not a good goal. We need to allow users to harden their code and prevent edge cases like this.
JHD: Defense model here is that you run code in an environment you trust, but after that anything could happen. I use Function.bind.call to protect against this.
???
There is a proposal for an extension-method operator ::
that ostensibly addresses a similar problem.
However, the extension-method proposal does not solve method extraction
and explicitly calls it out as an orthogonal non-goal.
In addition, the extension-method proposal is a successor
to an older proposal for a bind operator ::
.
This older proposal did address method extraction, but it is now inactive.
(A formal specification is available.)
Method extraction &.
is a left-associative infix operator
that binds its right-hand side (a method identifier
or a dynamic method name in [
]
)
to its left-hand side (the method’s original object),
creating a bound function in the same manner
as Function.prototype.bind
.
For example, arr&.slice
would be roughly
equivalent to arr.slice.bind(arr)
,
except that its behavior does not change
if code elsewhere reassigns the global method Function.prototype.bind
.
Likewise, obj&.[Symbol.iterator]
would be roughly
equivalent to obj[Symbol.iterator].bind(obj)
.
Method extraction has equal precedence with
member expressions, call expressions, new
expressions with arguments,
and optional chains.
Left-hand side | Example |
---|---|
Primary expressions | a&.m |
Member expressions | a.b&.m |
Call expressions | a()&.m |
new expressions with arguments |
new F()&.m |
Optional chains | a?.b&.m |
Similarly to the ?.
optional-chaining token,
the &.
token may be padded by whitespace.
For example, a &. m
is equivalent to a&.m
,
and a &. [Symbol.iterator]
is equivalent to a&.[Symbol.iterator]
.
Only minor formatting changes have been made to the status-quo examples.
Status quo | With method extraction |
---|---|
??? From ???. |
??? |