-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
[Question] Use arrow functions or bind manually in es6 classes? Any performance difference? #9851
Comments
Hi! These two ways of writing it are equivalent. (The second one is compiled to the first one.)
In your example, you still attach the function to the instance:
So they’re essentially the same. At Facebook, we use the second way (“class properties”) but be aware this is still experimental, and not part of ES6. If you only want to stick with stable syntax, then you could bind them manually. I hope this helps! |
As far as runtime behavior goes they are identical, but doing the later (binding a method in the constructor) means you're defining the method on the class prototype and the instance. Doing the former will only define the method as an instance property, avoiding the duplication. But as mentioned, it's experimental so YMMV. Check out this example in the Babel REPL to see the difference. |
Thanks @gaearon this is very helpful! This question was coming from when testing component methods, as I can find the method on class prototype if I use |
@aweary thanks! this helps a lot as we are in the process of converting |
Also check out the automatic class transform:
We used it to convert thousands of components. It's documented here: https://github.com/reactjs/react-codemod#explanation-of-the-new-es2015-class-transform-with-property-initializers |
I've just read an article which seems to disagree with the conclusions on this issue. Do you guys mind to give an opinion on that? Here it goes: |
A best practice, imo, is to never use an arrow function in a class property; it harms testability and limits what the engine can optimize. |
re: @lucasconstantino, would love to hear opinions from FB about that article in addition to how they go about testing those kinds of methods or perhaps deciding not to test them. |
@creativetim Component methods are usually implementation detail, so they shouldn't be tested. props/callbacks is the only interface you should use most of the time. If you use some methods as part of public api, this api should be used only through |
I don’t agree with that; using refs from outside a component to reach into it is a bad practice. |
Do you mean using refs for testing? |
I mean that unless it’s an explicit part of a component’s API, I’d suggest not trying to get access to a component’s internal implementation. I’m not sure why it would be needed for testing; enzyme can be used to get any node you want without refs. |
Yeah, I meant the same. It's about cases when you can't describe events as state. For example react-virtualized |
The performance difference between bind and arrows is not big (50% max) in his jsperf or a remake of it you can also have a variant of But I agree that all methods that can go on prototype (without even |
Another related post: https://flexport.engineering/ending-the-debate-on-inline-functions-in-react-8c03fabd144 (Ending the debate on inline functions in React) |
@lucasconstantino |
@dienluong it doesn't create a copy of the function, it creates a shallow "bind proxy" to the meat of the function, which is shared on the prototype, and thus much more optimizeable. So, in fact, constructor-binding is much better and does NOT crumble in any context in JavaScript, React or otherwise. |
@ljharb However, I did not find any source demonstrating that constructor-binding offer much better performance (compared to class property syntax). In fact, the official React documentation does recommend both constructor-binding and the 'class property' syntax, with the caveat that the latter is still experimental. (Note that my point wasn't that constructor-binding was a bad approach; my point was that the arguments put forth in that Medium article, which by the way disagrees with the accepted conclusion in this thread (i.e. that both methods are essentially the same), might be questionable.) |
Another concern with them is testability - with prototype methods, you can mock them out prior to creating your enzyme wrapper (or any other form of creating elements and testing them) - with arrows in class properties, you have to create the element, then get at the instance, then mock out the own property, and then force a rerender. |
For convenience, I'd like to add that when not being able to access the |
You’re referring, i believe, to babel’s output there, and to the chrome debugger’s inability to properly handle source maps in the repl - which is unrelated to this issue. |
Hi @gaearon ! Our team have an ongoing debate about what should we actually use, either binding methods to the class prototype or using arrow functions. We are having this debate because we have this circumstances:
May I ask what is your opinion about this, since your team actually suggests using Enzyme for testing? How do you guys deal with this kind of tests at Facebook? :) |
ES5:
` ES6:
` *(ES6 + babel): ("initiated as variables-functions" are converted into main props and methods, while "directly named" functions are prototypes)
` `
` |
That’s not ES7; ES7 is ES2016, and class fields are stage 3 (meaning they aren’t even in ES2019, and aren’t certain to be in ES2020 either) |
Sorry, thats babel + es6 - but in plan to be in some "new" es. - Hoppe now I'm right? @ljharb |
@lucasconstantino in the comment section of the article you linked this insight was shared. |
Not quite; manual binding leaves the method on the prototype for sharing and testing, arrows do not. |
Thanks for the correction @ljharb! |
Hello guys, a lot of colleagues asked me to clarify them the difference between classic method and arrow function method in ES6 class and I created a short video where i explain the differences. May be it will be usefull for you too: EN: https://youtu.be/19teBd3lrpk |
In terms of performance, is there any difference between using arrow functions and bind manually when using es6 classes? Using arrow functions the methods are not on the class prototype, it will be on the class instance only. Using bind will attach the methods to class prototype. It sounds like bind manually will have better performance, does that mean we should consider using bind instead of arrow functions for class methods?
Any suggestions or comments are really appreciated!
So in terms of performance, would you recommend using
or
The text was updated successfully, but these errors were encountered: