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

推荐订阅源

Help Net Security
Help Net Security
G
Google Developers Blog
P
Proofpoint News Feed
The GitHub Blog
The GitHub Blog
D
DataBreaches.Net
V
V2EX
Know Your Adversary
Know Your Adversary
T
The Exploit Database - CXSecurity.com
AWS News Blog
AWS News Blog
I
InfoQ
Microsoft Azure Blog
Microsoft Azure Blog
P
Privacy & Cybersecurity Law Blog
阮一峰的网络日志
阮一峰的网络日志
F
Fortinet All Blogs
S
Schneier on Security
P
Proofpoint News Feed
NISL@THU
NISL@THU
V
Vulnerabilities – Threatpost
U
Unit 42
Jina AI
Jina AI
L
LINUX DO - 热门话题
G
GRAHAM CLULEY
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Microsoft Security Blog
Microsoft Security Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Cisco Talos Blog
Cisco Talos Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
N
News and Events Feed by Topic
C
Cisco Blogs
B
Blog RSS Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
The Blog of Author Tim Ferriss
云风的 BLOG
云风的 BLOG
Y
Y Combinator Blog
量子位
Google DeepMind News
Google DeepMind News
Cloudbric
Cloudbric
T
Tor Project blog
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Threat Research - Cisco Blogs
Stack Overflow Blog
Stack Overflow Blog
V2EX - 技术
V2EX - 技术
The Last Watchdog
The Last Watchdog
Latest news
Latest news

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()
How && and || Operators Really Work in JavaScript
Dmitri Pavlutin · 2020-04-09 · via Dmitri Pavlutin Blog

The logical and (&&) and or (||) are logical operators in JavaScript. Normally, you're using these operators on booleans:


true && true // => true

true && false // => false

true || true // => true

true || false // => true


However, can you use && and || with operands other than booleans? Turns out, you can!

This post explains in detail how && and || operators work in JavaScript.

Before jumping into how the operators work, let's start with the basic concepts of truthy and falsy.

1. Falsy value

Because JavaScript is a loosely typed language, logical operations can be performed on any type. The expressions like 1 && 2, null || undefined, 'hello' && true are weird, but still valid in JavaScript.

To perform logical operations on any type, JavaScript decides whether a particular value can be considered falsy (an equivalent of false) or truthy (an equivalent of true).

Falsy is a value for which Boolean(value) returns false. Falsy values in JavaScript are only false, 0, '', null, undefined and NaN.


Boolean(false); // => false

Boolean(0); // => false

Boolean(''); // => false

Boolean(null); // => false

Boolean(undefined); // => false

Boolean(NaN); // => false


2. Truthy value

Truthy is a value for which Boolean(value) returns true. Saying it differently, truthy are the non-falsy values.

Examples of truthy values are true, 4, 'Hello', { name: 'John' } and everything else that's not falsy.


Boolean(true); // => true

Boolean(4); // => true

Boolean('Hello'); // => true

Boolean({ name: 'John' }); // => true


3. How && operator works

Now let's continue with proper learning of how && operator works. Note that the operator works in terms of truthy and fasly, rather than true and false.

Here's the syntax of the && operator in a chain:


operand1 && operand2 && ... && operandN


The expression is evaluated as follows:

Starting from left and moving to the right, return the first operand that is falsy. If no falsy operand was found, return the latest operand.

Let's see how the algorithm works in a few examples.

When the operands are booleans, it's simple:


true && false && true; // => false


The evaluation starts from left and moves to the right. The first true operand is passed. However, the second operand false is a falsy value, and evaluation stops. false becomes the result of the entire expression. The third operand true is not evaluated.

When operands are numbers:


3 && 1 && 0 && 10; // => 0


The evaluation is performed from left to right. 3 and 1 are passed because they are truthy. But the evaluation stops at the third operand 0 since it's falsy. 0 becomes the result of the entire expression. The fourth operand 10 is not evaluated.

A slighly more complex example with different types:


true && 1 && { name: 'John' }


Again, from left to right, the operands are checked for falsy. No operand is falsy, so the last operand is returned. The evaluation result is { name: 'John' }.

3.1 Skipping operands

The && evaluation algorithm is optimal because the evaluation of operands stops as soon as a falsy value is encountered.

Let's consider an example:


const person = null;

person && person.address && person.address.street; // => null


The evaluation of the long logical expression person && person.address && person.address.street stops right at the first operand person (which is null - i.e. falsy). person.address and person.address.street operands are skipped.

4. How || operator works

Here's a generalized syntax of || operator in chain:


operand1 || operand2 || ... || operandN


The evaluation of || happens this way:

Starting from left and moving to the right, return the first operand that is truthy. If no truthy operand was found, return the latest operand.

|| works the same way as &&, with the only difference that || stops evaluation when encounters a truthy operand.

Let's study some || examples.

A simple expression having 2 booleans:


true || false; // => true


The evaluation starts from left and moves to the right. Luckily, the first operand true is a truthy value, so the whole expression evaluates to true. The second operand false is not checked.

Having some numbers as operands:

The first operand 0 is falsy, so the evaluation continues. The second argument -1 is already truthy, so the evaluation stops, and the result is -1.

4.1 Default value when accessing properties

You can use a side-effect of the || evaluation to access an object property providing a default value when the property is missing.

For example, let's access the properties name and job of the person object. When the property is missing, simply default to a string 'Unknown'. Here's how you could use || operator to achieve it:


const person = {

name: 'John'

};

person.name || 'Unknown'; // => 'John'

person.job || 'Unknown'; // => 'Unknown'


Let's look at the expression person.name || 'Unknown'. Because the first operand person.name is 'John' (a truthy value), the evaluation early exists with the truthy value as a result. The expression evaluates to 'John'.

person.job || 'Unknown' operates differently. person.job is undefined, so the expression is the same as undefined || 'Unknown'. The || evaluation algorithm says that the expression should return the first operand that is truthy, which in this case is 'Unknown'.

5. Summary

Because JavaScript is a loosely typed language, the operands of && and || can be of any type.

The concepts of falsy and truthy are handy to deal with types conversion within logical operators. Falsy values are false, 0, '', null, undefined and NaN, while the rest of values are truthy.

&& operator evaluates the operands from left to right and returns the first falsy value encountered. If no operand is falsy, the latest operand is returned.

The same way || operator evaluates the operands from left to right but returns the first truthy value encountered. If no truthy value was found, the latest operand is returned.

While && and || evaluation algorithms seem weird at first, in my opinion, they're quite efficient. The algorithms perform early exit, which is a good performance optimization.

In terms of usage, I recommend to stick to booleans as operands for both && and ||, and avoid other types if possible. Logical expressions that operate only on booleans are easier to understand.

Can you explain how 0 || 1 && 2 is evaluated?