5 ms·
What happened to the bind operator (::)? I do miss threading macros from Clojure but I don't see them as solving a real problem in the javascript language. A sh
by maxfurman 8y ago
What happened to the bind operator (::)? I do miss threading macros from Clojure but I don't see them as solving a real problem in the javascript language. A shortcut for binding `this`, on the other hand, would have saved me a lot of time wondering why my React component methods weren't working correctly.
- adregan 8y agoYou can use the fat arrow syntax to implicitly bind a function to this: handleChange = e => this.setState({ value: e.currentTarget.value })
- purplerabbit 8y agoThe moment es6 classes showed up without automatic method binding was the moment I fell out of love with JavaScript. I can't imagine that there would EVER be a good reason not to have a method bound to the class. Now we've all been forced to learn this new property initializer syntax and add yet another babel dependency to facilitate it.
- rpeden 8y agoWouldn't that be problematic if you're binding lots of handlers, though? It seems like the fat arrow syntax here is creating a new anonymous function for every instance of the handler. And if you've got a list of tens or hundreds of items, and you want a click handler for each, you quickly get to the point where all the extra overhead matters. Like, for instance, in a React render function you could have {things.map(thing => { return <Thing onClick={e => this.handleClick(thingId) } /> })} or {things.map(thing => { return <Thing onClick={this.handleClick.bind(this, thingId)} /> })} But option #1 would be a lot less efficient if you've got lots of things, since it's creating a new closure that calls the instance method instead of just pointing at the instance method like snipper #2 does. I still see lots of people recommending #1 for this exact scenario, though. Maybe I'm just wrong, or maybe stuff like this is why I see so many SPAs consuming shocking amounts of memory. I grant that using the fat arrow is probably fine for the scenario you mentioned though, with something like a text field. I don't think I've seen many pages with so many text fields that the extra overhead would even make a difference.
- alxlu 8y agoHaving .bind inside a JSX prop also creates a new anonymous function on each render. To avoid it, you can do (sorry for bad formatting): class Thing extends React.Component { handleClick = (thingId) => { this.setState(/*stuff*/); } render() { return <div>{things.map(thing => <Thing onClick= {this.handleClick} />)}</div> } } You can also bind handleClick inside the constructor without the arrow. constructor(...args) { super(...args); this.handleClick = this._handleClick.bind(this); } _handleClick(thing) { // stuff }
- mercer 8y agoThe latter version seems to be the one I most commonly see, except _handleClick() is just handleClick() repeated. Am I correct in assuming this is considered idiomatic at this point?
- antonkm 8y agoYes, I'd say so.
- mercer 8y agoIs this better somehow? I feel like I should know this, but it's Friday night and I'm tired, but isn't the constructor fired on every instance of the component? And if so, is this a better approach for any particular reason other than clarity?
- aenigmaclamo 8y agoIt is fired on every instance of the component. However, if you create the arrow function in the render function, it'll be created for every render. Since React keeps the component instances around between renders, it can be a lot better.
- mercer 8y ago
- meandmycode 8y agoIt went through a bunch of iterations that simplified it, it used to be the abstract references operator which I believe would have a symbol lookup on the target function that would then allow the function to take over execution, thus allowing you to decide if the function would explicitly take the called upon object as `this` or as the first argument. It gradually got simplified but nobody could agree about the behaviour of if this would _just work_ with existing functions via the `this` or the first argument, I think eventually the proponents if it grew tired of the battle, they couldn't get unified support for one way or the other.. interesting the pipeline operator has basically gone through the exact same issues, but seems to have had much more attention to it. Ultimately I believe the bind operator was just too soon, generally at the time people were still trying to come to terms with what was a lot of new syntax coming to javascript, as well as react and similar things, now I think these chaining operators make a lot more sense to a lot more people.
- nemothekid 8y agoThere was a proposal for decorators that clearly handled this that seems to have been deprecated (it’s not included in Babel anymore). @autobind handleClick: () -> { return this.member } The whole binding in the constructor seems like needless noise to me