underscore
underscore copied to clipboard
_.bind nontrivial constructor fix (?)
A quick summary of what led up to this diff:
- #2197 was a complaint about
_.bind
performing worse than nativeFunction.prototype.bind
, due to it basically beingslice.call(arguments)
+ native bind (at least at the time). - #2199 "fixed" this by completely removing native bind out of the equation (but didn't update the comment, which has continued to claim a fallback to native bind until this very day).
- #2214 reported that this was a breaking change:
_.bind
previously worked with nontrivial constructors such asDate
in environments that supported native bind, but not anymore. This has been the status quo since June 2015. - In the discussion that followed, this was considered the most favorable solution: check for availability of native bind only at the time of definition of
_.bind
. - I took the above solution, updated it to the current situation and added a regression test.
I'm not actually sure this should be merged. Is using a bound function as a constructor important to support? On the other hand, #2199 was probably the wrong solution to the wrong problem in the first place, so maybe this detour should never have been made.
I'm not actually sure this should be merged. Is using a bound function as a constructor important to support?
It is not important to support. Within a constructor function, this
should be the instance you’re constructing.
I feel like we should rely on native bind
here if there are performance improvements it gives us, and not worry about it otherwise.
Here's the thing though. executeBound
already has a fallthrough case for being called as a constructor (i.e. with new
), in which case it doesn't keep the this
binding but does keep the argument bindings:
https://github.com/jashkenas/underscore/blob/4334c126b3e71e4aeb8912d05d72139d24f7d0f1/modules/index.js#L770-L778
And it works for simple constructors, but not for fancy stuff like Date
. Native bind has this sophistication too, but it does work for fancy constructors as well. So where to take this:
- Support some constructors but not others (current situation)?
- Support all constructors (this PR)?
- Support no constructors at all (another breaking change)?
So where to take this:
- Support some constructors but not others (current situation)?
- Support all constructors (this PR)?
- Support no constructors at all (another breaking change)?
I don’t believe that it’s terribly important — these sorts of tickets are originally driven by test-case, nit-picked development, not real-world use cases ... But, if it doesn’t cost us much (in bound function call speed, and in file size) to support all constructors with this PR, I think it’s fine and good to merge it!
Time for another benchmark, then.