-
Notifications
You must be signed in to change notification settings - Fork 2k
Function.length in fat arrow class method #2489
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
Comments
For convenience, here is what the above code compiles to: var Wtf, bar, foo, results, wtf,
_this = this,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
foo = function(a, b, c) {};
bar = function(a, b, c) {};
Wtf = (function() {
function Wtf() {
this.bar = __bind(this.bar, this);
}
Wtf.prototype.foo = function(a, b, c) {};
Wtf.prototype.bar = function(a, b, c) {};
return Wtf;
})();
wtf = new Wtf();
results = [foo.length, bar.length, wtf.foo.length, wtf.bar.length];
console.log(results); |
|
I wish this was simply possible... __bind = function(fn, me){
f = function(){ return fn.apply(me, arguments); };
f.length = fn.length;
return f
}; But alas, it seems not to be. |
Yep, |
Oh i am aware that it is the length of For example, when you use The point of binding a function is to allow that function to be passed anywhere while preserving the context of |
And my point being, is simply.. is this wrong? Should the side affects be addressed? |
Why was this issue closed? My point is that CoffeeScript's implementation is not equal to that of edit: Is there no way to make a custom implementation of |
I'd love to see your suggested compilation. Without abusing eval, there's no way to do what you're asking. |
Unless using @michaelficarra, BTW (and semi-off-topic), are you planing on adding different JS runtime "targets" in the new CS compiler? For example, if someone wanted to target only ECMAScript 5 compliant runtimes, the compiler could rely on things things like |
Are compile options a common thing? Perhaps we could allow for optional targets that would allow CoffeeScript to compile using modernized functions, rather than pigeonholing CoffeeScript into a browser compatibility box? (ie, to actually use |
@epidemian hah, i wrote my post before i saw yours (just couldn't submit it at the time). Same train of thought. |
Since the parameters are known at compile time,
could be:
No need to use |
Give @satyr a medal! Is there anything this feature is lacking? For example, the only thing i know of that
? |
But yeah, @satyr's solution works. |
@epidemian: In a way, yes. The typical usage of the compiler will be simply es6Compiler = new CoffeeScript.Compiler
es6Compiler.addRule CoffeeScript.Nodes.Class, ->
# create native JS "class" node
jsAST = es6Compiler.compile csAST, options If some compilation targets are commonly used, I may pull in sets of predefined rules. |
So the attempted fix earlier was totally a minehole of breakage and disaster. Is there a workable fix, or should we retire this issue? |
I think the conclusion was that there is no "fix", and that compile targets (eg, use edit: What am i thinking, @satyr totally had a solution. My apologies. It's not a true fix, and compile targets will still be better, but at the very least his solution completely resolves the |
While i certainly would prefer the use of Considering that we know how many parameter a bound method expects (otherwise the behaviour on 1.6.0 wouldn't be possible), then:
Could generate a constructor like: function Foo() {
this.method = __bind2(this.method, this);
} Where var __bind2 = function(fn, me){
return function(p1, p2){ return fn.apply(me, arguments); };
}; Quite ugly, i know, as it would require multiple variations of Another possibility is to inline the definition of function Foo() {
var _this = this, _method = this.method;
this.method = function(bar, baz) {
return _method.apply(_this, arguments);
};
} I find this solution to be no more verbose than the one used in 1.6.0, while fixing the Another possibility is doing some |
... we tried it. It breaks a whole slew of other stuff. It's not a viable change.
That's not going to cut it either, I'm afraid.
I have some serious doubts that it will actually preserve the current behavior -- but feel free to give it a shot, and see if the test cases pass. If they do, then we're gold.
Not gonna happen. |
So i guess the only option is eventual compile targets? |
…form, declaring the same parameters in the bound function as in the prototype's one Ugliest code ever 💩
…form, declaring the same parameters in the bound function as in the prototype's one Ugliest code ever 💩
…form, declaring the same parameters in the bound function as in the prototype's one Ugliest code ever 💩
* Add `_bindMethods` to class body and do all method binding there * Add `Code::fakeSignature` flag (Suppresses compilation of parameter defaults and destructuring) * Reuse (cloned) method parameters in wrapper * Remove `__bind` helper
Believe it or not, this is still an issue in CS2. The example above now (2.0.0-beta1) compiles to: var Wtf, bar, foo, results, wtf,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
foo = function(a, b, c) {};
bar = (a, b, c) => {};
Wtf = class Wtf {
constructor() {
this.bar = bind(this.bar, this);
}
foo(a, b, c) {}
bar(a, b, c) {}
};
wtf = new Wtf();
results = [foo.length, bar.length, wtf.foo.length, wtf.bar.length];
console.log(results); And still outputs But if we change the Wtf = class Wtf {
constructor() {
this.bar = (a, b, c) => {}
}
foo(a, b, c) {}
}; It suddenly outputs |
Thanks to #4526, this now compiles to: var Wtf, bar, foo, results, wtf;
foo = function(a, b, c) {};
bar = (a, b, c) => {};
Wtf = class Wtf {
constructor() {
this.bar = this.bar.bind(this);
}
foo(a, b, c) {}
bar(a, b, c) {}
};
wtf = new Wtf();
results = [foo.length, bar.length, wtf.foo.length, wtf.bar.length];
console.log(results); And it outputs I’m not sure it’s worth the effort to compile to the alternative in my last comment, or if that’s even an improvement, but that can be left for another issue or PR. |
I think the current compilation is best - the method still exists on the prototype, but a 'copy' is bound to the instance on construction. It means a bound method is still a method. |
In the following code, how is it possible to get the length of
wtf.bar
?As you can see, the combination of the fat arrow and a class instance causes
wtf.bar.length
to return zero. Is there a workaround for this? Is this "working as intended"? All sorts of various code uses the handyFunction.length
checks, and the inability to trustFunction.length
if the user declared the function as a fat-arrow function could cause problems (and already has for me).. Thoughts?The text was updated successfully, but these errors were encountered: