JavaScript, being a versatile and dynamic language, provides developers with various ways to define functions. Among these, two primary approaches stand out: traditional normal functions and the more concise arrow functions. In this blog post, we'll delve into the distinctions between arrow functions and normal functions, exploring their syntax, behavior, and use cases.
1. Syntax Clarity:
Normal Function Syntax:
function add(a, b) {
return a + b;
}
Arrow Function Syntax:
const add = (a, b) => a + b;
Arrow functions boast a more concise syntax, especially when the function body consists of a single expression. This brevity can enhance code readability, making it a preferred choice for simple operations.
2. Handling 'this' Keyword:
One of the crucial differences between arrow functions and normal functions lies in how they handle the this
keyword, which is fundamental for understanding their behavior.
Normal Function:
function greet() {
console.log("Hello, " + this.name);
}
const person = {
name: "John",
greet: greet
};
person.greet(); // Outputs: Hello, John
Arrow Function:
const greet = () => {
console.log("Hello, " + this.name);
};
const person = {
name: "John",
greet: greet
};
person.greet(); // Outputs: Hello, undefined
Arrow functions lack their own this
context, inheriting it from the surrounding scope. This can lead to unexpected behavior, especially in object methods.
3. The 'arguments' Object:
Normal functions have access to the arguments
object, which holds all the parameters passed to the function. However, arrow functions do not have their own arguments
object.
Normal Function:
function displayArguments() {
console.log(arguments);
}
displayArguments(1, "hello", true); // Outputs: [1, "hello", true]
Arrow Function:
const displayArguments = () => {
console.log(arguments); // ReferenceError: arguments is not defined
}
displayArguments(1, "hello", true);
When dealing with a variable number of parameters, normal functions, with their arguments
object, provide flexibility that arrow functions lack.
4. Usage in Object Methods:
Normal functions are often preferred when defining methods within objects, especially when you need access to the object's properties.
Normal Function:
const car = {
brand: "Toyota",
displayBrand: function() {
console.log("Brand: " + this.brand);
}
};
car.displayBrand(); // Outputs: Brand: Toyota
Arrow Function:
const car = {
brand: "Toyota",
displayBrand: () => {
console.log("Brand: " + this.brand); // Outputs: Brand: undefined
}
};
car.displayBrand();
Normal functions prove more suitable for object methods requiring access to the object's context, as arrow functions lack a distinct this
context.
Conclusion:
In conclusion, the choice between arrow functions and normal functions depends on the specific use case. Arrow functions shine in scenarios that require brevity and don't involve manipulating the this
keyword or utilizing the arguments
object. Meanwhile, normal functions offer more flexibility, making them a better fit for object methods and situations where a distinct this
context is crucial.
Understanding the nuances between these two function types empowers developers to make informed decisions, selecting the most appropriate tool for each coding scenario. Both arrow functions and normal functions play pivotal roles in JavaScript development, and mastering when to use each will undoubtedly elevate your coding proficiency.
If you want to sharpen your brain every week, make sure to subscribe to my weekly newsletter,
https://cypherhritam.substack.com?utm_source=navbar&utm_medium=web&r=39yftb
Top comments (26)
Should point out that one big advantage of arrow functions not having a
this
is that you can use thethis
of the enclosing context, normally a nightmare for sub-functions.Yep ! I always just arrow functions in classes . It avoids having to use « .bind(this) »
Please stop …
There are other disadvantages:
So only use arrow functions in classes when there is a very good reason to (i.e. to avoid having to use bind anyway).
Classes often use arrow functions as reusable event listeners. However EventTarget.addEventListener() can also accept objects as listeners as long as they implement EventListener.handleEvent().
React's synthetic event system doesn't support object event listeners however object event listeners can be used via useEffect().
Technically arrow functions cannot be named.
All that is happening here is that an anonymous function expression is bound to a variable name. To get a named function expression:
What is the difference?
In the following the locally available function name
fibRec
is used:With arrow functions the variable name
fn
from the creating scope has to be used:Contrast this with a function declaration which cannot be unnamed.
The advantage of a function declaration is that it is hoisted to the top of the scope. This works:
This does not work:
This doesn't work either:
While
var calculate
is hoisted, the assignment isn't.Despite of what you may see in framework tutorials in terms of "Vanilla JS" that is considered bad form.
The issue is that in arrow functions
this
refers to the lexical scope that created the function.As a consequence each object instance will create a new, separate function.
For a regular method a single function exists on the prototype object of all the object instances that share it - i.e. one single function is reused across all object instances. For traditional methods (including the short hand syntax)
this
(the function context) refers to the calling context.So when using arrow functions for "regular methods" you are creating more functions than you need to.
Arrow functions in class declarations are justified when that function is intended to be used as a callback (e.g. event listener), i.e. it needs to be bound to (
this
of) that particular object instance.Please have a look at:
Also ES6 is the legacy term for ES2015. There is no ES7. Since ES2015 TC39 has annually published updates to the spec, e.g. ES2016, ES2017, etc.
The additions (finished proposals) for each publication year are identified here.
Some people use "ES.Next" when Babel offers implementations of proposals before they reach stage 4 (finished).
Inside a function they are scoped to the function - i.e. not globally accessible - that is what the "immediately invoked function expressions" IIFE are about. However
var
declarations are effectively hoisted to the top of the function - independent of where they appear inside the function.There is a class declaration and class expression.
The MDN's statement:
is a bit misleading. It's more accurate to say that classes are syntax sugar for constructor functions.
"we use
this
keyword to refer to the current object (an instance of the class)."And as already mentioned
this
has a different meaning in arrow and traditional methods:super is a keyword.
super([arguments])
is only valid in the constructor.super.name
orsuper[name]
can be used to access properties (and functions/methods) on the parent.The spread syntax also works on object literals and can also be used to convert an iterable to arguments for a function call.
JSX supports spread attributes:
Some people think of the rest syntax as "gather" because it collects the remaining arguments.
The
rest
syntax can also be used for Array destructuring and Object destructuring.You can use "rest in object destructuring" to omit object properties.
One issue is that these functions are limited to arrays rather than general iterables. While at times Array.from, Object.entries, Object.keys, and Object.values can be helpful often it's more performant to stick to using for..of.
Ah, I am afraid I won't stop 😅 and here is why :
arrow
functions inside classes because:BLUF is you have to choose your problem and I don't want "this" to be one of them 😉
This raises the question: why use
class
at all?Remember JavaScript is one of the few languages where you are not forced to use classes—you can actually work with objects directly.
James Coplien: The Architectural Voids of Change, The End User and Deep Knowledge - YouTube
Keynote på Software Architecture Open Space 2019, den 07/11-2019.Få invitationer til vores events: http://eepurl.com/gCwRTPKontakt os direkte: https://www.lu...
It seems that for your use cases a factory function creating a closure is much clearer approach than using
class
.Us🤝
True AF man, That's why I always use arrow functions as well
The flexible syntax can be curse or blessing. As mentioned, bracket can be ommitted in some cases. This are different ways to implement the same function:
This can be confusing (but even handy) if you write things like this:
Agree , that’s why the classic function with a clear declaration and return is my favorite.
No room for error , confusion , personal taste.
Also, match a common pattern across most other languages.
I wrote a post on this topic some time ago.
I agree, once you add
typescript
(which everyone should) the arrow syntax becomes much worse.I´m not sure I like typescript. Why use "any"? It should be enough just do omit the type declaration.
Using any is pretty much a last resort .
Typescript , although it’s extremely weak compared to strongly typed compiled languages, is still a significant improvement over plain JavaScript.
It’s a very easy way to significantly reduce bugs.
I worked with Object pascal at fairly large projects, so I know the advantages of strong types. But a compiler does far more than just type checking. It will detect errors even in parts of the code that will never be visited (ok, and will tell you, that it´s unused). A lot of errors in Javascript pop up when the code is executed, and this is far too late.
Usually I add some type checks where necessary and go with the hints, VScode / TSlint will give me while editing. The number of errors that could be prevented using types is relatively low in my daily work. This might be different if you work with more people on the same proect.
Being typeless is not always a disadvantage, but you surely needs a different way of thinking at some points. The only real painpoint for me is refractoring, as it forces you to manually revisit all functions calls. With types, changes can be detected automatically in most cases.
Ideally, Javascript should be extended to optionally allow type definitions for variables, function results and parameter lists. This would be fully sufficient for me.
I mean if u can pick one style and use that, like I use this
Although I agree with you when multiple devs are working on a project it might get a little messy or confusing
Hard disagree on being more concise.
The classic function defenition is much clearer in syntax , arguments /output.
Not to mention that if you want to search your code for a function , with arrow functions it’s much more annoying compared to just searching for function keyword.
I agree with the search part, although for smaller or one line expressions, the arrow function saves both lines of code but it also makes it easier when multiple small functions are declared for me atleast
I don’t see the saving , you replace function keyword with a const binding.
You can also write a classic function in one line.
The examples you used are mostly trivial , see how it looks with typed input / output , destruct of arguments. The syntax becomes much less readable.
Arrow functions are nice for anonymous functions.
To be complete about syntax clarity, you can also declare a function like this:
Yeah right!
Unfortunately, not everything was clear to me, I’m not a technical specialist! but sometimes I read materials on such topics to be comprehensively developed
I am learning a lot from the comments as well.
Us
Refreshing!
usually I will answer this question this way, normal funtion play the role of implementing classes in JavaScript. but arrow function is juat a pure function. no other meanings.