đŸ•ˇī¸ Crawler Inspector

URL Lookup

Direct Parameter Lookup

Raw Queries and Responses

1. Shard Calculation

Query:
Response:
Calculated Shard: 32 (from laksa139)

2. Crawled Status Check

Query:
Response:

3. Robots.txt Check

Query:
Response:

4. Spam/Ban Check

Query:
Response:

5. Seen Status Check

â„šī¸ Skipped - page is already crawled

📄
INDEXABLE
✅
CRAWLED
6 days ago
🤖
ROBOTS ALLOWED

Page Info Filters

FilterStatusConditionDetails
HTTP statusPASSdownload_http_code = 200HTTP 200
Age cutoffPASSdownload_stamp > now() - 6 MONTH0.2 months ago
History dropPASSisNull(history_drop_reason)No drop reason
Spam/banPASSfh_dont_index != 1 AND ml_spam_score = 0ml_spam_score=0
CanonicalPASSmeta_canonical IS NULL OR = '' OR = src_unparsedNot set

Page Details

PropertyValue
URLhttps://www.freecodecamp.org/news/the-difference-between-arrow-functions-and-normal-functions/
Last Crawled2026-04-04 07:45:26 (6 days ago)
First Indexed2023-04-14 07:03:07 (2 years ago)
HTTP Status Code200
Meta TitleArrow Functions vs Regular Functions in JavaScript – What's the Difference?
Meta DescriptionBy Dillion Megida In JavaScript, there are two types of functions. You have normal functions and arrow functions. Let's explore the difference between them in this article. Arrow functions was introduced in ES6. And it introduced a simple and shorter...
Meta Canonicalnull
Boilerpipe Text
By Dillion Megida In JavaScript, there are two types of functions. You have normal functions and arrow functions. Let's explore the difference between them in this article. Arrow functions was introduced in ES6. And it introduced a simple and shorter way to create functions. Here's how to create a normal function, with arguments, which returns something: function multiply ( num1 , num2 ) { const result = num1 * num2 return result } If you want to transform this into an arrow function, here's what you'll have: const multiply = ( num1 , num2 ) => { const result = num1 * num2 return result } If the return statement is the only statement in the function, you can even have a shorter function expression. For example: const multiply = ( num1 , num2 ) => { return num1 * num2 } This function only contains the return statement. With arrow functions, we can have something shorter like this: const multiply = ( num1 , num2 ) => num1 * num2 We skip the curly braces and the return keyword. Shorter; one-liner. But the syntax of writing both types of functions is not the only difference. There's more, so let's look at them. I have a video version of this topic which you can also check out :) 1. No arguments object in arrow functions A normal function has an arguments object which you can access in the function: function print ( ) { console . log ( arguments ) } The arguments object is a local variable that contains the arguments passed to the function when called. Let's try it out: print ( "hello" , 400 , false ) // { // '0': 'hello', // '1': 400, // '2': false // } As you can see here, the three arguments passed when calling print() are contained in the arguments object which we log to the console. We can access the first argument with arguments[0] , the second with arguments[1] and the third with arguments[2] But this object does not exist in arrow functions. Let's try it out. Say we have print using an arrow function: const print = ( ) => { console . log ( arguments ) } print ( "hello" , 400 , false ) // Uncaught ReferenceError: arguments is not defined Now we have a reference error: arguments is not defined . That's because the arguments variable does not exist in arrow functions. 2. Arrow functions do not create their own this binding In normal functions, a this variable is created which references the objects that call them. For example: const obj = { name : 'deeecode' , age : 200 , print : function ( ) { console . log ( this ) } } obj . print ( ) // { // name: 'deeecode', // age: 200, // print: [Function: print] // } As you can see here, the this in the print method points to obj , which is the object that calls the method. Here's another example: const obj = { name : 'deeecode' , age : 200 , print : function ( ) { function print2 ( ) { console . log ( this ) } print2 ( ) } } obj . print ( ) // Window Here, we have two functions. The first one is print which is a method of the obj object. The second is print2 which is a function declared inside print . print2() is also called directly. In this case, print is called by obj ( obj.print() ) but no object calls print2 ( print2() ). So the this in print2 would reference the window object by default. Now let's see what happens with an arrow function. const obj = { name : 'deeecode' , age : 200 , print : ( ) => { console . log ( this ) } } obj . print ( ) // Window By using an arrow function for print , this function does not automatically create a this variable. As a result, any reference to this would point to what this was before the function was created. As you see in the result, this was pointing to the Window object before print was created. Let's see another example: const obj = { name : 'deeecode' , age : 200 , print : function ( ) { const print2 = ( ) => { console . log ( this ) } print2 ( ) } } obj . print ( ) // { // name: 'deeecode', // age: 200, // print: [Function: print] // } Here, we have print as a normal function which means a this variable is automatically created in it. Then we have print2 which is an arrow function. Because obj is calling print (as in obj.print() ), the this in print would point to obj . Since print2 is an arrow function, it doesn't create its own this variable. Therefore, any reference to this would point to what the value of this was before the function was created. In this case where obj calls print , this was pointing to obj before print2 was created. As you can see in the results, by logging this from print2 , obj is the result. You can learn more about this in my article here 3. Arrow functions cannot be used as constructors With normal functions, you can create constructors which serve as a special function for instantiating an object from a class. Here is an example of an Animal class which we instantiate two objects from: class Animal { constructor ( name , numOfLegs ) { this . name = name this . numOfLegs = numOfLegs } sayName ( ) { console . log ( ` My name is ${ this . name } ` ) } } const Dog = new Animal ( "Bingo" , 4 ) const Bird = new Animal ( "Steer" , 2 ) Dog . sayName ( ) // My name is Bingo Bird . sayName ( ) // My name is Steer Here, we have the Animal constructor which can be instantiated with different parameters. In the constructor, two arguments are required: name and noOfLegs . In the case of Dog , we create a new instance of Animal using "Bingo" as the name and 4 as the noOfLegs . In the case of Bird , we create a new instance of Animal using "Steer" as the name and 2 as the noOfLegs . By calling sayName on Dog and Bird , you can see how the method works currently with each object. The this variable points to the objects and the name field is gotten from each of them. The this variable is very important for classes and constructors. In point 2, we saw that arrow functions cannot create their own this . For this reason, arrow functions also cannot be used as constructors. Let's attempt it and see what happens: class Animal { constructor = ( name , numOfLegs ) => { this . name = name this . numOfLegs = numOfLegs } sayName ( ) { console . log ( ` My name is ${ this . name } ` ) } } // Uncaught SyntaxError: Classes may not have a field named 'constructor' Here, we have an arrow function used for the constructor . But, we get a SyntaxError: Classes may not have a field named 'constructor' . Because arrow functions involve expressions that are assigned variables, JavaScript now sees constructor as a field. And in classes, you cannot have a field named constructor as that is a reserved name. But, we can use arrow functions for the methods in the class without getting errors. For example: class Animal { constructor ( name , numOfLegs ) { this . name = name this . numOfLegs = numOfLegs } sayName = ( ) => { console . log ( ` My name is ${ this . name } ` ) } } const Dog = new Animal ( "Bingo" , 4 ) Dog . sayName ( ) // My name is Bingo Here, we have a normal function for the constructor , and an arrow function for the sayName method. sayName is a field. And we do not get errors. By calling sayName() on Dog , we still get "My name is Bingo". Though sayName as an arrow function does not create its own this , remember that any reference to this would point to the value of it before the arrow function was created. In this case, the value of this pointed to Dog before sayName was created. 4. Arrow functions cannot be declared When it comes to functions, you need to understand function declaration and function expression . Function declarations involve the function keyword and a name for the function. For example: function printHello ( ) { console . log ( "hello" ) } printHello is a declared function . But, check out this example: const printHello = function ( ) { console . log ( "hello" ) } In this case, printHello is not a declared function. We have an anonymous function (not named) on the right side of the assignment operator. This function is a function expression , which is assigned to the printHello variable. Though the function keyword is used, there is no name assigned, which makes it an expression and not a declaration. To prove that it is not a declaration, try the following: function ( ) { console . log ( "hello" ) } Because this expression is not assigned to a variable, you get an error: SyntaxError: Function statements require a function name Back to arrow functions. Normal functions can be declared when you use the function keyword and a name, but arrow functions cannot be declared. They can only be expressed because they are anonymous: const printHello = ( ) => { console . log ( "hello" ) } As you see here, we have an anonymous function (starting from () => ... ) which is assigned to the printHello variable. printHello is not a declared function here. It is a variable that holds the evaluated value from the function expression. 5 Arrow functions cannot be accessed before initialization Hoisting is a concept where a variable or function is lifted to the top of its global or local scope before the whole code is executed. This makes it possible for such a variable/function to be accessed before initialization. Here's a function example: printName ( ) console . log ( "hello" ) function printName ( ) { console . log ( "i am dillion" ) } // i am dillion // hello As you can see here, we called printName before it was actually declared in the code. But we don't get any errors. printName() is executed (logging "i am dillion" to the console) before console.log("hello") . What happens here is hoisting. The printName function is raised to the top of the global scope (the scope it is declared in) before the whole code is executed, thereby making it possible to execute the function earlier. But not all kinds of functions can be accessed before initialization. All functions and variables in JavaScript are hoisted, but only declared functions can be accessed before initialization . Here's an example with an arrow function: printName ( ) console . log ( "hello" ) const printName = ( ) => { console . log ( "i am dillion" ) } // ReferenceError: Cannot access 'printName' before initialization Running this code, you get an error: ReferenceError: Cannot access 'printName' before initialization . As we saw in point 4, printName is not a declared function. It is a variable, declared with const which is assigned a function expression. Variables declared with let and const are hoisted, but they cannot be accessed before the line they are initialized. Let's say we use var for our arrow function: printName ( ) console . log ( "hello" ) var printName = ( ) => { console . log ( "i am dillion" ) } // TypeError: printName is not a function Here, we have declared the printName variable with var . The error we get now is TypeError: printName is not a function . The reason for this is that variables declared with var are hoisted and accessible, but they have a default value of undefined . So attempting to access printName before the line it was initialized with the function expression is interpreted as undefined() , and as you know, "undefined is not a function". You can learn more about the hoisting differences between var, let, and const here Wrap up Although arrow functions allow you to write functions more concisely, they also have limitations. As we have seen in this article, some of the behaviors that occur in normal functions do not happen in arrow functions. If you want to create constructors, retain the normal behavior of this or have your functions hoisted, then arrow functions are not the right approach. If you enjoyed this article, please share it with others :) Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started
Markdown
[![freeCodeCamp.org](https://cdn.freecodecamp.org/platform/universal/fcc_primary.svg)](https://www.freecodecamp.org/news/) Menu Menu - [Forum](https://forum.freecodecamp.org/) - [Curriculum](https://www.freecodecamp.org/learn) [Donate](https://www.freecodecamp.org/donate/) [Learn to code — free 3,000-hour curriculum](https://www.freecodecamp.org/) April 13, 2023 / [\#100DaysOfCode](https://www.freecodecamp.org/news/tag/100daysofcode/) # Arrow Functions vs Regular Functions in JavaScript – What's the Difference? ![Arrow Functions vs Regular Functions in JavaScript – What's the Difference?](https://www.freecodecamp.org/news/content/images/size/w2000/2023/04/25-arrow-normal-functions.png) By Dillion Megida In JavaScript, there are two types of functions. You have normal functions and arrow functions. Let's explore the difference between them in this article. Arrow functions was introduced in ES6. And it introduced a simple and shorter way to create functions. Here's how to create a normal function, with arguments, which returns something: ``` function multiply(num1, num2) { const result = num1 * num2 return result } ``` If you want to transform this into an arrow function, here's what you'll have: ``` const multiply = (num1, num2) => { const result = num1 * num2 return result } ``` If the `return` statement is the only statement in the function, you can even have a shorter function expression. For example: ``` const multiply = (num1, num2) => { return num1 * num2 } ``` This function only contains the `return` statement. With arrow functions, we can have something shorter like this: ``` const multiply = (num1, num2) => num1 * num2 ``` We skip the curly braces and the `return` keyword. Shorter; one-liner. But the syntax of writing both types of functions is not the only difference. There's more, so let's look at them. I have a [video version of this topic](https://youtu.be/M10gzHpIUDw) which you can also check out :) ## 1\. No `arguments` object in arrow functions A normal function has an `arguments` object which you can access in the function: ``` function print() { console.log(arguments) } ``` The `arguments` object is a local variable that contains the arguments passed to the function when called. Let's try it out: ``` print("hello", 400, false) // { // '0': 'hello', // '1': 400, // '2': false // } ``` As you can see here, the three arguments passed when calling `print()` are contained in the `arguments` object which we log to the console. We can access the first argument with `arguments[0]`, the second with `arguments[1]` and the third with `arguments[2]` But this object does not exist in arrow functions. Let's try it out. Say we have `print` using an arrow function: ``` const print = () => { console.log(arguments) } print("hello", 400, false) // Uncaught ReferenceError: arguments is not defined ``` Now we have a reference error: **arguments is not defined**. That's because the `arguments` variable does not exist in arrow functions. ## 2\. Arrow functions do not create their own `this` binding In normal functions, a `this` variable is created which references the objects that call them. For example: ``` const obj = { name: 'deeecode', age: 200, print: function() { console.log(this) } } obj.print() // { // name: 'deeecode', // age: 200, // print: [Function: print] // } ``` As you can see here, the `this` in the `print` method points to `obj`, which is the object that calls the method. Here's another example: ``` const obj = { name: 'deeecode', age: 200, print: function() { function print2() { console.log(this) } print2() } } obj.print() // Window ``` Here, we have two functions. The first one is `print` which is a method of the `obj` object. The second is `print2` which is a function declared inside `print`. `print2()` is also called directly. In this case, `print` is called by `obj` (`obj.print()`) but no object calls `print2` (`print2()`). So the `this` in `print2` would reference the window object by default. Now let's see what happens with an arrow function. ``` const obj = { name: 'deeecode', age: 200, print: () => { console.log(this) } } obj.print() // Window ``` By using an arrow function for `print`, this function does not automatically create a `this` variable. As a result, any reference to `this` would point to what `this` was before the function was created. As you see in the result, `this` was pointing to the `Window` object before `print` was created. Let's see another example: ``` const obj = { name: 'deeecode', age: 200, print: function() { const print2 = () => { console.log(this) } print2() } } obj.print() // { // name: 'deeecode', // age: 200, // print: [Function: print] // } ``` Here, we have `print` as a normal function which means a `this` variable is automatically created in it. Then we have `print2` which is an arrow function. Because `obj` is calling `print` (as in `obj.print()`), the `this` in `print` would point to `obj`. Since `print2` is an arrow function, it doesn't create its own `this` variable. Therefore, any reference to `this` would point to what the value of `this` was before the function was created. In this case where `obj` calls `print`, `this` was pointing to `obj` before `print2` was created. As you can see in the results, by logging `this` from `print2`, `obj` is the result. You can learn more about [`this` in my article here](https://dillionmegida.com/p/this-demystified/) ## 3\. Arrow functions cannot be used as constructors With normal functions, you can create constructors which serve as a special function for instantiating an object from a class. Here is an example of an `Animal` class which we instantiate two objects from: ``` class Animal { constructor(name, numOfLegs) { this.name = name this.numOfLegs = numOfLegs } sayName() { console.log(`My name is ${this.name}`) } } const Dog = new Animal("Bingo", 4) const Bird = new Animal("Steer", 2) Dog.sayName() // My name is Bingo Bird.sayName() // My name is Steer ``` Here, we have the `Animal` constructor which can be instantiated with different parameters. In the constructor, two arguments are required: `name` and `noOfLegs`. In the case of `Dog`, we create a new instance of `Animal` using "Bingo" as the `name` and **4** as the `noOfLegs`. In the case of `Bird`, we create a new instance of `Animal` using "Steer" as the `name` and **2** as the `noOfLegs`. By calling `sayName` on `Dog` and `Bird`, you can see how the method works currently with each object. The `this` variable points to the objects and the `name` field is gotten from each of them. The `this` variable is very important for classes and constructors. In point 2, we saw that arrow functions cannot create their own `this`. For this reason, arrow functions also cannot be used as constructors. Let's attempt it and see what happens: ``` class Animal { constructor = (name, numOfLegs) => { this.name = name this.numOfLegs = numOfLegs } sayName() { console.log(`My name is ${this.name}`) } } // Uncaught SyntaxError: Classes may not have a field named 'constructor' ``` Here, we have an arrow function used for the `constructor`. But, we get a SyntaxError: **Classes may not have a field named 'constructor'**. Because arrow functions involve expressions that are assigned variables, JavaScript now sees `constructor` as a field. And in classes, you cannot have a field named `constructor` as that is a reserved name. But, we can use arrow functions for the methods in the class without getting errors. For example: ``` class Animal { constructor (name, numOfLegs){ this.name = name this.numOfLegs = numOfLegs } sayName = () => { console.log(`My name is ${this.name}`) } } const Dog = new Animal("Bingo", 4) Dog.sayName() // My name is Bingo ``` Here, we have a normal function for the `constructor`, and an arrow function for the `sayName` method. `sayName` is a field. And we do not get errors. By calling `sayName()` on `Dog`, we still get "My name is Bingo". Though `sayName` as an arrow function does not create its own `this`, remember that any reference to `this` would point to the value of it before the arrow function was created. In this case, the value of `this` pointed to `Dog` before `sayName` was created. ## 4\. Arrow functions cannot be declared When it comes to functions, you need to understand **function declaration** and **function expression**. Function declarations involve the `function` keyword and a name for the function. For example: ``` function printHello() { console.log("hello") } ``` `printHello` is a **declared function**. But, check out this example: ``` const printHello = function() { console.log("hello") } ``` In this case, `printHello` is not a declared function. We have an anonymous function (not named) on the right side of the assignment operator. This function is a **function expression**, which is assigned to the `printHello` variable. Though the `function` keyword is used, there is no name assigned, which makes it an expression and not a declaration. To prove that it is not a declaration, try the following: ``` function() { console.log("hello") } ``` Because this expression is not assigned to a variable, you get an error: **SyntaxError: Function statements require a function name** Back to arrow functions. Normal functions can be declared when you use the function keyword and a name, but arrow functions cannot be declared. They can only be expressed because they are anonymous: ``` const printHello = () => { console.log("hello") } ``` As you see here, we have an anonymous function (starting from `() => ...`) which is assigned to the `printHello` variable. `printHello` is not a declared function here. It is a variable that holds the evaluated value from the function expression. ## 5 Arrow functions cannot be accessed before initialization Hoisting is a concept where a variable or function is lifted to the top of its global or local scope before the whole code is executed. This makes it possible for such a variable/function to be accessed before initialization. Here's a function example: ``` printName() console.log("hello") function printName() { console.log("i am dillion") } // i am dillion // hello ``` As you can see here, we called `printName` before it was actually declared in the code. But we don't get any errors. `printName()` is executed (logging "i am dillion" to the console) before `console.log("hello")`. What happens here is hoisting. The `printName` function is raised to the top of the global scope (the scope it is declared in) before the whole code is executed, thereby making it possible to execute the function earlier. But not all kinds of functions can be accessed before initialization. All functions and variables in JavaScript are hoisted, but **only declared functions can be accessed before initialization**. Here's an example with an arrow function: ``` printName() console.log("hello") const printName = () => { console.log("i am dillion") } // ReferenceError: Cannot access 'printName' before initialization ``` Running this code, you get an error: **ReferenceError: Cannot access 'printName' before initialization**. As we saw in point 4, `printName` is not a declared function. It is a variable, declared with `const` which is assigned a function expression. Variables declared with `let` and `const` are hoisted, but they cannot be accessed before the line they are initialized. Let's say we use `var` for our arrow function: ``` printName() console.log("hello") var printName = () => { console.log("i am dillion") } // TypeError: printName is not a function ``` Here, we have declared the `printName` variable with `var`. The error we get now is **TypeError: printName is not a function**. The reason for this is that variables declared with `var` are hoisted and accessible, but they have a default value of `undefined`. So attempting to access `printName` before the line it was initialized with the function expression is interpreted as `undefined()`, and as you know, "undefined is not a function". You can learn more about [the hoisting differences between var, let, and const here](https://www.freecodecamp.org/news/javascript-let-and-const-hoisting/) ## Wrap up Although arrow functions allow you to write functions more concisely, they also have limitations. As we have seen in this article, some of the behaviors that occur in normal functions do not happen in arrow functions. If you want to create constructors, retain the normal behavior of `this` or have your functions hoisted, then arrow functions are not the right approach. If you enjoyed this article, please share it with others :) *** If you read this far, thank the author to show them you care. Say Thanks Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. [Get started](https://www.freecodecamp.org/learn) ADVERTISEMENT freeCodeCamp is a donor-supported tax-exempt 501(c)(3) charity organization (United States Federal Tax Identification Number: 82-0779546) Our mission: to help people learn to code for free. We accomplish this by creating thousands of videos, articles, and interactive coding lessons - all freely available to the public. Donations to freeCodeCamp go toward our education initiatives, and help pay for servers, services, and staff. You can [make a tax-deductible donation here](https://www.freecodecamp.org/donate/). ## Trending Books and Handbooks - [REST APIs](https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/) - [Clean Code](https://www.freecodecamp.org/news/how-to-write-clean-code/) - [TypeScript](https://www.freecodecamp.org/news/learn-typescript-with-react-handbook/) - [JavaScript](https://www.freecodecamp.org/news/learn-javascript-for-beginners/) - [AI Chatbots](https://www.freecodecamp.org/news/how-to-build-an-ai-chatbot-with-redis-python-and-gpt/) - [Command Line](https://www.freecodecamp.org/news/command-line-for-beginners/) - [GraphQL APIs](https://www.freecodecamp.org/news/building-consuming-and-documenting-a-graphql-api/) - [CSS Transforms](https://www.freecodecamp.org/news/complete-guide-to-css-transform-functions-and-properties/) - [Access Control](https://www.freecodecamp.org/news/how-to-build-scalable-access-control-for-your-web-app/) - [REST API Design](https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/) - [PHP](https://www.freecodecamp.org/news/the-php-handbook/) - [Java](https://www.freecodecamp.org/news/the-java-handbook/) - [Linux](https://www.freecodecamp.org/news/learn-linux-for-beginners-book-basic-to-advanced/) - [React](https://www.freecodecamp.org/news/react-for-beginners-handbook/) - [CI/CD](https://www.freecodecamp.org/news/learn-continuous-integration-delivery-and-deployment/) - [Docker](https://www.freecodecamp.org/news/the-docker-handbook/) - [Golang](https://www.freecodecamp.org/news/learn-golang-handbook/) - [Python](https://www.freecodecamp.org/news/the-python-handbook/) - [Node.js](https://www.freecodecamp.org/news/get-started-with-nodejs/) - [Todo APIs](https://www.freecodecamp.org/news/build-crud-operations-with-dotnet-core-handbook/) - [JavaScript Classes](https://www.freecodecamp.org/news/how-to-use-classes-in-javascript-handbook/) - [Front-End Libraries](https://www.freecodecamp.org/news/front-end-javascript-development-react-angular-vue-compared/) - [Express and Node.js](https://www.freecodecamp.org/news/the-express-handbook/) - [Python Code Examples](https://www.freecodecamp.org/news/python-code-examples-sample-script-coding-tutorial-for-beginners/) - [Clustering in Python](https://www.freecodecamp.org/news/clustering-in-python-a-machine-learning-handbook/) - [Software Architecture](https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns/) - [Programming Fundamentals](https://www.freecodecamp.org/news/what-is-programming-tutorial-for-beginners/) - [Coding Career Preparation](https://www.freecodecamp.org/news/learn-to-code-book/) - [Full-Stack Developer Guide](https://www.freecodecamp.org/news/become-a-full-stack-developer-and-get-a-job/) - [Python for JavaScript Devs](https://www.freecodecamp.org/news/learn-python-for-javascript-developers-handbook/) ## Mobile App - [![Download on the App Store](https://cdn.freecodecamp.org/platform/universal/apple-store-badge.svg)](https://apps.apple.com/us/app/freecodecamp/id6446908151?itsct=apps_box_link&itscg=30200) - [![Get it on Google Play](https://cdn.freecodecamp.org/platform/universal/google-play-badge.svg)](https://play.google.com/store/apps/details?id=org.freecodecamp) ## Our Charity [Publication powered by Hashnode](https://hashnode.com/) [About](https://www.freecodecamp.org/news/about/) [Alumni Network](https://www.linkedin.com/school/free-code-camp/people/) [Open Source](https://github.com/freeCodeCamp/) [Shop](https://www.freecodecamp.org/news/shop/) [Support](https://www.freecodecamp.org/news/support/) [Sponsors](https://www.freecodecamp.org/news/sponsors/) [Academic Honesty](https://www.freecodecamp.org/news/academic-honesty-policy/) [Code of Conduct](https://www.freecodecamp.org/news/code-of-conduct/) [Privacy Policy](https://www.freecodecamp.org/news/privacy-policy/) [Terms of Service](https://www.freecodecamp.org/news/terms-of-service/) [Copyright Policy](https://www.freecodecamp.org/news/copyright-policy/)
Readable Markdown
![Arrow Functions vs Regular Functions in JavaScript – What's the Difference?](https://www.freecodecamp.org/news/content/images/size/w2000/2023/04/25-arrow-normal-functions.png) By Dillion Megida In JavaScript, there are two types of functions. You have normal functions and arrow functions. Let's explore the difference between them in this article. Arrow functions was introduced in ES6. And it introduced a simple and shorter way to create functions. Here's how to create a normal function, with arguments, which returns something: ``` function multiply(num1, num2) { const result = num1 * num2 return result } ``` If you want to transform this into an arrow function, here's what you'll have: ``` const multiply = (num1, num2) => { const result = num1 * num2 return result } ``` If the `return` statement is the only statement in the function, you can even have a shorter function expression. For example: ``` const multiply = (num1, num2) => { return num1 * num2 } ``` This function only contains the `return` statement. With arrow functions, we can have something shorter like this: ``` const multiply = (num1, num2) => num1 * num2 ``` We skip the curly braces and the `return` keyword. Shorter; one-liner. But the syntax of writing both types of functions is not the only difference. There's more, so let's look at them. I have a [video version of this topic](https://youtu.be/M10gzHpIUDw) which you can also check out :) ## 1\. No `arguments` object in arrow functions A normal function has an `arguments` object which you can access in the function: ``` function print() { console.log(arguments) } ``` The `arguments` object is a local variable that contains the arguments passed to the function when called. Let's try it out: ``` print("hello", 400, false) // { // '0': 'hello', // '1': 400, // '2': false // } ``` As you can see here, the three arguments passed when calling `print()` are contained in the `arguments` object which we log to the console. We can access the first argument with `arguments[0]`, the second with `arguments[1]` and the third with `arguments[2]` But this object does not exist in arrow functions. Let's try it out. Say we have `print` using an arrow function: ``` const print = () => { console.log(arguments) } print("hello", 400, false) // Uncaught ReferenceError: arguments is not defined ``` Now we have a reference error: **arguments is not defined**. That's because the `arguments` variable does not exist in arrow functions. ## 2\. Arrow functions do not create their own `this` binding In normal functions, a `this` variable is created which references the objects that call them. For example: ``` const obj = { name: 'deeecode', age: 200, print: function() { console.log(this) } } obj.print() // { // name: 'deeecode', // age: 200, // print: [Function: print] // } ``` As you can see here, the `this` in the `print` method points to `obj`, which is the object that calls the method. Here's another example: ``` const obj = { name: 'deeecode', age: 200, print: function() { function print2() { console.log(this) } print2() } } obj.print() // Window ``` Here, we have two functions. The first one is `print` which is a method of the `obj` object. The second is `print2` which is a function declared inside `print`. `print2()` is also called directly. In this case, `print` is called by `obj` (`obj.print()`) but no object calls `print2` (`print2()`). So the `this` in `print2` would reference the window object by default. Now let's see what happens with an arrow function. ``` const obj = { name: 'deeecode', age: 200, print: () => { console.log(this) } } obj.print() // Window ``` By using an arrow function for `print`, this function does not automatically create a `this` variable. As a result, any reference to `this` would point to what `this` was before the function was created. As you see in the result, `this` was pointing to the `Window` object before `print` was created. Let's see another example: ``` const obj = { name: 'deeecode', age: 200, print: function() { const print2 = () => { console.log(this) } print2() } } obj.print() // { // name: 'deeecode', // age: 200, // print: [Function: print] // } ``` Here, we have `print` as a normal function which means a `this` variable is automatically created in it. Then we have `print2` which is an arrow function. Because `obj` is calling `print` (as in `obj.print()`), the `this` in `print` would point to `obj`. Since `print2` is an arrow function, it doesn't create its own `this` variable. Therefore, any reference to `this` would point to what the value of `this` was before the function was created. In this case where `obj` calls `print`, `this` was pointing to `obj` before `print2` was created. As you can see in the results, by logging `this` from `print2`, `obj` is the result. You can learn more about [`this` in my article here](https://dillionmegida.com/p/this-demystified/) ## 3\. Arrow functions cannot be used as constructors With normal functions, you can create constructors which serve as a special function for instantiating an object from a class. Here is an example of an `Animal` class which we instantiate two objects from: ``` class Animal { constructor(name, numOfLegs) { this.name = name this.numOfLegs = numOfLegs } sayName() { console.log(`My name is ${this.name}`) } } const Dog = new Animal("Bingo", 4) const Bird = new Animal("Steer", 2) Dog.sayName() // My name is Bingo Bird.sayName() // My name is Steer ``` Here, we have the `Animal` constructor which can be instantiated with different parameters. In the constructor, two arguments are required: `name` and `noOfLegs`. In the case of `Dog`, we create a new instance of `Animal` using "Bingo" as the `name` and **4** as the `noOfLegs`. In the case of `Bird`, we create a new instance of `Animal` using "Steer" as the `name` and **2** as the `noOfLegs`. By calling `sayName` on `Dog` and `Bird`, you can see how the method works currently with each object. The `this` variable points to the objects and the `name` field is gotten from each of them. The `this` variable is very important for classes and constructors. In point 2, we saw that arrow functions cannot create their own `this`. For this reason, arrow functions also cannot be used as constructors. Let's attempt it and see what happens: ``` class Animal { constructor = (name, numOfLegs) => { this.name = name this.numOfLegs = numOfLegs } sayName() { console.log(`My name is ${this.name}`) } } // Uncaught SyntaxError: Classes may not have a field named 'constructor' ``` Here, we have an arrow function used for the `constructor`. But, we get a SyntaxError: **Classes may not have a field named 'constructor'**. Because arrow functions involve expressions that are assigned variables, JavaScript now sees `constructor` as a field. And in classes, you cannot have a field named `constructor` as that is a reserved name. But, we can use arrow functions for the methods in the class without getting errors. For example: ``` class Animal { constructor (name, numOfLegs){ this.name = name this.numOfLegs = numOfLegs } sayName = () => { console.log(`My name is ${this.name}`) } } const Dog = new Animal("Bingo", 4) Dog.sayName() // My name is Bingo ``` Here, we have a normal function for the `constructor`, and an arrow function for the `sayName` method. `sayName` is a field. And we do not get errors. By calling `sayName()` on `Dog`, we still get "My name is Bingo". Though `sayName` as an arrow function does not create its own `this`, remember that any reference to `this` would point to the value of it before the arrow function was created. In this case, the value of `this` pointed to `Dog` before `sayName` was created. ## 4\. Arrow functions cannot be declared When it comes to functions, you need to understand **function declaration** and **function expression**. Function declarations involve the `function` keyword and a name for the function. For example: ``` function printHello() { console.log("hello") } ``` `printHello` is a **declared function**. But, check out this example: ``` const printHello = function() { console.log("hello") } ``` In this case, `printHello` is not a declared function. We have an anonymous function (not named) on the right side of the assignment operator. This function is a **function expression**, which is assigned to the `printHello` variable. Though the `function` keyword is used, there is no name assigned, which makes it an expression and not a declaration. To prove that it is not a declaration, try the following: ``` function() { console.log("hello") } ``` Because this expression is not assigned to a variable, you get an error: **SyntaxError: Function statements require a function name** Back to arrow functions. Normal functions can be declared when you use the function keyword and a name, but arrow functions cannot be declared. They can only be expressed because they are anonymous: ``` const printHello = () => { console.log("hello") } ``` As you see here, we have an anonymous function (starting from `() => ...`) which is assigned to the `printHello` variable. `printHello` is not a declared function here. It is a variable that holds the evaluated value from the function expression. ## 5 Arrow functions cannot be accessed before initialization Hoisting is a concept where a variable or function is lifted to the top of its global or local scope before the whole code is executed. This makes it possible for such a variable/function to be accessed before initialization. Here's a function example: ``` printName() console.log("hello") function printName() { console.log("i am dillion") } // i am dillion // hello ``` As you can see here, we called `printName` before it was actually declared in the code. But we don't get any errors. `printName()` is executed (logging "i am dillion" to the console) before `console.log("hello")`. What happens here is hoisting. The `printName` function is raised to the top of the global scope (the scope it is declared in) before the whole code is executed, thereby making it possible to execute the function earlier. But not all kinds of functions can be accessed before initialization. All functions and variables in JavaScript are hoisted, but **only declared functions can be accessed before initialization**. Here's an example with an arrow function: ``` printName() console.log("hello") const printName = () => { console.log("i am dillion") } // ReferenceError: Cannot access 'printName' before initialization ``` Running this code, you get an error: **ReferenceError: Cannot access 'printName' before initialization**. As we saw in point 4, `printName` is not a declared function. It is a variable, declared with `const` which is assigned a function expression. Variables declared with `let` and `const` are hoisted, but they cannot be accessed before the line they are initialized. Let's say we use `var` for our arrow function: ``` printName() console.log("hello") var printName = () => { console.log("i am dillion") } // TypeError: printName is not a function ``` Here, we have declared the `printName` variable with `var`. The error we get now is **TypeError: printName is not a function**. The reason for this is that variables declared with `var` are hoisted and accessible, but they have a default value of `undefined`. So attempting to access `printName` before the line it was initialized with the function expression is interpreted as `undefined()`, and as you know, "undefined is not a function". You can learn more about [the hoisting differences between var, let, and const here](https://www.freecodecamp.org/news/javascript-let-and-const-hoisting/) ## Wrap up Although arrow functions allow you to write functions more concisely, they also have limitations. As we have seen in this article, some of the behaviors that occur in normal functions do not happen in arrow functions. If you want to create constructors, retain the normal behavior of `this` or have your functions hoisted, then arrow functions are not the right approach. If you enjoyed this article, please share it with others :) *** Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. [Get started](https://www.freecodecamp.org/learn)
Shard32 (laksa)
Root Hash13723046482134587832
Unparsed URLorg,freecodecamp!www,/news/the-difference-between-arrow-functions-and-normal-functions/ s443