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

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
IT之家
IT之家
J
Java Code Geeks
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
W
WeLiveSecurity
B
Blog RSS Feed
V2EX - 技术
V2EX - 技术
H
Heimdal Security Blog
S
Security @ Cisco Blogs
博客园 - 叶小钗
月光博客
月光博客
Webroot Blog
Webroot Blog
H
Hacker News: Front Page
N
News and Events Feed by Topic
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Help Net Security
Help Net Security
S
Secure Thoughts
SecWiki News
SecWiki News
Last Week in AI
Last Week in AI
Hugging Face - Blog
Hugging Face - Blog
S
Schneier on Security
A
Arctic Wolf
博客园 - 司徒正美
T
Tor Project blog
T
Tenable Blog
量子位
D
DataBreaches.Net
PCI Perspectives
PCI Perspectives
T
The Exploit Database - CXSecurity.com
T
Threatpost
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
Cloudbric
Cloudbric
T
The Blog of Author Tim Ferriss
N
News | PayPal Newsroom
Project Zero
Project Zero
S
Securelist
Forbes - Security
Forbes - Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
B
Blog
L
LINUX DO - 热门话题
Security Archives - TechRepublic
Security Archives - TechRepublic
O
OpenAI News
C
Cisco Blogs
V
V2EX
P
Privacy & Cybersecurity Law Blog
Cisco Talos Blog
Cisco Talos Blog

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()
The Legend of JavaScript Equality Operator
Dmitri Pavlutin · 2016-01-04 · via Dmitri Pavlutin Blog
Post cover

During everyday JavaScript coding, it may be hard to see how the equality operator works. Especially when the operands have different types. Time to time this creates bugs in conditionals, which are difficult to identify. It is easy to understand why 0 == 8 is false or '' == false is true. But why {} == true is false is not obviously to see. If you're interested:

  • to know better the equality and identity operators
  • to learn the formal computation algorithm
  • to practice a plenty of examples

then make yourself comfortable and let's begin.

The following terminology is used in the article:

  • Operator is a symbol denoting an operation.
    For example the equality operator == compares two values, identity operator === compares two values and their types, addition operator + sums two numbers or concatenates two strings.
  • Operand is the subject of the operation, a quantity on which an operation is performed.
    In the expression 0 == {}, the 0 is the first operand and {} the second.
  • Primitive types in JavaScript are considered numbers, strings, booleans, null and undefined.

The identity operator

JavaScript is performing the equality evaluation. The interpreter first converts both operands to the same type. Then executes the identity comparison.
The identity evaluation algorithm (IEA) ===:

  1. If both operands have different types, they are not strictly equal
  2. If both operands are null, they are strictly equal
  3. If both operands are undefined, they are strictly equal
  4. If one or both operands are NaN, they are not strictly equal
  5. If both operands are true or both false, they are strictly equal
  6. If both operands are numbers and have the same value, they are strictly equal
  7. If both operands are strings and have the same value, they are strictly equal
  8. If both operands have reference to the same object or function, they are strictly equal
  9. In all other cases operands are not strictly equal.

The rules are quite simple.
It is worth mentioning that NaN in identity (and in equality) operator compared with any other value always evaluates to false. Lets consider some examples. It's the best way to remember the strict comparison algorithm.

Example 1


1 === "1" // false, IEA rule 1


Operands are different types (number and string) and based on IEA rule 1 they are not identical.

Example 2


0 === 0 // true, IEA rule 6


Operands are the same type (number) and have the same value, so they are strictly equal based on IEA rule 6.

Example 3


undefined === undefined // true, IEA rule 3


Both operands are undefined and applying the IEA rule 3 it's an equality.

Example 4


undefined === null // false, IEA rule 1


Because operands are different types, based on IEA rule 1 they're not identical.

Example 5


NaN === NaN // false, IEA rule 4


Operands are the same type (numbers), but the IEA rule 4 indicates than nothing is equal with a NaN. The result is false.

Example 6


var firstObject = {},

secondObject = firstObject;

secondObject['name'] = 'Neo';

secondObject === firstObject // true, IEA rule 8


Both variables firstObject and secondObject are references to the same object and based on IEA rule 8 the identity operator evaluates to true.

Example 7


[] === [] //false, IEA rule 9


The [] literal creates a new array reference. Both operands being the same type (object), however have reference to different objects. The IEA rule 9 says that the identity evaluates to false.

See the examples in JS Bin

Converting an object to a primitive

Another step before learning equality is understanding the object to primitive conversion. JavaScript use it when comparing an object with a primitive value. The object to primitive conversion algorithm (OPCA):

  1. If the method valueOf() exists it is called. If valueOf() returns a primitive, the object is converted to this value
  2. In other case if the method toString() exists it is called. If toString() returns a primitive, the object is converted to this value
  3. In other case JavaScript throws an error: TypeError: Cannot convert object to primitive value

Most of the native objects when calling the valueOf() method returns the object itself. So the toString() method is used more often.
A note about the Date objects: when converting to a primitive, the object is converted instantly to a string using toString() method. This way the rule 1 is skipped for Date. The plain JavaScript object, {} or new Object(), usually is converted to "[object Object]".
An array is converted to by joining it's elements with "," separator. For example [1, 3, "four"] is converted to "1,3,four".

The equality operator

Now it is the interesting part. Before reading this, I recommend to have a good understanding of the identity and object to primitive conversion parts, if you just scrolled here.
The equality evaluation algorithm (EEA) ==:

  1. If the operands have the same type, test them for strict equality using IEA. If they are not strictly equal, they aren't equal, otherwise they are equal
  2. If the operands have different types:
  3. If one operand is null and another undefined, they are equal
  4. If one operand is number and another is a string, convert the string to number. Compute the comparison again
  5. If one operand is boolean, transform true to 1 and false to 0. Compute the comparison again
  6. If one operand is an object and another is a number or string, convert the object to a primitive using OPCA. Compute the comparison again
  7. In all other cases operands are not equal

Let's consider some examples.

Example 1

  1. 1 == true (Transform true to 1 using EEA rule 2.3)
  2. 1 == 1 (Operands have the same type, numbers. Transform the equality to identity using EEA rule 1)
  3. 1 === 1 (Both operands are numbers and have the same value. Based on IEA rule 6, it's an equality)
  4. true

Example 2

  1. '' == 0 (One operand is string and another is number, based on EEA rule 2.2 the '' is transformed to a number)
  2. 0 == 0 (Operands are the same type, transform the equality to identity using EEA rule 1)
  3. 0 === 0 (Operands are the same type and have the same value, so based on IEA rule 6 it's an identity)
  4. true

Example 3

  1. null == 0 (null is a primitive of type null and 0 is number. Apply the EEA rule 3)
  2. false

Example 4


null == undefined // true


  1. null == undefined (Based on EEA rule 2.1 the operands are equal)
  2. true

Example 5

  1. NaN == NaN (Both operands are numbers. Transform the equality to identity using EEA rule 1)
  2. NaN === NaN (Based on rule IEA rule 4 the operands are not strictly equal)
  3. false

Example 6

  1. [''] == '' ([''] is an array and '' a string. Apply the EEA rule 2.4 and transform the array to a primitive using OPCA rule 2)
  2. '' == '' (Both operands are strings, so transform the equality to identity)
  3. '' === '' (Both operands are the same type and have the same value. Using the IEA rule 7 it's an identity)
  4. true

Example 7

  1. {} == true (Using the EEA rule 2.3, transform the true operand to 1)
  2. {} == 1 (First operand is an object, so it's necessary to transform it to a primitive using OPCA)
  3. "[object Object]" == 1 (Because first operand is a string and second a number, we need to transform the "[object Object]" to a number using the EEA rule 2.2)
  4. NaN == 1 (Both operands are numbers, so transform the equality to identity using EEA rule 1)
  5. NaN === 1 (Based on IEA rule 4, which says that nothing is equal with a NaN, the result is false)
  6. false

See the examples in JS Bin

Useful tips

Even after checking in details all the examples in this article, learning the algorithms, you may find complicated to instantly understand complex comparisons. Honestly this operator was a long time a black box for me too.

Let me tell you a little trick how to pass this. Add this article to bookmarks (using Ctrl+D) and next time you see an interesting case, write a step by step computation based on the equality algorithm. If you check by yourself at least 10 examples, you won't have any problems in the future.

Start right now! What is the result and the detailed explanation of [0] == 0? Feel free to write a comment with the response.

The equality operator == makes type conversions. As result some comparisons may have unexpected results, for example {} == true is false (see example 7). In most cases is safer to use the identity operator ===.

##Conclusion Equality and identity are probably one of the most used operators. Understanding them is one of the steps to write a stable and less buggy JavaScript.

Dmitri Pavlutin

About Dmitri Pavlutin

Software developer and sometimes writer. My daily routine consists of (but not limited to) drinking coffee, coding, writing, overcoming boredom 😉, developing a gift boxes Shopify app, and blogging about Shopify. Living in the sunny Barcelona. 🇪🇸