In-depth understanding of JavaScript arrow functions. We will show you how to use ES6 arrow syntax, as well as some common mistakes to be aware of when using arrow functions in your code. You will see many examples that illustrate how it works.
After the release of ECMAScript 2015 (also known as ES6), JavaScript arrow functions appeared. Thanks to its concise syntax and how to handle the this
keyword, the arrow function quickly became one of the developers' favorite features.
function
keyword, curly braces {}
and the return
keyword when there is only one expression. this
arrow function captures its value to customize the closed context of the arrow function, not where it is called, which makes it suitable for traditional function expressions that need to be bound to an external this
context Condition. function
constructors, because they have lexical this
bindings and are missing arguments
objects. .map()
, .sort()
, .forEach()
, .filter()
, .reduce()
, Arrow function syntax: Rewrite regular functions
The
function is like a recipe where you can store useful instructions to accomplish what needs to happen in your program, such as performing an action or returning a value. By calling your function you can perform the steps contained in the recipe. You can do this every time you call the function without rewriting the recipe over and over again.// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
The following is the standard way to declare a function and call it in JavaScript:
const sayHiStranger = function () { return 'Hi, stranger!' }
You can also write the same function as a function expression as follows:
const sayHiStranger = () => 'Hi, stranger'
JavaScript arrow functions are always expressions. Here is how to rewrite the above function as an arrow function expression using fat arrow notation:
<🎜> <🎜>The advantages include: <🎜>function
Keywordreturn
Keyword{}
In JavaScript, the function is "first class citizen". You can store functions in variables, pass them as arguments to other functions, and return them as values from other functions. You can do all of these with JavaScript arrow functions.
In the above example, the function has no parameters. In this case, you have to add a set of empty brackets() before the fat arrow (=>) symbol. This is also true when you create a function with multiple parameters:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
However, when there is only one parameter, you can omit the brackets (not have to do this, but it can):
const sayHiStranger = function () { return 'Hi, stranger!' }
But be careful. For example, if you decide to use the default parameter, you must enclose it in parentheses:
const sayHiStranger = () => 'Hi, stranger'
Just because you can, it doesn't mean you should. With some lighthearted, kind-hearted satire, Kyle Simpson (the author of "You Don't Know JS") put his thoughts on omitting brackets into this flowchart. (The flowchart should be inserted here, but since the picture cannot be inserted directly, it is omitted here)
You can make the ES6 arrow syntax more concise when there is only one expression in the function body. You can put everything on one line, remove the curly braces, and remove the return
keyword.
You have just seen how these neat lines of code work in the example above. Let me give you another example for reference only. The function of the orderByLikes() function is as its name: it returns an array of Netflix series objects arranged in the order of the highest number of likes:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
This is cool, but be careful about the readability of the code - especially when sorting a bunch of arrow functions using a line of code and unbranched ES6 arrow syntax, like in this example:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
What happened there? Try using regular function syntax:
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
Now you can quickly understand how the external function greeter has a parameter greeting and returns an anonymous function. In turn, this internal function has a parameter named name and returns a string using greeting and name values. Here is how to call the function:
// 使用JS sort()函数按点赞数降序排列标题(点赞数越多,排名越高,点赞数越少,排名越低) const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes ) // 调用函数 // 输出:按降序排列的标题和点赞数 console.log(orderByLikes)
When your JavaScript arrow function contains multiple statements, you need to enclose all statements in curly braces and use the return
keyword.
In the following code, the function builds an object containing some Netflix series titles and summary (Netflix comments are from Rotten Tomato website):
const greeter = greeting => name => `${greeting}, ${name}!`
.map()
function is expanded through a series of statements and finally returns an object. This makes it inevitable to use curly braces around the function body.
Also, since you are using curly braces, implicit return is not an option. You must use the return
keyword.
If your function returns the object literal using implicit return , you need to enclose the object in parentheses. Failure to do so will result in an error because the JavaScript engine mistakenly parses the braces of the object literal into braces of the function. As you just noticed above, you cannot omit the return
keyword when you use curly braces in the arrow function.
The shorter version of the previous code demonstrates this syntax:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
Functions that have no name identifier between the function
keyword and the parameter list are called anonymous functions . Here is how regular anonymous function expressions look like:
const sayHiStranger = function () { return 'Hi, stranger!' }
Arrow functions are all anonymous functions:
const sayHiStranger = () => 'Hi, stranger'
Starting from ES6, variables and methods can infer the name of an anonymous function based on their syntactic position, using their name
attribute. This makes it possible to recognize the function when checking its value or reporting an error.
Check with anonymousArrowFunc:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
Note that this inferred name
attribute only exists when anonymous functions are assigned to variables, as shown in the example above. If you use anonymous functions as a callback function, this practical function is lost. This is illustrated by the following demonstration, where anonymous functions in the .setInterval()
method cannot use the name
attribute:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
And more than that. This inferred name
property still cannot be used as an appropriate identifier for which you can reference the function from within the function—for example, for recursion, unbinding events, etc.
The intrinsic anonymity of arrow functions leads Kyle Simpson to express his views on them as follows:
Since I think anonymous functions are not suitable for frequent use in programs, I don't like using the =>arrow function form. ——"You Don't Know JS"
The most important thing about arrow functions is to remember how they handle the this
keywords. In particular, the this
keyword inside the arrow function will not be rebinded.
To illustrate what this means, check out the following demonstration: (The code Pen should be inserted here, but since the code Pen cannot be inserted directly, it is omitted here)
This is a button. Clicking the button triggers a reverse counter from 5 to 1, which is displayed on the button itself.
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
Note how the event handler in the .addEventListener()
method is a regular anonymous function expression, not an arrow function. Why? If you log in the function this
, you will see that it references the button element with the listener attached, which is exactly the expected result and what the program needs to work as planned.
// 使用JS sort()函数按点赞数降序排列标题(点赞数越多,排名越高,点赞数越少,排名越低) const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes ) // 调用函数 // 输出:按降序排列的标题和点赞数 console.log(orderByLikes)
In the Firefox Developer Tools console, it looks like this: (The image should be inserted here, but since the image cannot be inserted directly, it is omitted here)
However, try replacing the regular function with the arrow function as follows:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
Now, this
no longer quotes buttons. Instead, it references a Window object: (The image should be inserted here, but since the image cannot be inserted directly, it is omitted here)
This means that if you want to add a class to the button using this
after clicking the button, your code won't work, as shown in the following example:
const sayHiStranger = function () { return 'Hi, stranger!' }
The error message in the console is as follows: (The picture should be inserted here, but since the picture cannot be inserted directly, it is omitted here)
When you use arrow functions in JavaScript, the value of the this
keyword is not rebined. It inherits from the parent scope (this is called the lexical scope). In this particular case, the arrow function in question is passed as an argument to the startBtn.addEventListener()
method, which is in the global scope. Therefore, this
in the function handler is also bound to the global scope - that is, the Window object.
So if you want this
to reference the start button in your program, the correct way is to use a regular function, not an arrow function.
The next thing to note is the code in the .setInterval()
method in the above demonstration. Here you will also find an anonymous function, but this time it is an arrow function. Why?
Note that if you use a regular function, what will the value of this
be:
const sayHiStranger = () => 'Hi, stranger'
Will it be a button element? Not at all. It will be a Window object! (The picture should be inserted here, but since the picture cannot be inserted directly, it is omitted here)
In fact, the context has changed because this
is now in an unbound or global function that is passed as an argument to .setInterval()
. Therefore, the value of the this
keyword also changes because it is now bound to the global scope.
In this case, a common trick is to include another variable to store the value of the this
keyword so that it continues to reference the expected element—in this case the button element:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
You can also use .bind()
to solve this problem:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
Using the arrow function, the problem completely disappeared. The following is the value of this
when using the arrow function:
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
(The picture should be inserted here, but since the picture cannot be inserted directly, it is omitted here)
This time, the console recorded the buttons, which is what we wanted. In fact, the program will change the button text, so it needs this
to reference the button element:
// 使用JS sort()函数按点赞数降序排列标题(点赞数越多,排名越高,点赞数越少,排名越低) const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes ) // 调用函数 // 输出:按降序排列的标题和点赞数 console.log(orderByLikes)
arrow function does not have its own this
context. They inherit from the parent's this
value, and it is because of this feature that they become an excellent choice in the above situations.
Arrow functions are not just a fancy new way to write JavaScript functions. They have their own limitations, which means that in some cases you don't want to use it. The click handler in the previous demonstration is an example, but this is not the only one. Let's check a few more.
Arrow function is not used well as an object method. Here is an example.
Consider this netflixSeries object, which has some properties and several methods. Call console.log(netflixSeries.getLikes())
should print a message containing the current number of likes. Call console.log(netflixSeries.addLike())
should increase the number of likes by one, and then print a new value and a thank you message in the console:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
In contrast, calling the .getLikes()
method returns "undefined has NaN likes", and calling the .addLike()
method returns "Thank you for liking undefined, which now has NaN likes". Therefore, this.title
and this.likes
cannot refer to the properties of an object title
and likes
respectively.
Same problem lies in the lexical scope of the arrow function. this
in the object method is referencing the parent scope, in this case, it is a Window object, not the parent object itself - that is, it is not a netflixSeries object.
Of course, the solution is to use the regular function:
const sayHiStranger = function () { return 'Hi, stranger!' }
Another thing to note is that third-party libraries usually bind method calls so that the this
value points to useful content.
For example, in a jQuery event handler, this
will allow you to access the DOM element of the bound handler:
const sayHiStranger = () => 'Hi, stranger'
However, if we use the arrow function - as we have seen, it does not have its own this
context - we will get unexpected results:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
Here is a further example of using Vue:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
In the created
hook, this
binds to the Vue instance, so the message "Hello, World!" is displayed.
However, if we use the arrow function, this
will point to the parent scope, which does not have the message
attribute:
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
Sometimes you may need to create a function with an uncertain number of parameters. For example, suppose you want to create a function that lists your favorite Netflix series in order of preference. However, you don't know how many series you want to include. JavaScript provides arguments
objects. This is an array-like object (not a complete array) that stores the value passed to the function when it is called.
Try to implement this function using the arrow function:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
When you call the function, you will receive the following error message: Uncaught ReferenceError: arguments is not defined. This means that the arguments
object is not available in the arrow function. In fact, replacing the arrow function with a regular function can solve the problem:
const sayHiStranger = function () { return 'Hi, stranger!' }
Therefore, if you need arguments
objects, you cannot use the arrow function.
But what if you really want to use the arrow function to copy the same function? One thing you can do is use the remaining parameters of ES6 (...). Here is how to rewrite your function:
const sayHiStranger = () => 'Hi, stranger'
keyword in JavaScript. The arrow function also works well with array methods such as this
, .map()
, .sort()
, .forEach()
, .filter()
and .reduce()
. But remember: arrow functions do not replace regular JavaScript functions. Remember, use them only if arrow functions are the correct tool.
If you have any questions about arrow functions, or need any help to use them correctly, I recommend you visit the SitePoint-friendly forum. There are a lot of knowledgeable programmers out there ready to help.
You can define arrow functions using the following syntax: (parameters) => expression. For example: (x,y)=>x y defines an arrow function that takes two parameters and returns their sum.
You can define arrow functions using the following syntax: (parameters) => expression. For example: (x,y)=>x y defines an arrow function that takes two parameters and returns their sum.
The arrow function and the regular function are different in the following aspects:
They don't have their own this
. Instead, they inherit the this
value of the surrounding lexical scope.
Arrow functions cannot be used as constructors, which means you cannot create instances of objects using new
.
The arrow function does not have its own arguments
object. Instead, they inherit the closed scope arguments
.
The arrow function is simpler and more suitable for simple single-line operations.
Arrow functions provide concise syntax to make your code more readable. They also help avoid the problem of this
binding, as they inherit the surrounding context. This can simplify certain coding patterns and reduce the need for workarounds such as bind
, apply
or call
.
Although arrow functions are useful for many scenarios, they may not work in all cases. They are best suited for short and simple functions. Traditional functions may be more suitable for complex functions or functions that require their own this
context.
The arrow function was introduced in ECMAScript 6 (ES6) and is supported by modern browsers and Node.js versions. They are widely used in modern JavaScript development.
arrow function cannot be used as a constructor, does not have its own arguments
object, and is not very suitable for methods that require a dynamic this
context. Furthermore, their concise syntax may not be suitable for functions containing multiple statements.
Yes, arrow functions can be used for methods in objects or classes. However, remember that arrow functions do not have their own this
, so they may not work as expected in methods that require dynamic this
context.
When returning object literals directly from arrow functions, the object needs to be enclosed in parentheses to avoid confusion with function blocks. For example: () => ({ key: value }).
Yes, if the arrow function accepts a single parameter, the brackets around the parameter can be omitted. For example, x => x * 2 is a valid arrow function.
The above is the detailed content of Arrow Functions in JavaScript: Fat & Concise Syntax. For more information, please follow other related articles on the PHP Chinese website!