Closed Bug 854938 Opened 12 years ago Closed 12 years ago

Calling .bind() twice on the same function with the same parameters should result in values that are considered equal

Categories

(Core :: JavaScript Engine, defect)

x86_64
Windows 8
defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: Unfocused, Unassigned)

Details

The following isn't obvious, and seems counter to what most people expect: someFunction.bind(param) !== someFunction.bind(param) It's be useful if those two values were considered equal. A common use-case that seems to catch developers out is addEventListener/removeEventListener, where it's expected that the following should work: elem.addEventListener("click", this.someFunction.bind(this)); ... elem.removeEventListener("click", this.someFunction.bind(this)); ie, that the call to removeEventListener would remove the listener added above.
I agree that this is desirable. Unfortunately, I very much doubt we can change the behavior of Function#bind, anymore. See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.3.4.5 for the specification of bind, and http://people.mozilla.org/~jorendorff/es6-draft.html#sec-8.4.1.3 for the underlying abstract operation that creates a new function for each invokation. Since bind is in the wild, supported by multiple browsers, changing its behavior would be backwards-incompatible and almost guaranteed to break some websites. At the very least we'd need to bring this up with TC39, perhaps via a post to es-discuss. Maybe jorendorff has a different perspective on it, but I'm afraid we can't do anything but wontfix this.
Flags: needinfo?(jorendorff)
I'm not so sure memoization is actually a desirable characteristic of Function.prototype.bind. But my view's irrelevant given that ES5 says Function.prototype.bind doesn't memoize. We can't unilaterally add our own memoization scheme, and I think we'd break stuff if we did. WONTFIX unless TC39 decides to break compatibility here. And I'm pretty sure that ain't gonna happen.
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → WONTFIX
Memoization would definitely be contrary to the standard. I think it would be undesirable, too. > elem.addEventListener("click", this.someFunction.bind(this)); > ... > elem.removeEventListener("click", this.someFunction.bind(this)); If we made this work in one case (and believe me it's more work than you'd think!), people would quite naturally start expecting it to work in other cases: elem.addEventListener("click", function (event) { flash(event.target); }); ... elem.removeEventListener("click", function (event) { flash(event.target); }); And then: for (let elem of widgets) elem.addEventListener("click", function () { flash(elem); }); ... for (let elem of widgets) elem.removeEventListener("click", function () { flash(elem); }); It gets harder and harder to tell if the functions are really equivalent. The question generally is not decidable (it is actually non-computable), so if once we raised expectations in this regard, it would be impossible to fulfill them. Anyway, when I call .bind I really expect to get a new Function object. I would be astonished to find that the function returned by bind() already had properties set on it, or had been frozen, and memoization would make that possible.
Flags: needinfo?(jorendorff)
You need to log in before you can comment on or make changes to this bug.