-
Notifications
You must be signed in to change notification settings - Fork 2k
fixes #1819: bound instance methods should reflect prototype changes #1821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The semantics of this seem incorrect. If you have a bound function in a class definition, and then later replace it with an unbound one ... the function should now be unbound -- not just a new bound version of the new function. Does that make sense? |
Both the current and proposed semantics equally clash with JS's prototypal paradigm. I just think the proposed semantics are more useful. |
Yes -- I'm not saying that the current implementation isn't wrong for this case ... I'm just saying that this fix doesn't seem complete. |
Hmm. I don't think it's possible to achieve the consistent behavior jashkenas is describing without storing additional state. We want the constructor to bind a method only if it's the original, defined with An implementation that would give us the desired consistency would compile
into something like this:
(Edit: Nope, this won't work either; in the example below, I believe this is the test case we want to solve:
|
Ignore previous meandering comment (except the test case, which is legit); here's a bona fide solution: Compile
to
where the
(Edit: Some small errors above corrected. I've run the code and verified that it passes the test from my previous comment.) The two checks—one in the constructor, the other in Does that sound good to you, Michael? |
Yeah, that LGTM. I wish there was a somewhat simpler method, though. |
I wish there were as well, but after tinkering with this for a while, I'm fairly certain that both checks are necessary: You need a test in the function returned from And you need a test in the constructor (on some data structure containing references to the bound functions used in the original class definition), because otherwise, With both checks, |
I've come up with what I believe is a significantly cleaner implementation: var __bindMethods = function(methods, me) {
var proto = me.constructor.prototype;
for(var m in methods)
(function(method, protoMethod) {
if(protoMethod === method)
me[m] = function() {
return protoMethod === method ? method.apply(me, arguments) : protoMethod.apply(this, arguments);
};
}(methods[m], proto[m]));
};
var Foo = (function() {
function Foo() {
__bindMethods(_bound, this);
}
var _bound = {};
Foo.prototype.boundMethod = _bound.boundMethod = function() { return 23 };
Foo.prototype.unboundMethod = function() { return 42 };
return Foo;
})(); I moved almost all of the boilerplate code out of each constructor and into the helper. We don't want to duplicate all that code for each class. I've also eliminated the dependency on all other helper functions. Thoughts? Personally, I'm pretty in favour of this change. |
Ha, I woke up this morning thinking about a similar revision. Definitely an improvement. There's also one small edge case with both implementations, though:
The fix is simply to kill the |
depends on the acceptance of the proposal in #1819