JavaScript: The difference between regular functions and arrow functions.
--
Hey Medium, my name is Gevorg, and I’m a software engineer specializing in Node.js.
Today I decided to write my first post, hopefully, you will find something new or interesting for you.
Feel free to add comments if any. Happy reading.
Today arrow functions have a big usage, but most people don’t know about all the differences between arrow functions and regular functions, so let’s start investigating them.
There are 7 differences between arrow functions and regular functions:
1. Implicit return
2. No arguments (argument was an array-like object)
3. No prototype object for arrow functions
4. Don’t have own this
5. Can’t be used as a function constructor
6. Can’t be used as a generator function
7. No duplicate name parameters
These are the main differences between the arrow and regular functions. Let’s go over them point by point.
Implicit return
First, let’s remember how we can return some value from a function, we just simply need to write the return keyword before the value that we want to return.
// regular function
function sum(a, b) {
return a + b; // returning the sum of a and b
}
There is no other way to return any value from a function, but it’s possible in arrow functions.
Let's see the example:
// arrow functions
// we can write it in regular way, with return keyword
const sum = (a, b) => {
return a + b;
}
// we can return the sum of a and b without return keyword
const sum = (a, b) => a + b;
// if we need to return some object, or multiline part of code
// we just need to wrap all code in round brackets
const getUser = () => ({
name: 'John',
age: 19
}); // return value {name: 'John', age: 19}
No arguments
So we have an array-like object called arguments in regular functions.
The arguments object stores all the arguments that we pass to the function, and we can access them via indexes. It also has length property and callee method which references the function.
Note:
Thearguments.callee()
method has been deprecated. There can be some browsers, which support it till now, but its usage is not recommended by the web standard. Using arguments callee in strict mode will throw a Type error.
I wanted to mention this as a side note for your information.
Let’s see the example:
function sum(a, b) {
console.log(arguments); // {0: 1, 1: 5, 2: true, 3: 'string'}
console.log(arguments.length); // 4
console.log(arguments.callee === sum); // true
return a + b;
}
sum(1, 5, true, 'string'); // return 6
Arrow functions don’t have arguments object, so once we try to access it, we will get the following error:
const sum = (a, b) => {
console.log(arguments);
console.log(arguments.length);
console.log(arguments.callee === sum);
return a + b;
}
sum(1, 2, 5, true, 'string');
// Uncaught ReferenceError: arguments is not defined
But arrow functions have access to the arguments object of the closest non-arrow parent function.
function hello(g) {
const sum = (a, b) => {
console.log(arguments); // {0: 'random'}
console.log(arguments.length); // 1
console.log(arguments.callee === hello); // true
return a + b;
};
sum(1, 2);
}
hello('random')
Note: There are some differences in Node.js
Trying to access arguments object in an arrow function defined globally in Node.js environment we will not get an error as all our code in Node.js is wrapped inside a function that has 5 arguments ( exports, require, module, __filename, __dirname ) and the arrow function will take the arguments object of the wrapper function.
No prototype object for arrow functions
One more difference is a prototype property. While we can access it from a regular function, in arrow functions we cannot do that as they simply do not have prototype property.
function foo() {};
const arrowFoo = () => {};
console.log(foo.prototype); // { constructor: f foo() }
console.log(arrowFoo.prototype); // undefined
Don’t have own this
Inside regular functions, the value of this is dynamic meaning that the value of this depends on how the function will be invoked.
Let's see some examples:
Note:
It nescessary to mention the difference between the environments we run the following code.
For example in browser, the value of this is a window global object, but in Node the value of this is a current module.
function foo() {
console.log(this)
}
foo() // global object (window) or {} (current module)
When executing an object method, the value of this inside the method will refer to the current object.
const obj = {
method() {
console.log(this)
}
}
obj.method(); // { method: [Function: method] }
Or, alternatively, we can bind a function with context, which we need:
function foo() {
console.log(this)
}
const obj = {key: 'value'};
foo.call(obj); // { key: 'value' }
So, we discussed and already remember how this works with regular functions. Now let's move to the arrow functions.
Arrow functions don’t define their own execution context, and take the value of this from the outer scope.
const foo = () => console.log(this);
foo(); // undefined
// arrow function as mthod
const obj = {
method: () => {
console.log(this);
}
}
obj.method(); // window in browser or {} current module in Node.js
Of course, we can use some methods like call, apply and bind, to bind the context of this, but it will not help us, arrow functions will take the value of this from the outer scope.
const foo = () => {
console.log(this);
}
const obj = {key: 'value'};
foo.call(obj); // window in browser or {} current module in Node.js
Can’t be used as a constructor
Functions in JavaScript can be used as a constructor, to help us create objects with the same shape, using new keyword, but arrow functions can’t be used as a constructor, JavaScript will throw TypeError.
// regular functions
function User(name, age) {
this.name = name;
this.age = age;
}
const john = new User('John', 11); // {name: 'John', age: 11}
//arrow functions
const User = (name, age) => {
this.name = name;
this.age = age;
}
const john = new User('John', 11); // TypeError: User is not a constructor
Can’t be used as a function generator
First, let's remember how we can define function generators and how they work.
function* foo() {
yield 1;
yield 2;
return 3;
}
let generator = foo();
let one = generator.next();
let two = generator.next();
let three = generator.next();
console.log(one); // {value: 1, done: false}
console.log(two); // {value: 2, done: false}
console.log(three); // {value: 3, done: true}
A function generator is defined using function* keyword, which is not possible in arrow functions. Arrow function syntax does not include function keyword, and there is no designated location to incorporate the * symbol. Additionally, attempting to use the yield keyword within an arrow function will result in the following error:
const fakeGenerator = () => {
yield 1;
yield 2;
return 3;
}
// SyntaxError: Unexpected number
// A 'yield' expression is only allowed in a generator body
Duplicate name parameters are not allowed in arrow functions
As this is a very rare case, let me begin by explaining what duplicate name parameters mean.
Let’s see an example:
// providing 3 parameters with the same name
function foo(a, a, a) {
return a;
}
foo(1, 2, 3);
In the following code, the value of a will be 3.
Initially, the code will assign a value of 1 to the parameter a. However, when we proceed to the second parameter, the value of a will be overwritten with the value 2. Finally, the third parameter will once again overwrite the value of a with the last assigned value, which is 3. So, in this example, the output of the foo function will be 3.
Now let's see where is the difference inside the arrow functions.
const foo = (a, a, a) => {
return a;
}
foo(1, 2, 3);
At first glance, it may not appear to cause any issues. However, when attempting to run the following code, we encounter a syntax error as follows:
// SyntaxError: Duplicate parameter name not allowed in this context
We just can’t write parameters with the same name inside arrow functions։
Conclusion
The main purpose of this article is to serve as both a handbook and a brief exploration of the subject matter. Hope this article will be useful, and you will learn something new or will refresh your knowledge.
Thank you, see you soon.