|
| 1 | +# Chapter 23: What's new in ES2021 |
| 2 | + |
| 3 | +Let's get started with the first of the new ES2021 features: |
| 4 | + |
| 5 | +## String.prototype.replaceAll |
| 6 | + |
| 7 | +`String.replace` is a useful method that allows us to replace a pattern in a string with something else. The problem is that if we want to use a `string` as a pattern and not a RegEx, only the **first** occurrence will get replaced. |
| 8 | + |
| 9 | +```js |
| 10 | +const str = "I like my dog, my dog loves me"; |
| 11 | +const newStr = str.replace("dog", "cat"); |
| 12 | +newStr; |
| 13 | +// "I like my cat, my dog loves me" |
| 14 | +``` |
| 15 | + |
| 16 | +As the name implies, `String.replaceAll` will do exactly what we need in this scenario, replace all the matching pattern, allowing us to easily replace all mentions of a substring, without the use of RegEx: |
| 17 | + |
| 18 | +```js |
| 19 | +const str = "I like my dog, my dog loves me"; |
| 20 | +const newStr = str.replaceAll("dog", "cat"); |
| 21 | +newStr; |
| 22 | +// "I like my cat, my cat loves me" |
| 23 | +``` |
| 24 | + |
| 25 | +[Read More](https://github.com/tc39/proposal-string-replaceall) |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +## Promise.any |
| 30 | + |
| 31 | +During the past years we've seen new methods such as `Promise.all` and `Promise.race` with ES6, `Promise.allSettled` last year with ES2020 and ES2021 will introduce a new one: `Promise.any`. |
| 32 | + |
| 33 | +I bet you can already tell what it does from the name of the method. |
| 34 | + |
| 35 | +`Promise.any` shorts-circuits once a given promise is fulfilled but will continue until all promises are rejected. |
| 36 | + |
| 37 | +Don't get confused with `Promise.race` because with `race`, the promise short-circuits once one of the given promises resolves **or rejects**. |
| 38 | + |
| 39 | +They have similar behavior for what concerns fulfillment but very different for rejection. |
| 40 | + |
| 41 | +If all the promises inside of `Promise.any` fails, it will throw an `AggregateError` (a subclass of `Error`) containing the rejection reasons of all the promises. |
| 42 | + |
| 43 | +We can use it like this: |
| 44 | + |
| 45 | +```javascript |
| 46 | +// example taken from: https://github.com/tc39/proposal-promise-any |
| 47 | +Promise.any(promises).then( |
| 48 | + (first) => { |
| 49 | + // Any of the promises was fulfilled. |
| 50 | + }, |
| 51 | + (error) => { |
| 52 | + // All of the promises were rejected. |
| 53 | + } |
| 54 | +); |
| 55 | +``` |
| 56 | + |
| 57 | +[Read More](https://github.com/tc39/proposal-promise-any) |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +## Logical Operators and Assignment Expressions |
| 62 | + |
| 63 | +With `ES2021` we will be able to combine Logical Operators (`&&`, `||` and `??`) with Assignment Expression (`=`) similarly to how it's already possible to do in Ruby. |
| 64 | + |
| 65 | +If you skipped on `ES2020` you may not be aware of `??` which is the **nullish coalescing** operator. Let's look at an example: |
| 66 | + |
| 67 | +```js |
| 68 | +const a = null ?? "test"; |
| 69 | +// 'test' |
| 70 | +const b = 0 ?? "test"; |
| 71 | +// 0 |
| 72 | +``` |
| 73 | +
|
| 74 | +The **nullish coalescing** operator returns the _right_ hand-side when the left-hand-side is `null` or `undefined`, otherwise it returns the _left_ hand-side. In the first example the left-hand-side was `null` thus it returned the right-hand-side while on the second example it returned the left-hand-side because it was neither `null` nor `undefined`. |
| 75 | +
|
| 76 | +Moving back to ES2021 stuff, in `JavaScript` we already have many [assignment opeartors](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#Assignment_operators) like the following basic example: |
| 77 | +
|
| 78 | +```js |
| 79 | +let a = 0; |
| 80 | +a += 2; |
| 81 | +// 2 |
| 82 | +``` |
| 83 | +
|
| 84 | +But with this new proposal we will be able to do the following: |
| 85 | +
|
| 86 | +```js |
| 87 | +a ||= b; |
| 88 | +// equivalent to a = a || b |
| 89 | + |
| 90 | +c &&= d; |
| 91 | +// equivalent to c = c && d |
| 92 | + |
| 93 | +e ??= f; |
| 94 | +// equivalent to e = e ?? f |
| 95 | +``` |
| 96 | +
|
| 97 | +Let's go over each one by one: |
| 98 | +
|
| 99 | +- `a ||= b` will return `a` if `a` is a truthy value, or `b` if `a` is falsy |
| 100 | +- `c &&= d` will return `d` if both `c` and `d` are truthy, or `c` otherwise |
| 101 | +- `e ??= f` will return `f` if `e` is `null` or `undefined` otherwise it will return `e` |
| 102 | +
|
| 103 | +[Read More](https://github.com/tc39/proposal-logical-assignment) |
| 104 | +
|
| 105 | + |
| 106 | +
|
| 107 | +## Numeric Separators |
| 108 | +
|
| 109 | +The introduction of Numeric Separators will make it easier to read numeric values by using the `_` (underscore) character to provide a separation between groups of digits. |
| 110 | +
|
| 111 | +Let's look at more examples: |
| 112 | +
|
| 113 | +```js |
| 114 | +x = 100_000; |
| 115 | +// 100 thousand |
| 116 | + |
| 117 | +dollar = 55_90; |
| 118 | +// 55 dollar 90 cents |
| 119 | + |
| 120 | +fraction = 0.000_1; |
| 121 | +// 1 thousandth |
| 122 | +``` |
| 123 | +
|
| 124 | +[Read more](https://github.com/tc39/proposal-numeric-separator) |
| 125 | +
|
| 126 | + |
| 127 | +
|
| 128 | +## WeakRefs |
| 129 | +
|
| 130 | +From [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef#:~:text=A%20weak%20reference%20to%20an%20object%20is%20a%20reference%20that,reclaimed%20by%20the%20garbage%20collector.&text=When%20an%20object%20no%20longer,object%20and%20reclaim%20its%20memory.): A weak reference to an object is a reference that does not prevent the object from being reclaimed by the garbage collector. |
| 131 | +
|
| 132 | +With this new proposal for ES2021, we will be able to create weak references to objects with the `WeakRef` class. Please follow the link below to read a more in-depth explanation. |
| 133 | +
|
| 134 | +[Read More](https://github.com/tc39/proposal-weakrefs) |
| 135 | +
|
| 136 | + |
| 137 | +
|
| 138 | +## Intl.ListFormat |
| 139 | +
|
| 140 | +The `Intl.ListFormat` object is a constructor for objects that enable language-sensitive list formatting. |
| 141 | +
|
| 142 | +Looking at an example is easier than explaining it: |
| 143 | +
|
| 144 | +```js |
| 145 | +const list = ["Apple", "Orange", "Banana"]; |
| 146 | + |
| 147 | +new Intl.ListFormat("en-GB", { style: "long", type: "conjunction" }).format( |
| 148 | + list |
| 149 | +); |
| 150 | +// Apple, Orange and Banana |
| 151 | + |
| 152 | +new Intl.ListFormat("en-GB", { style: "short", type: "disjunction" }).format( |
| 153 | + list |
| 154 | +); |
| 155 | +// Apple, Orange or Banana |
| 156 | +``` |
| 157 | +
|
| 158 | +You are not limited to English, let's try with a few different languages: |
| 159 | +
|
| 160 | +```js |
| 161 | +const list = ["Apple", "Orange", "Banana"]; |
| 162 | + |
| 163 | +// Italian |
| 164 | +console.log( |
| 165 | + new Intl.ListFormat("it", { style: "long", type: "conjunction" }).format(list) |
| 166 | +); |
| 167 | +// Apple, Orange e Banana |
| 168 | + |
| 169 | +// Spanish |
| 170 | +console.log( |
| 171 | + new Intl.ListFormat("es", { style: "long", type: "conjunction" }).format(list) |
| 172 | +); |
| 173 | +// Apple, Orange y Banana |
| 174 | + |
| 175 | +// German |
| 176 | +console.log( |
| 177 | + new Intl.ListFormat("de", { style: "long", type: "conjunction" }).format(list) |
| 178 | +); |
| 179 | +// Apple, Orange und Banana |
| 180 | +``` |
| 181 | +
|
| 182 | +Pretty neat uh? For a more detailed look at this specification check out the link below. |
| 183 | +
|
| 184 | +[Read More](https://github.com/tc39/proposal-intl-list-format) |
| 185 | +
|
| 186 | + |
| 187 | +
|
| 188 | +## dateStyle and timeStyle options for Intl.DateTimeFormat |
| 189 | +
|
| 190 | +We can use `dateStyle` and `timeStyle` to request a locale-specific date and time of a given length. |
| 191 | +
|
| 192 | +```js |
| 193 | +// short |
| 194 | +new Intl.DateTimeFormat("en", { |
| 195 | + timeStyle: "short", |
| 196 | +}).format(Date.now()); |
| 197 | +// "2:45 PM" |
| 198 | + |
| 199 | +// medium |
| 200 | +new Intl.DateTimeFormat("en", { |
| 201 | + timeStyle: "medium", |
| 202 | +}).format(Date.now()); |
| 203 | +// "2:45:53 PM" |
| 204 | + |
| 205 | +// long |
| 206 | +new Intl.DateTimeFormat("en", { |
| 207 | + timeStyle: "long", |
| 208 | +}).format(Date.now()); |
| 209 | +// "2:46:05 PM GMT+7" |
| 210 | +``` |
| 211 | +
|
| 212 | +Now let's try with `dateStyle`: |
| 213 | +
|
| 214 | +```js |
| 215 | +// short |
| 216 | +new Intl.DateTimeFormat("en", { |
| 217 | + dateStyle: "short", |
| 218 | +}).format(Date.now()); |
| 219 | +// "7/25/20" |
| 220 | + |
| 221 | +// medium |
| 222 | +new Intl.DateTimeFormat("en", { |
| 223 | + dateStyle: "medium", |
| 224 | +}).format(Date.now()); |
| 225 | +// "Jul 25, 2020" |
| 226 | + |
| 227 | +// long |
| 228 | +new Intl.DateTimeFormat("en", { |
| 229 | + dateStyle: "long", |
| 230 | +}).format(Date.now()); |
| 231 | +// "July 25, 2020" |
| 232 | +``` |
| 233 | +
|
| 234 | +You can pass whatever locale you want and you can also pass both `dateStyle` and `timeStyle` options at the same time, choosing between the three options of 'short', 'medium', and 'long' that best suit your needs. |
| 235 | +
|
| 236 | +[Read More](https://github.com/tc39/proposal-intl-datetime-style) |
0 commit comments