jashkenas/coffee-script — Issue #1819: replacing bound methods gives wrong results
Author: abelousov
Created: 2011-11-03 16:45:27+00:00
State: open

If you replace class prototype method which is bound with fat arrow, it isn't replaced in any previously created instance.

Jasmine spec:

```
describe 'Coffeescript: class methods binding (fat arrow)', ->
it 'should allow method replacement for both future and existing instances', ->
class Foo
replaced: => false

existing = new Foo
Foo::replaced = -> true
future = new Foo

expect(future.replaced()).toBeTruthy() #OK
expect(existing.replaced()).toBeTruthy() #fail: Expected undefined to be truthy

```

It happens because __bind takes final, computed reference to prototype method, so when prototype method changes, bound method references old prototype method.

The solution is to use specific method to bind prototype methods, giving it not with method itself, but its name:

```
var __bindPrototypeMethods = function(methodName, me){
return function(){ return me.constructor.prototype[methodName].apply(me, arguments); }; };
```

complete javascript for previous code would be:

```
var __bindPrototypeMethods = function(methodName, me){
return function(){ return me.constructor.prototype[methodName].apply(me, arguments); }; };

describe('SingleValueController', function() {
return describe('Coffeescript: class methods binding (fat arrow)', function() {
return it('should allow method replacement for both future and existing instances', function() {
var Foo, existing, future;
Foo = (function() {
function Foo() {
this.replaced = __bindPrototypeMethods('replaced', this);
}
Foo.prototype.replaced = function() {
return false;
};
return Foo;
})();
existing = new Foo;
Foo.prototype.replaced = function() {
return true;
};
future = new Foo;
expect(future.replaced()).toBeTruthy();
return expect(existing.replaced()).toBeTruthy();
});
});
});
```