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

Arrow functions do not .bind() #1043

Closed
TejasQ opened this Issue Dec 7, 2017 · 6 comments

Comments

Projects
None yet
6 participants
@TejasQ

TejasQ commented Dec 7, 2017

Hello,

A coworker of mine unfamiliar with Javascript (he's a Scala dude) pointed out to me that this code right here

const lambda = (() => this.foo).bind({ foo: 1 }) // returns undefined
const properFunction = (function() { return this.foo }).bind({ foo: 1 }) // returns 1

works a little quirky: though we're explicitly binding a context to the lambda, not only does it fail, which is understandable given their lexical this contexts, but it gives no feedback to the developer.

Not sure if this is a browser issue or a language issue, but I thought I'd start a conversation about this. Please let me know if this is better suited to the web platform as opposed to TC39 and I'll gladly close this and open it elsewhere.

Thank you for reading! ❤️

@Donskelle

This comment has been minimized.

Show comment
Hide comment
@Donskelle

Donskelle Dec 7, 2017

Yeah thats a feature of es2015. They don't want us to bind contexts around. Use arguments

Donskelle commented Dec 7, 2017

Yeah thats a feature of es2015. They don't want us to bind contexts around. Use arguments

@ljharb

This comment has been minimized.

Show comment
Hide comment
@ljharb

ljharb Dec 8, 2017

Member

@TejasQ a similar "issue" exists with function foo() { }.bind(this).bind(this) - if it doesn't fail the second time, then (() => {}).bind(this) shouldn't fail.

Similarly, var self = this; function foo() { self.something(); }.bind(this) doesn't have the effect you intend, but that couldn't be made to fail - in other words, using .bind has always required you to have intimate knowledge about the implementation of the function to guarantee an effect, including whether it's already bound, or if it's an arrow function, or it it even references this at all.

Member

ljharb commented Dec 8, 2017

@TejasQ a similar "issue" exists with function foo() { }.bind(this).bind(this) - if it doesn't fail the second time, then (() => {}).bind(this) shouldn't fail.

Similarly, var self = this; function foo() { self.something(); }.bind(this) doesn't have the effect you intend, but that couldn't be made to fail - in other words, using .bind has always required you to have intimate knowledge about the implementation of the function to guarantee an effect, including whether it's already bound, or if it's an arrow function, or it it even references this at all.

@littledan littledan added the question label Dec 8, 2017

@claudepache

This comment has been minimized.

Show comment
Hide comment
@claudepache

claudepache Dec 8, 2017

Contributor

I guess (disclaimer: I don’t know Scala) that the core issue is that it is not possible to bind a new this-value to a function whose this-value is already bound. Instead, Function#bind will just silently ignore the provided value.

In the particular case, the this-value of the arrow function is already bound to the this-value of its enclosing scope.

There is some logic behind that behaviour, but you need good understanding of the JS function model in order to grasp it, and it may be unexpected for people accustomed to other models.

Contributor

claudepache commented Dec 8, 2017

I guess (disclaimer: I don’t know Scala) that the core issue is that it is not possible to bind a new this-value to a function whose this-value is already bound. Instead, Function#bind will just silently ignore the provided value.

In the particular case, the this-value of the arrow function is already bound to the this-value of its enclosing scope.

There is some logic behind that behaviour, but you need good understanding of the JS function model in order to grasp it, and it may be unexpected for people accustomed to other models.

@Kovensky

This comment has been minimized.

Show comment
Hide comment
@Kovensky

Kovensky Dec 21, 2017

Forbidding .bind at all is also a bad idea because you can still use .bind for partial application.

const add3 = (a, b, c) => a + b + c
const add2 = add3.bind(undefined, 0)
const plus5 = add2.bind(undefined, 5)
plus5(3) // 8

Kovensky commented Dec 21, 2017

Forbidding .bind at all is also a bad idea because you can still use .bind for partial application.

const add3 = (a, b, c) => a + b + c
const add2 = add3.bind(undefined, 0)
const plus5 = add2.bind(undefined, 5)
plus5(3) // 8
@ljharb

This comment has been minimized.

Show comment
Hide comment
@ljharb

ljharb Dec 21, 2017

Member

This seems answered; @TejasQ, is it ok to close?

Member

ljharb commented Dec 21, 2017

This seems answered; @TejasQ, is it ok to close?

@TejasQ

This comment has been minimized.

Show comment
Hide comment
@TejasQ

TejasQ Jan 4, 2018

Indeed. Though I'd reiterate as a closing thought that a greater deal of verbosity here could help. Thank you all for your consideration!

TejasQ commented Jan 4, 2018

Indeed. Though I'd reiterate as a closing thought that a greater deal of verbosity here could help. Thank you all for your consideration!

@TejasQ TejasQ closed this Jan 4, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment