Polyfilling bind
is hard, if not even impossible to do correclty. If you take a look at the spec, you notice that bound functions are Function objects
Clearly, that first quality is the most important, so what we do is to return a function that exhibits this behaviour. You already notice that not everything can be done properly, as .length
of functions is non-writable, and prototype
(implicitly created) is non-deleteable.
So how to implement [[Construct]]? We would need to determine whether the function was called with a new
expression. This cannot be done reliably, as a new
call could be faked with the help of .call()
/.apply()
and Object.create()
. So what is usually done is testing Object.getPrototypeOf(this) === constructor.prototype
, or more simple just this instanceof constructor
. If required, we then would fake the [[Construct]] call of the to-be-bound function with the extended arguments.
So how to implement [[HasInstance]]? The only way to manipulate this is the value of the .prototype
, which is used for the prototype chain lookups. To make fBound.[[HasInstance]]
work the same way as fToBind.[[HasInstance]]
, we need to set fBound.prototype = fToBind.prototype
.
However, if we do that, the is[[Construct]]ing check will fail us when the bound function is called on instances of the binded function. Hmm.
So, we will need to balance the trade-offs of the possible solutions. The MDN polyfill could be changed in the way you suggest, could be changed to pass Object.create(fToBind.prototype)
instead of this
, etc.
Property | current MDN | your | … with same
| polyfill | solution | prototypes
------------------------------+-------------------------------------------
fBound(…) uses boundThis | yes yes yes
|
new fBound(…) ignores it | yes yes yes
|
fBound.call(new fToBind) | yes yes no
uses boundThis |
|
new fToBind instanceof fBound | no no yes
|
new fBound instanceof fBound | yes yes yes
|
new fBound instanceof fToBind | yes no yes
|
Object.getPrototypeOf(new | no no yes
fBound)==fToBind.prototype |