惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
GbyAI
GbyAI
博客园 - Franky
宝玉的分享
宝玉的分享
Blog — PlanetScale
Blog — PlanetScale
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
I
InfoQ
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
有赞技术团队
有赞技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Full Disclosure
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
博客园 - 【当耐特】
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Project Zero
Project Zero
量子位
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
美团技术团队
Attack and Defense Labs
Attack and Defense Labs
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Troy Hunt's Blog
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
P
Proofpoint News Feed
Schneier on Security
Schneier on Security
Spread Privacy
Spread Privacy
S
SegmentFault 最新的问题
L
LINUX DO - 最新话题
Simon Willison's Weblog
Simon Willison's Weblog
爱范儿
爱范儿
博客园 - 聂微东
A
About on SuperTechFans
PCI Perspectives
PCI Perspectives
D
Docker

Dmitri Pavlutin Blog

Pure Functions in JavaScript: A Beginner's Guide Record Type in TypeScript: A Quick Intro How to Write Comments in React: The Good, the Bad and the Ugly 4 Ways to Create an Enum in JavaScript React forwardRef(): How to Pass Refs to Child Components TypeScript Function Types: A Beginner's Guide How to Use v-model to Access Input Values in Vue Mastering Vue refs: From Zero to Hero Environment Variables in JavaScript: process.env 5 Must-Know Differences Between ref() and reactive() in Vue How to Destructure Props in Vue (Composition API) Triangulation in Test-Driven Development How to Use nextTick() in Vue Programming to Interface Vs to Implementation A Smarter JavaScript Mapper: array.flatMap() Array Grouping in JavaScript: Object.groupBy() How to Access ES Module Metadata using import.meta JSON Modules in JavaScript How to Trim Strings in JavaScript TypeScript Function Overloading How to Debounce and Throttle Callbacks in Vue How to Show/Hide Elements in Vue Sparse vs Dense Arrays in JavaScript How to Fill an Array with Initial Values in JavaScript Covariance and Contravariance in TypeScript What are Higher-Order Functions in JavaScript? How to Use TypeScript with React Components Index Signatures in TypeScript How to Use React useReducer() Hook unknown vs any in TypeScript A Guide to React Context and useContext() Hook How to Use Promise.any() 2 Ways to Remove a Property from an Object in JavaScript 'return await promise' vs 'return promise' in JavaScript How to Use Promise.allSettled() How to Use fetch() with JSON JavaScript Promises: then(f,f) vs then(f).catch(f) What is a Promise in JavaScript? How to Use Promise.all() A Simple Guide to Component Props in React Don't Stop Me Now: How to Use React useTransition() hook A Simple Explanation of JavaScript Variables: const, let, var ES Modules Dynamic Import How to Memoize with React.useMemo() How to Cleanup Async Effects in React Why Math.max() Without Arguments Returns -Infinity How to Debounce and Throttle Callbacks in React Don't Confuse Function Expressions and Function Declarations in JavaScript How to Use ES Modules in Node.js Solving a Mystery Behavior of parseInt() in JavaScript How to Use Array Reduce Method in JavaScript 3 Ways to Merge Arrays in JavaScript A Guide to Jotai: the Minimalist React State Management Library The Difference Between Values and References in JavaScript How to Implement a Queue in JavaScript A Helpful Algorithm to Determine "this" value in JavaScript React useRef() Hook Explained in 3 Steps 7 Interview Questions on "this" keyword in JavaScript. Can You Answer Them? How to Greatly Enhance fetch() with the Decorator Pattern 7 Interview Questions on JavaScript Closures. Can You Answer Them? What's a Method in JavaScript? array.sort() Does Not Simply Sort Numbers in JavaScript How to Solve the Infinite Loop of React.useEffect() The New Array Method You'll Enjoy: array.at(index) What's the Difference between DOM Node and Element? Why Promises Are Faster Than setTimeout()? Everything About Callback Functions in JavaScript How React Updates State 5 Mistakes to Avoid When Using React Hooks 5 Best Practices to Write Quality JavaScript Variables Type checking in JavaScript: typeof and instanceof operators 3 Ways to Check if a Variable is Defined in JavaScript React Forms Tutorial: Access Input Values, Validate, Submit Forms Prototypal Inheritance in JavaScript How to Timeout a fetch() Request How to Learn JavaScript If You're a Beginner A Simple Explanation of React.useEffect() A Simple Explanation of JavaScript Iterators How to Use React Controlled Inputs Everything about null in JavaScript How to Use Fetch with async/await Getting Started with Arrow Functions in JavaScript An Interesting Explanation of async/await in JavaScript Front-end Architecture: Stable and Volatile Dependencies Is it Safe to Compare JavaScript Strings? How to Access Object's Keys, Values, and Entries in JavaScript What Actually is a String in JavaScript? 3 Ways to Shallow Clone Objects in JavaScript (w/ bonuses) Checking if an Array Contains a Value in JavaScript JavaScript Event Delegation: A Beginner's Guide How to Parse URL in JavaScript: hostname, pathname, query, hash 3 Ways to Detect an Array in JavaScript How to Get the Screen, Window, and Web Page Sizes in JavaScript 3 Ways to Check If an Object Has a Property/Key in JavaScript How to Compare Objects in JavaScript Object.is() vs Strict Equality Operator in JavaScript Own and Inherited Properties in JavaScript 5 Differences Between Arrow and Regular Functions How to Use Object Destructuring in JavaScript Your Guide to React.useCallback()
5 Best Practices to Write Quality Arrow Functions
Dmitri Pavlutin · 2020-01-29 · via Dmitri Pavlutin Blog

The arrow function deserves the popularity. Its syntax is concise, binds this lexically, fits great as a callback.

In this post, you'll read 5 best practices to get even more benefits from the arrow functions.

1. Arrow function name inference

The arrow function in JavaScript is anonymous: the name property of the function is an empty string ''.


( number => number + 1 ).name; // => ''


The anonymous functions are marked as anonymous during a debug session or call stack analysis. Unfortunately, anonymous gives no clue about the code being executed.

Here's a debug session of a code that executes anonymous functions:

Anonymous arrow functions call stack

The call stack on the right side consists of 2 functions marked as anonymous. You can't get anything useful from such call stack information.

Fortunately, the function name inference (a feature of ES2015) can detect the function name under certain conditions. The idea of name inference is that JavaScript can determine the arrow function name from its syntactic position: e.g. from the variable name that holds the function object.

Let's see how function name inference works:


const increaseNumber = number => number + 1;

increaseNumber.name; // => 'increaseNumber'


Because the variable increaseNumber holds the arrow function, JavaScript decides that 'increaseNumber' could be a good name for that function. Thus the arrow function receives the name 'increaseNumber'.

A good practice is to use function name inference to name the arrow functions.

Now let's check a debug session with code that uses name inference:

Anonymous arrow functions call stack

Because the arrow functions have names, the call stack gives more information about the code being executed:

  • handleButtonClick function name indicates that a click event had happened
  • increaseCounter increases a counter variable.

2. Inline when possible

An inline function is a function that has only one expression. I like about arrow functions the ability to compose short inline functions.

For example, instead of using the long form of an arrow function:


const array = [1, 2, 3];

array.map((number) => {

return number * 2;

});


You could easily remove the curly braces { } and return statement when the arrow function has one expression:


const array = [1, 2, 3];

array.map(number => number * 2);


Here's my advice:

When the function has one expression, a good practice is to inline the arrow function.

3. Fat arrow and comparison operators

The comparison operators >, <, <= and >= look similar to the fat arrow => (which defines the arrow function).

When these comparison operators are used in an inline arrow function, it creates some confusion.

Let's define an arrow function that uses <= operator:


const negativeToZero = number => number <= 0 ? 0 : number;


The presence of both symbols => and <= on the same line is misleading.

To distinguish clearly the fat arrow from the comparison operator, the first option is to wrap the expression into a pair of parentheses:


const negativeToZero = number => (number <= 0 ? 0 : number);


The second option is to deliberately define the arrow function using a longer form:


const negativeToZero = number => {

return number <= 0 ? 0 : number;

};


These refactorings eliminate the confusion between fat arrow symbol and comparison operators.

If the arrow function contains the operators >, <, <= and >=, a good practice is to wrap the expression into a pair of parentheses or deliberately use a longer arrow function form.

4. Constructing plain objects

An object literal inside an inline arrow function triggers a syntax error:


const array = [1, 2, 3];

// throws SyntaxError!

array.map(number => { 'number': number });


JavaScript considers the curly braces a code block, rather than an object literal.

Wrapping the object literal into a pair of parentheses solves the problem:


const array = [1, 2, 3];

// Works!

array.map(number => ({ 'number': number }));


If the object literal has lots of properties, you can even use newlines, while still keeping the arrow function inline:


const array = [1, 2, 3];

// Works!

array.map(number => ({

'number': number

'propA': 'value A',

'propB': 'value B'

}));


My recommendation:

Wrap object literals into a pair of parentheses when used inside inline arrow functions.

5. Be aware of excessive nesting

The arrow function syntax is short, which is good. But as a side effect, it could be cryptic when many arrow functions are nested.

Let's consider the following scenario. When a button is clicked, a request to server starts. When the response is ready, the items are logged to console:


myButton.addEventListener('click', () => {

fetch('/items.json')

.then(response => response.json())

.then(json => {

json.forEach(item => {

console.log(item.name);

});

});

});


The arrow functions are 3 levels nesting. It takes effort and time to understand what the code does.

To increase readability of nested functions, the first approach is to introduce variables that each holds an arrow function. The variable should describe concisely what the function does (see arrow function name inference best practice).


const readItemsJson = json => {

json.forEach(item => console.log(item.name));

};

const handleButtonClick = () => {

fetch('/items.json')

.then(response => response.json())

.then(readItemsJson);

};

myButton.addEventListener('click', handleButtonClick);


The refactoring extracts the arrow functions into variables readItemsJson and handleButtonClick. The level of nesting decreases from 3 to 2. Now, it's easier to understand what the script does.

Even better you could refactor the entire function to use async/await syntax, which is a great way to solve the nesting of functions:


const handleButtonClick = async () => {

const response = await fetch('/items.json');

const json = await response.json();

json.forEach(item => console.log(item.name));

};

myButton.addEventListener('click', handleButtonClick);


Resuming:

A good practice is to avoid excessive nesting of arrow functions by extracting them into variables as separate functions or, if possible, embrace async/await syntax.

6. Conclusion

The arrow functions in JavaScript are anonymous. To make debugging productive, a good practice is to use variables to hold the arrow functions. This allows JavaScript to infer the function names.

An inline arrow function is handy when the function body has one expression.

The operators >, <, <= and >= look similar to the fat arrow =>. Care must be taken when these operators are used inside inline arrow functions.

The object literal syntax { prop: 'value' } is similar to a code of block { }. So when the object literal is placed inside an inline arrow function, you need to wrap it into a pair of parentheses: () => ({ prop: 'value' }).

Finally, the excessive nesting of functions obscures the code intent. A good approach to reduce the arrow functions nesting is to extract them into variables. Alternatively, try to use even better features like async/await syntax.

What's your favorite coding best practices? Leave a comment below!