preface
Recently is the school enrollment season, sometimes I will ask students about the arrow function and ordinary function similarities and differences, often can get some superficial answers, but not comprehensive and in-depth. So I’m going to write a whole article about the arrow function.
The arrow function was introduced into JavaScript by ES6 and is a new way of writing anonymous functions, similar to Lambda functions in other languages. Arrow functions differ from traditional functions in many ways, such as scope, syntax, and so on.
The function definitions
Before diving into the similarities and differences between arrow functions and traditional functions, let’s look at the use of traditional functions to better understand the similarities and differences between arrow functions.
The following is the definition of a sum function that returns the sum of two arguments.
function sum(a, b) {
return a + b
}
Copy the code
With traditional functions, you can call the function even before you define it
sum(1, 2)
function sum(a, b) {
return a + b
}
Copy the code
You can print out the function declaration by the function name
console.log(sum)
Copy the code
The following output is displayed:
ƒ sum(a, b) {return a + b}Copy the code
Function expressions can usually have a name, but they can also be anonymous, meaning functions have no name.
The sum function is declared anonymously as follows:
const sum = function (a, b) {
return a + b
}
Copy the code
We assigned the anonymous function to the sum variable, which would result in an error if called before the definition:
sum(1, 2)
const sum = function (a, b) {
return a + b
}
Copy the code
Uncaught ReferenceError: Cannot access ‘sum’ before initialization
We can also print sum:
const sum = function (a, b) {
return a + b
}
console.log(sum)
Copy the code
The printout looks like this:
ƒ (a, b) {return a + b}Copy the code
Sum is an anonymous function, not a named function.
Arrow function
There are a number of differences between arrow functions and normal functions. The biggest differences are that arrow functions don’t have their own this binding, don’t have prototype, and can’t be used as constructors. At the same time, arrow functions can be written more concisely as normal functions.
This binding
In JavaScript, this is often a tricky thing. In JavaScript there are bind, apply, call, and other methods that affect the object specified by this.
The arrow function’s this is semantic; therefore, the arrow function’s this is context-scoped. The following example will explain the difference between this and arrow functions:
const printNumbers = {
phrase: 'The current value is:',
numbers: [1, 2, 3, 4],
loop() {
this.numbers.forEach(function (number) {
console.log(this.phrase, number)
})
},
}
Copy the code
You might expect the loop function to print the text and the corresponding number, and then return undefined:
printNumbers.loop()
Copy the code
Output:
undefined 1
undefined 2
undefined 3
undefined 4
Copy the code
In the example above, this.phrase represents undefined, indicating that this in the anonymous function in the forEach method does not refer to printNumber. This is because ordinary functions do not determine the value of this by context scope, but by the object on which the function is actually called.
In older versions of JavaScript, you could show the bind this by using the bind method. Bind can be used as follows:
const printNumbers = { phrase: 'The current value is:', numbers: [1, 2, 3, 4]. ForEach (function (number) {console.log(this.phrase, function (number) {console.log(this.phrase, function (number) {console.log(this.phrase, function (number)); number) }.bind(this), ) }, } printNumbers.loop()Copy the code
This will print the correct result:
The current value is: 1
The current value is: 2
The current value is: 3
The current value is: 4
Copy the code
The arrow function provides a more elegant solution. Since the reference to this is context-scoped, it points to printNumbers:
const printNumbers = {
phrase: 'The current value is:',
numbers: [1, 2, 3, 4],
loop() {
this.numbers.forEach((number) => {
console.log(this.phrase, number)
})
},
}
printNumbers.loop()
Copy the code
Arrow functions as object methods
Arrow functions work fine in loops, but can be problematic as object methods.
const printNumbers = {
phrase: 'The current value is:',
numbers: [1, 2, 3, 4],
loop: () => {
this.numbers.forEach((number) => {
console.log(this.phrase, number)
})
},
}
Copy the code
Call the loop method
printNumbers.loop()
Copy the code
The result is the following error:
Uncaught TypeError: Cannot read property 'forEach' of undefined
Copy the code
This is because when the loop arrow function is declared, this will not point to printNumbers, but to an external Window. The Window does not have a numbers field, which causes an error. Therefore, object methods generally use traditional methods.
Arrow functions have no Prototype and constructor
Function or Class in JavaScript has a Prototype property that can be used for object copy or inheritance.
function myFunction() {
this.value = 5
}
// Log the prototype property of myFunction
console.log(myFunction.prototype)
Copy the code
Output:
{constructor: ƒ}
Copy the code
However, the arrow function does not have the Prototype property, so we can try printing the arrow function’s Prototype.
const myArrowFunction = () => {}
// Attempt to log the prototype property of myArrowFunction
console.log(myArrowFunction.prototype)
Copy the code
Output:
undefined
Copy the code
Also, because there is no Prototype attribute, there is no instantiation through new.
const arrowInstance = new myArrowFunction()
console.log(arrowInstance)
Copy the code
Output error:
Uncaught TypeError: myArrowFunction is not a constructor
Copy the code
In addition to these changes, there are some grammatical differences in the arrow function that make writing more concise.
Implied return
Traditional methods require braces {} and return the value via a return statement.
const sum = (a, b) => {
return a + b
}
Copy the code
Arrow functions simplify function declarations and provide implied return values.
const sum = (a, b) => a + b
Copy the code
Single arguments omit parentheses
Such as:
const square = (x) => x * x
Copy the code
When there is only one argument, you can omit () and write it as follows:
const square = x => x * x
square(10)
Copy the code
Output: 100
Some libraries always try to ignore (), while others always keep it, especially those in TypeScript that declare the type of each parameter. Therefore, you need to define the style of your code base first and stick to it.
Write in the last
In this article, you learned the difference between arrow functions and traditional functions. Arrow functions are always anonymous, have no Prototype or constructor, can’t be instantiated with new, and are determined by semantic context. Then you learned about syntactic optimizations for arrow functions, such as implicit returns, and the omission of parentheses for individual arguments.
“Dad” has been engaged in Internet research and development for more than 10 years, and has worked in IBM, SAP, Lufax, Ctrip and other domestic and foreign IT companies. Currently, he is in charge of the big front-end technology team related to catering in Meituan, and regularly shares his thoughts and summaries on big front-end technology, investment and financial management, and personal growth.