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

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
雷峰网
雷峰网
The Register - Security
The Register - Security
The Cloudflare Blog
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
I
InfoQ
博客园 - 三生石上(FineUI控件)
H
Help Net Security
博客园 - 司徒正美
Vercel News
Vercel News
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
云风的 BLOG
云风的 BLOG
B
Blog
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
L
LangChain Blog
人人都是产品经理
人人都是产品经理
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recorded Future
Recorded Future
小众软件
小众软件
Martin Fowler
Martin Fowler
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
腾讯CDC
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Apple Machine Learning Research
Apple Machine Learning Research
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Y
Y Combinator Blog
V
Visual Studio Blog
F
Fortinet All Blogs
Microsoft Azure Blog
Microsoft Azure Blog
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
V
V2EX
Blog — PlanetScale
Blog — PlanetScale

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()
Must Know Details about ES2016 Features
Dmitri Pavlutin · 2016-07-12 · via Dmitri Pavlutin Blog

Good news, in June 2016 ECMAScript 2016 was approved. It contains the features that passed the stage 4, which means finished, of the TC39 process:

This edition is smaller than ECMAScript 2015, but it doesn't mean less important. Still it has details that you should know before using the new features.

The new method array.includes(item, [fromIndex]) allows to determine if an array contains a specific element. The precedent approach, less comfortable, to verify an element existence is to use array.indexOf(item) !== -1.
The difference between the two of course is the shorter usage of include(). However these methods use different equality algorithms and threat variously the empty slots in array.

The exponentiation operator ** has edge cases when it comes to NaN.

The current article covers the details about ES2016 features with informative examples. Also it makes a comparison with older approaches in terms of compatibility, so you could migrate JavaScript code without surprises.

1. The array method includes()

The array method includes(element, [fromIndex]) determines whether an array contains a specific element and returns the corresponding boolean (true if element is found, false otherwise). An optional argument fromIndex allows to search from a specific index.

Let's see some basic examples:


let months = ['June', 'July', 'August'];

months.includes('June'); // => true

months.includes('January'); // => false


'June' element exists in months array, so includes() method returns true. For a non available 'January' element, the method returns false.

Notice that includes() requires the searched element to match by type, because it uses for comparison the same value zero algorithm (a slight modified version of strict equality):


let items = ['1', 5, 8];

items.includes(1); // => false

items.includes(8); // => true


items contains a string '1'. However when searching for a number items.includes(1) there is no match (false is returned), because '1' and 1 are different types (string and number correspondingly).

When searching for objects, the method will match only references to the same object:


class Season {

constructor(name) {

this.name = name;

}

}

let winter = new Season('Winter');

let summer = new Season('Summer');

let seasons = [winter, new Season('Summer')];

seasons.includes(winter); // => true

seasons.includes(summer); // => false


seasons.includes(winter) returns true, because winter variable is an object reference contained in seasons.
On the other hand seasons.includes(summer) returns false, since the collection does not have an item that references summer object. new Season('Summer') (indicated in the array literal) is a reference to a different instance, thus not equal to summer.

The includes() method is available in typed arrays too:


let int8Array = Int8Array.from([17, 25]);

int8Array.includes(17); // => true


1.1 Searching from an index

The method array.includes(element, [fromIndex]) accepts a second optional parameter fromIndex, which enables searching from a specific index:

  • For a number greater or equal to zero and less than array length, it indicates the index to start the search.
  • For a number greater or equal to the array length, includes() always returns false.
  • For a negative number, the search starts from a computed index: array.length + fromIndex.
  • If not specified, it defaults to 0.

Let's follow an example:


let countries = ['UK', 'USA', 'Ireland', 'France'];

countries.includes('UK', 1); // => false

countries.includes('Ireland', 1); // => true

countries.includes('USA', 6); // => false


'UK' element has index 0 in countries. However the search starts from 1 and the index 0 is skipped, so the element is not found.
'Ireland' has index 2, thus the search countries.includes('Ireland', 1) from index 1 is able to find it.
The 'USA' element is checked from index 6, which is bigger than the array length 4. includes() method for such situations returns false.

For a negative from index parameter, the search starts from array.length + fromIndex up to the end of array:


let numbers = [56, 11, 58, 89, 100];

numbers.includes(11, -2); // => false

numbers.includes(89, -2); // => true


The index to begin searching parameter is a negative number -2 and the search starts from index 5 - 2 = 3. The searched 11 is compared only with 89 and 100 elements, so there is no match.
When searching for 89 element with the same -2 offset, it is a match.

1.2 Searching for NaN

includes() method uses same value zero comparison algorithm (see here why), which is a modified version of the strict equality comparison. The main difference between the two is NaN with NaN equality consideration:

  • Same value zero considers that NaN is equal with NaN
  • Strict equality considers that NaN is not equal with NaN

Because includes() uses the same value zero comparison, it is possible to identify NaN elements:


let weirdNumbers = [-1, 100, NaN];

weirdNumbers.includes(NaN); // => true


weirdNumbers contains a NaN, so includes() method is able to find it.

indexOf() array method has a different behavior in this situation, because it uses the strict equality comparison. Even if the array contains NaN, indexOf() returns -1 (meaning element not found):


let weirdNumbers = [-1, 100, NaN];

weirdNumbers.indexOf(NaN); // => -1

NaN === NaN; // => false


weirdNumbers contains NaN, however indexOf() returns -1.
Strict equality operator === uses the same comparison algorithm, so NaN === NaN is false too.

Even if includes() can find NaN, it is best to code your application not to generate NaN (which indicates that a wrong operation on numbers was applied).

1.3 Searching in a sparse array

An array in JavaScript is sparse when it contains empty slots (a.k.a. holes), i.e. the elements do not have contiguous indexes starting from 0. Sparse arrays can be created using:

  • An array literal with missing element between commas [4, ,5]
  • An array constructor new Array(n), where n is a number
  • After applying delete array[index] operator

Let's see how an array literal creates a sparse array:


let sparseArray = [1, , 3];

sparseArray[1]; // => undefined

sparseArray[2]; // => 3


sparseArray contains an empty slot at index 1. Accessing an empty slot sparseArray[1] evaluates to undefined.

includes() method does not skip the holes in array during the search iteration. Because accessing a hole evaluates to undefined, calling includes(undefined) returns a match when a hole is encountered:


let sparseArray = [1, , 3];

sparseArray.includes(undefined); // => true


Since sparseArray has an empty slot at index 1, executing sparseArray.includes(undefined) returns true.

Many other array methods do skip the empty slots, as their array iteration algorithm verifies if the element exists.
This rule applies to indexOf() method too:


let sparseArray = [1, , 3];

sparseArray.indexOf(undefined); // => -1


indexOf() method returns -1 when searching for undefined in an array with holes.

Of course, the general rule is to avoid at all dealing with sparse arrays.

2. The exponentiation operator

The exponentiation operator base ** exponent raises the base to the power exponent.

Let's consider some examples:


2 ** 3; // => 8

5 ** 2; // => 25

0.5 ** 1; // => 0.5


The appropriate equivalent of this operator is Math.pow(base, exponent) function.

It is possible to combine the exponentiation with an assignment **= for a shorter form:


let num = 2;

num **=4;

num; // => 16


When combining the unary minus operator -number with the exponentiation: -x ** y, JavaScript first evaluates x to power y, then applies the minus sign to the result. Exponentiation has a higher priority over the unary minus operator.
The execution of -x ** y is equivalent to -(x ** y). For instance -5 ** 2 equals to -25.

2.1 Exponent special cases

Any number, including NaN, powered to 0 exponent evaluates to 1:


25 ** 0; // => 1

NaN ** 0; // => 1

Infinity ** 0; // => 1


If the exponent is NaN, the exponentiation result is always NaN, for any base value:


25 ** NaN; // => NaN

-5 ** NaN; // => NaN

NaN ** NaN; // => NaN


3. Finale

ECMAScript 2016 does not introduce big changes in the language. But it's the beginning of the JavaScript certain progress in smaller steps.

Without doubt includes() is a long-awaited method to check the existence of an element. The workaround used before that indexOf(item) !== -1 is not a comfortable alternative.

includes() method handles differently NaN and empty slots in arrays. In my opinion it evaluates these situations better and more predictable. In the end it's ok to return true when searching NaN value in an array that contains a NaN, instead of -1 (missing) like indexOf() does.

You probably won't deal a lot with the exponentiation operator, however a short form to raise to power it's nice to have in the pocket.

We, developers, are creating the future of JavaScript. If you have an interesting idea about a new language feature, do not hesitate to contribute to ECMAScript.

In your opinion, what important feature JavaScript still misses? Feel free to write a comment below.