Add nullish coalescing to multiple articles, refactor operators, renumber the chapter
This commit is contained in:
parent
175aefa0b8
commit
8a13c992d6
54 changed files with 386 additions and 183 deletions
|
@ -19,8 +19,7 @@ For example:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
We will learn functions (a way to group commands) soon. Looking ahead, let's note that `"use strict"` can be put at the beginning of the function body instead of the whole script. Doing that enables strict mode in that function only. But usually, people use it for the whole script.
|
Quite soon we're going to learn functions (a way to group commands) soon, so let's note in advance that `"use strict"` can be put at the beginning of a function. Doing that enables strict mode in that function only. But usually people use it for the whole script.
|
||||||
|
|
||||||
|
|
||||||
````warn header="Ensure that \"use strict\" is at the top"
|
````warn header="Ensure that \"use strict\" is at the top"
|
||||||
Please make sure that `"use strict"` is at the top of your scripts, otherwise strict mode may not be enabled.
|
Please make sure that `"use strict"` is at the top of your scripts, otherwise strict mode may not be enabled.
|
||||||
|
@ -47,11 +46,13 @@ Once we enter strict mode, there's no going back.
|
||||||
|
|
||||||
## Browser console
|
## Browser console
|
||||||
|
|
||||||
For the future, when you use a browser console to test features, please note that it doesn't `use strict` by default.
|
When you use a [developer console](info:devtools) to run code, please note that it doesn't `use strict` by default.
|
||||||
|
|
||||||
Sometimes, when `use strict` makes a difference, you'll get incorrect results.
|
Sometimes, when `use strict` makes a difference, you'll get incorrect results.
|
||||||
|
|
||||||
You can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
|
So, how to actually `use strict` in the console?
|
||||||
|
|
||||||
|
First, you can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
'use strict'; <Shift+Enter for a newline>
|
'use strict'; <Shift+Enter for a newline>
|
||||||
|
@ -61,25 +62,28 @@ You can try to press `key:Shift+Enter` to input multiple lines, and put `use str
|
||||||
|
|
||||||
It works in most browsers, namely Firefox and Chrome.
|
It works in most browsers, namely Firefox and Chrome.
|
||||||
|
|
||||||
If it doesn't, the most reliable way to ensure `use strict` would be to input the code into console like this:
|
If it doesn't, e.g. in an old browser, there's an ugly, but reliable way to ensure `use strict`. Put it inside this kind of wrapper:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// ...your code...
|
// ...your code here...
|
||||||
})()
|
})()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Always "use strict"
|
## Should we "use strict"?
|
||||||
|
|
||||||
We have yet to cover the differences between strict mode and the "default" mode.
|
The question may sound obvious, but it's not so.
|
||||||
|
|
||||||
In the next chapters, as we learn language features, we'll note the differences between the strict and default modes. Luckily, there aren't many and they actually make our lives better.
|
One could recommend to start scripts with `"use strict"`... But you know what's cool?
|
||||||
|
|
||||||
For now, it's enough to know about it in general:
|
Modern JavaScript supports "classes" and "modules" - advanced language structures (we'll surely get to them), that enable `use strict` automatically. So we don't need to add the `"use strict"` directive, if we use them.
|
||||||
|
|
||||||
1. The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some built-in features. We'll see the details later in the tutorial.
|
**So, for now `"use strict";` is a welcome guest at the top of your scripts. Later, when your code is all in classes and modules, you may omit it.**
|
||||||
2. Strict mode is enabled by placing `"use strict"` at the top of a script or function. Several language features, like "classes" and "modules", enable strict mode automatically.
|
|
||||||
3. Strict mode is supported by all modern browsers.
|
As of now, we've got to know about `use strict` in general.
|
||||||
4. We recommended always starting scripts with `"use strict"`. All examples in this tutorial assume strict mode unless (very rarely) specified otherwise.
|
|
||||||
|
In the next chapters, as we learn language features, we'll see the differences between the strict and old modes. Luckily, there aren't many and they actually make our lives better.
|
||||||
|
|
||||||
|
All examples in this tutorial assume strict mode unless (very rarely) specified otherwise.
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# Data types
|
# Data types
|
||||||
|
|
||||||
A variable in JavaScript can contain any data. A variable can at one moment be a string and at another be a number:
|
A value in JavaScript is always of a certain type. For example, a string or a number.
|
||||||
|
|
||||||
|
There are eight basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.
|
||||||
|
|
||||||
|
We can put any type in a variable. For exampple, a variable can at one moment be a string and then store a number:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// no error
|
// no error
|
||||||
|
@ -8,9 +12,7 @@ let message = "hello";
|
||||||
message = 123456;
|
message = 123456;
|
||||||
```
|
```
|
||||||
|
|
||||||
Programming languages that allow such things are called "dynamically typed", meaning that there are data types, but variables are not bound to any of them.
|
Programming languages that allow such things, such as JavaScript, are called "dynamically typed", meaning that there exist data types, but variables are not bound to any of them.
|
||||||
|
|
||||||
There are eight basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.
|
|
||||||
|
|
||||||
## Number
|
## Number
|
||||||
|
|
||||||
|
@ -64,18 +66,20 @@ We'll see more about working with numbers in the chapter <info:number>.
|
||||||
|
|
||||||
## BigInt
|
## BigInt
|
||||||
|
|
||||||
In JavaScript, the "number" type cannot represent integer values larger than <code>2<sup>53</sup></code> (or less than <code>-2<sup>53</sup></code> for negatives), that's a technical limitation caused by their internal representation. That's about 16 decimal digits, so for most purposes the limitation isn't a problem, but sometimes we need really big numbers, e.g. for cryptography or microsecond-precision timestamps.
|
In JavaScript, the "number" type cannot represent integer values larger than <code>(2<sup>53</sup>-1)</code> (that's `9007199254740991`), or less than <code>-(-2<sup>53</sup>-1)</code> for negatives. It's a technical limitation caused by their internal representation.
|
||||||
|
|
||||||
|
For most purposes that's quite enough, but sometimes we need really big numbers, e.g. for cryptography or microsecond-precision timestamps.
|
||||||
|
|
||||||
`BigInt` type was recently added to the language to represent integers of arbitrary length.
|
`BigInt` type was recently added to the language to represent integers of arbitrary length.
|
||||||
|
|
||||||
A `BigInt` is created by appending `n` to the end of an integer literal:
|
A `BigInt` value is created by appending `n` to the end of an integer:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// the "n" at the end means it's a BigInt
|
// the "n" at the end means it's a BigInt
|
||||||
const bigInt = 1234567890123456789012345678901234567890n;
|
const bigInt = 1234567890123456789012345678901234567890n;
|
||||||
```
|
```
|
||||||
|
|
||||||
As `BigInt` numbers are rarely needed, we devoted them a separate chapter <info:bigint>.
|
As `BigInt` numbers are rarely needed, we don't cover them here, but devoted them a separate chapter <info:bigint>. Read it when you need such big numbers.
|
||||||
|
|
||||||
```smart header="Compatability issues"
|
```smart header="Compatability issues"
|
||||||
Right now `BigInt` is supported in Firefox and Chrome, but not in Safari/IE/Edge.
|
Right now `BigInt` is supported in Firefox and Chrome, but not in Safari/IE/Edge.
|
||||||
|
@ -163,7 +167,7 @@ In JavaScript, `null` is not a "reference to a non-existing object" or a "null p
|
||||||
|
|
||||||
It's just a special value which represents "nothing", "empty" or "value unknown".
|
It's just a special value which represents "nothing", "empty" or "value unknown".
|
||||||
|
|
||||||
The code above states that `age` is unknown or empty for some reason.
|
The code above states that `age` is unknown.
|
||||||
|
|
||||||
## The "undefined" value
|
## The "undefined" value
|
||||||
|
|
||||||
|
@ -174,30 +178,33 @@ The meaning of `undefined` is "value is not assigned".
|
||||||
If a variable is declared, but not assigned, then its value is `undefined`:
|
If a variable is declared, but not assigned, then its value is `undefined`:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let x;
|
let age;
|
||||||
|
|
||||||
alert(x); // shows "undefined"
|
alert(age); // shows "undefined"
|
||||||
```
|
```
|
||||||
|
|
||||||
Technically, it is possible to assign `undefined` to any variable:
|
Technically, it is possible to explicitly assign `undefined` to a variable:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let x = 123;
|
let age = 100;
|
||||||
|
|
||||||
x = undefined;
|
// change the value to undefined
|
||||||
|
age = undefined;
|
||||||
|
|
||||||
alert(x); // "undefined"
|
alert(age); // "undefined"
|
||||||
```
|
```
|
||||||
|
|
||||||
...But we don't recommend doing that. Normally, we use `null` to assign an "empty" or "unknown" value to a variable, and we use `undefined` for checks like seeing if a variable has been assigned.
|
...But we don't recommend doing that. Normally, one uses `null` to assign an "empty" or "unknown" value to a variable, while `undefined` is reserved as a default initial value for unassigned things.
|
||||||
|
|
||||||
## Objects and Symbols
|
## Objects and Symbols
|
||||||
|
|
||||||
The `object` type is special.
|
The `object` type is special.
|
||||||
|
|
||||||
All other types are called "primitive" because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities. We'll deal with them later in the chapter <info:object> after we learn more about primitives.
|
All other types are called "primitive" because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities.
|
||||||
|
|
||||||
The `symbol` type is used to create unique identifiers for objects. We mention it here for completeness, but we'll study it after objects.
|
Being that important, objects deserve a special treatment. We'll deal with them later in the chapter <info:object>, after we learn more about primitives.
|
||||||
|
|
||||||
|
The `symbol` type is used to create unique identifiers for objects. We have to mention it here for the sake of completeness, but also postpone the details till we know objects.
|
||||||
|
|
||||||
## The typeof operator [#type-typeof]
|
## The typeof operator [#type-typeof]
|
||||||
|
|
||||||
|
@ -241,8 +248,8 @@ typeof alert // "function" (3)
|
||||||
The last three lines may need additional explanation:
|
The last three lines may need additional explanation:
|
||||||
|
|
||||||
1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter <info:number>. Here, it serves just as an example of an object.
|
1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter <info:number>. Here, it serves just as an example of an object.
|
||||||
2. The result of `typeof null` is `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, this is an error in the language.
|
2. The result of `typeof null` is `"object"`. That's an officially recognized error in `typeof` behavior, coming from the early days of JavaScript and kept for compatibility. Definitely, `null` is not an object. It is a special value with a separate type of its own.
|
||||||
3. The result of `typeof alert` is `"function"`, because `alert` is a function. We'll study functions in the next chapters where we'll also see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently, returning `"function"`. That's not quite correct, but very convenient in practice.
|
3. The result of `typeof alert` is `"function"`, because `alert` is a function. We'll study functions in the next chapters where we'll also see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently, returning `"function"`. That also comes from the early days of JavaScript. Technically, such behavior isn't correct, but can be convenient in practice.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,10 @@
|
||||||
# Interaction: alert, prompt, confirm
|
# Interaction: alert, prompt, confirm
|
||||||
|
|
||||||
In this part of the tutorial we cover JavaScript language "as is", without environment-specific tweaks.
|
As we'll be using the browser as our demo environment, let's see a couple of functions to interact with the user: `alert`, `prompt` and `confirm`.
|
||||||
|
|
||||||
But we'll still be using the browser as our demo environment, so we should know at least a few of its user-interface functions. In this chapter, we'll get familiar with the browser functions `alert`, `prompt` and `confirm`.
|
|
||||||
|
|
||||||
## alert
|
## alert
|
||||||
|
|
||||||
Syntax:
|
This one we've seen already. It shows shows a message and waits for the user to presses "OK".
|
||||||
|
|
||||||
```js
|
|
||||||
alert(message);
|
|
||||||
```
|
|
||||||
|
|
||||||
This shows a message and pauses script execution until the user presses "OK".
|
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -20,7 +12,7 @@ For example:
|
||||||
alert("Hello");
|
alert("Hello");
|
||||||
```
|
```
|
||||||
|
|
||||||
The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons, etc. until they have dealt with the window. In this case -- until they press "OK".
|
The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons, etc, until they have dealt with the window. In this case -- until they press "OK".
|
||||||
|
|
||||||
## prompt
|
## prompt
|
||||||
|
|
||||||
|
@ -38,7 +30,11 @@ It shows a modal window with a text message, an input field for the visitor, and
|
||||||
`default`
|
`default`
|
||||||
: An optional second parameter, the initial value for the input field.
|
: An optional second parameter, the initial value for the input field.
|
||||||
|
|
||||||
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing Cancel or hitting the `key:Esc` key.
|
```smart header="The square brackets in syntax `[...]`"
|
||||||
|
The square brackets around `default` in the syntax above denote that the parameter as optional, not required.
|
||||||
|
```
|
||||||
|
|
||||||
|
The visitor can type something in the prompt input field and press OK. Then we get that text in the `result`. Or they can cancel the input by pressing Cancel or hitting the `key:Esc` key, then we get `null` as the `result`.
|
||||||
|
|
||||||
The call to `prompt` returns the text from the input field or `null` if the input was canceled.
|
The call to `prompt` returns the text from the input field or `null` if the input was canceled.
|
||||||
|
|
|
@ -7,7 +7,9 @@ For example, `alert` automatically converts any value to a string to show it. Ma
|
||||||
There are also cases when we need to explicitly convert a value to the expected type.
|
There are also cases when we need to explicitly convert a value to the expected type.
|
||||||
|
|
||||||
```smart header="Not talking about objects yet"
|
```smart header="Not talking about objects yet"
|
||||||
In this chapter, we won't cover objects. Instead, we'll study primitives first. Later, after we learn about objects, we'll see how object conversion works in the chapter <info:object-toprimitive>.
|
In this chapter, we won't cover objects. We'll be talking about primitives just yet.
|
||||||
|
|
||||||
|
Later, after we learn about objects, in the chapter <info:object-toprimitive> we'll see how objects fit in.
|
||||||
```
|
```
|
||||||
|
|
||||||
## String Conversion
|
## String Conversion
|
32
1-js/02-first-steps/08-operators/4-fix-prompt/solution.md
Normal file
32
1-js/02-first-steps/08-operators/4-fix-prompt/solution.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
The reason is that prompt returns user input as a string.
|
||||||
|
|
||||||
|
So variables have values `"1"` and `"2"` respectively.
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let a = "1"; // prompt("First number?", 1);
|
||||||
|
let b = "2"; // prompt("Second number?", 2);
|
||||||
|
|
||||||
|
alert(a + b); // 12
|
||||||
|
```
|
||||||
|
|
||||||
|
What we should to is to convert strings to numbers before `+`. For example, using `Number()` or prepending them with `+`.
|
||||||
|
|
||||||
|
For example, right before `prompt`:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let a = +prompt("First number?", 1);
|
||||||
|
let b = +prompt("Second number?", 2);
|
||||||
|
|
||||||
|
alert(a + b); // 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Or in the `alert`:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let a = prompt("First number?", 1);
|
||||||
|
let b = prompt("Second number?", 2);
|
||||||
|
|
||||||
|
alert(+a + +b); // 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Using both unary and binary `+` in the latest code. Looks funny, doesn't it?
|
18
1-js/02-first-steps/08-operators/4-fix-prompt/task.md
Normal file
18
1-js/02-first-steps/08-operators/4-fix-prompt/task.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
importance: 5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Fix the addition
|
||||||
|
|
||||||
|
Here's a code that asks the user for two numbers and shows their sum.
|
||||||
|
|
||||||
|
It works incorrectly. The output in the example below is `12` (for default prompt values).
|
||||||
|
|
||||||
|
Why? Fix it. The result should be `3`.
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let a = prompt("First number?", 1);
|
||||||
|
let b = prompt("Second number?", 2);
|
||||||
|
|
||||||
|
alert(a + b); // 12
|
||||||
|
```
|
|
@ -1,8 +1,8 @@
|
||||||
# Operators
|
# Basic operators, maths
|
||||||
|
|
||||||
We know many operators from school. They are things like addition `+`, multiplication `*`, subtraction `-`, and so on.
|
We know many operators from school. They are things like addition `+`, multiplication `*`, subtraction `-`, and so on.
|
||||||
|
|
||||||
In this chapter, we'll concentrate on aspects of operators that are not covered by school arithmetic.
|
In this chapter, we’ll start with simple operators, then concentrate on JavaScript-specific aspects, not covered by school arithmetic.
|
||||||
|
|
||||||
## Terms: "unary", "binary", "operand"
|
## Terms: "unary", "binary", "operand"
|
||||||
|
|
||||||
|
@ -28,9 +28,55 @@ Before we move on, let's grasp some common terminology.
|
||||||
|
|
||||||
Formally, in the examples above we have two different operators that share the same symbol: the negation operator, a unary operator that reverses the sign, and the subtraction operator, a binary operator that subtracts one number from another.
|
Formally, in the examples above we have two different operators that share the same symbol: the negation operator, a unary operator that reverses the sign, and the subtraction operator, a binary operator that subtracts one number from another.
|
||||||
|
|
||||||
## String concatenation, binary +
|
## Maths
|
||||||
|
|
||||||
Now, let's see special features of JavaScript operators that are beyond school arithmetics.
|
The following math operations are supported:
|
||||||
|
|
||||||
|
- Addition `+`,
|
||||||
|
- Subtraction `-`,
|
||||||
|
- Multiplication `*`,
|
||||||
|
- Division `/`,
|
||||||
|
- Remainder `%`,
|
||||||
|
- Exponentiation `**`.
|
||||||
|
|
||||||
|
The first four are straightforward, while `%` and `**` need a few words about them.
|
||||||
|
|
||||||
|
### Remainder %
|
||||||
|
|
||||||
|
The remainder operator `%`, despite its appearance, is not related to percents.
|
||||||
|
|
||||||
|
The result of `a % b` is the [remainder](https://en.wikipedia.org/wiki/Remainder) of the integer division of `a` by `b`.
|
||||||
|
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
alert( 5 % 2 ); // 1, a remainder of 5 divided by 2
|
||||||
|
alert( 8 % 3 ); // 2, a remainder of 8 divided by 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exponentiation **
|
||||||
|
|
||||||
|
The exponentiation operator `a ** b` multiplies `a` by itself `b` times.
|
||||||
|
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
alert( 2 ** 2 ); // 4 (2 multiplied by itself 2 times)
|
||||||
|
alert( 2 ** 3 ); // 8 (2 * 2 * 2, 3 times)
|
||||||
|
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2, 4 times)
|
||||||
|
```
|
||||||
|
|
||||||
|
Mathematically, the exponentiation is defined for non-integer numbers as well. For example, a square root is an exponentiation by `1/2`:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root)
|
||||||
|
alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## String concatenation with binary +
|
||||||
|
|
||||||
|
Let's meet features of JavaScript operators that are beyond school arithmetics.
|
||||||
|
|
||||||
Usually, the plus operator `+` sums numbers.
|
Usually, the plus operator `+` sums numbers.
|
||||||
|
|
||||||
|
@ -41,7 +87,7 @@ let s = "my" + "string";
|
||||||
alert(s); // mystring
|
alert(s); // mystring
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that if one of the operands is a string, the other one is converted to a string too.
|
Note that if any of the operands is a string, then the other one is converted to a string too.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -50,22 +96,23 @@ alert( '1' + 2 ); // "12"
|
||||||
alert( 2 + '1' ); // "21"
|
alert( 2 + '1' ); // "21"
|
||||||
```
|
```
|
||||||
|
|
||||||
See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, the other one is converted into a string as well.
|
See, it doesn't matter whether the first operand is a string or the second one.
|
||||||
|
|
||||||
However, note that operations run from left to right. If there are two numbers followed by a string, the numbers will be added before being converted to a string:
|
|
||||||
|
|
||||||
|
Here's a more complex example:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
alert(2 + 2 + '1' ); // "41" and not "221"
|
alert(2 + 2 + '1' ); // "41" and not "221"
|
||||||
```
|
```
|
||||||
|
|
||||||
String concatenation and conversion is a special feature of the binary plus `+`. Other arithmetic operators work only with numbers and always convert their operands to numbers.
|
Here, operators work one after another. The first `+` sums two numbers, so it returns `4`, then the next `+` adds the string `1` to it, so it's like `4 + '1' = 41`.
|
||||||
|
|
||||||
For instance, subtraction and division:
|
The binary `+` is the only operator that supports strings in such a way. Other arithmetic operators work only with numbers and always convert their operands to numbers.
|
||||||
|
|
||||||
|
Here's the demo for subtraction and division:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
alert( 2 - '1' ); // 1
|
alert( 6 - '2' ); // 4, converts '2' to a number
|
||||||
alert( '6' / '2' ); // 3
|
alert( '6' / '2' ); // 3, converts both operands to numbers
|
||||||
```
|
```
|
||||||
|
|
||||||
## Numeric conversion, unary +
|
## Numeric conversion, unary +
|
||||||
|
@ -140,6 +187,7 @@ Here's an extract from the [precedence table](https://developer.mozilla.org/en/J
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 17 | unary plus | `+` |
|
| 17 | unary plus | `+` |
|
||||||
| 17 | unary negation | `-` |
|
| 17 | unary negation | `-` |
|
||||||
|
| 16 | exponentiation | `**` |
|
||||||
| 15 | multiplication | `*` |
|
| 15 | multiplication | `*` |
|
||||||
| 15 | division | `/` |
|
| 15 | division | `/` |
|
||||||
| 13 | addition | `+` |
|
| 13 | addition | `+` |
|
||||||
|
@ -162,24 +210,11 @@ let x = 2 * 2 + 1;
|
||||||
alert( x ); // 5
|
alert( x ); // 5
|
||||||
```
|
```
|
||||||
|
|
||||||
It is possible to chain assignments:
|
### Assignment = returns a value
|
||||||
|
|
||||||
```js run
|
The fact of `=` being an operator, not a "magical" language construct has an interesting implication.
|
||||||
let a, b, c;
|
|
||||||
|
|
||||||
*!*
|
Most operators in JavaScript return a value. That's obvious for `+` and `-`, but also true for `=`.
|
||||||
a = b = c = 2 + 2;
|
|
||||||
*/!*
|
|
||||||
|
|
||||||
alert( a ); // 4
|
|
||||||
alert( b ); // 4
|
|
||||||
alert( c ); // 4
|
|
||||||
```
|
|
||||||
|
|
||||||
Chained assignments evaluate from right to left. First, the rightmost expression `2 + 2` is evaluated and then assigned to the variables on the left: `c`, `b` and `a`. At the end, all the variables share a single value.
|
|
||||||
|
|
||||||
````smart header="The assignment operator `\"=\"` returns a value"
|
|
||||||
An operator always returns a value. That's obvious for most of them like addition `+` or multiplication `*`. But the assignment operator follows this rule too.
|
|
||||||
|
|
||||||
The call `x = value` writes the `value` into `x` *and then returns it*.
|
The call `x = value` writes the `value` into `x` *and then returns it*.
|
||||||
|
|
||||||
|
@ -199,49 +234,74 @@ alert( c ); // 0
|
||||||
|
|
||||||
In the example above, the result of expression `(a = b + 1)` is the value which was assigned to `a` (that is `3`). It is then used for further evaluations.
|
In the example above, the result of expression `(a = b + 1)` is the value which was assigned to `a` (that is `3`). It is then used for further evaluations.
|
||||||
|
|
||||||
Funny code, isn't it? We should understand how it works, because sometimes we see it in JavaScript libraries, but shouldn't write anything like that ourselves. Such tricks definitely don't make code clearer or readable.
|
Funny code, isn't it? We should understand how it works, because sometimes we see it in JavaScript libraries.
|
||||||
````
|
|
||||||
|
|
||||||
## Remainder %
|
Although, please don't write the code like that. Such tricks definitely don't make code clearer or readable.
|
||||||
|
|
||||||
The remainder operator `%`, despite its appearance, is not related to percents.
|
### Chaining assignments
|
||||||
|
|
||||||
The result of `a % b` is the remainder of the integer division of `a` by `b`.
|
Another interesting feature is the ability to chain assignments:
|
||||||
|
|
||||||
For instance:
|
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
alert( 5 % 2 ); // 1 is a remainder of 5 divided by 2
|
let a, b, c;
|
||||||
alert( 8 % 3 ); // 2 is a remainder of 8 divided by 3
|
|
||||||
alert( 6 % 3 ); // 0 is a remainder of 6 divided by 3
|
*!*
|
||||||
|
a = b = c = 2 + 2;
|
||||||
|
*/!*
|
||||||
|
|
||||||
|
alert( a ); // 4
|
||||||
|
alert( b ); // 4
|
||||||
|
alert( c ); // 4
|
||||||
```
|
```
|
||||||
|
|
||||||
## Exponentiation **
|
Chained assignments evaluate from right to left. First, the rightmost expression `2 + 2` is evaluated and then assigned to the variables on the left: `c`, `b` and `a`. At the end, all the variables share a single value.
|
||||||
|
|
||||||
The exponentiation operator `**` is a recent addition to the language.
|
Once again, for the purposes of readability it's better to split such code into few lines:
|
||||||
|
|
||||||
For a natural number `b`, the result of `a ** b` is `a` multiplied by itself `b` times.
|
```js
|
||||||
|
c = 2 + 2;
|
||||||
|
b = c;
|
||||||
|
a = c;
|
||||||
|
```
|
||||||
|
That's easier to read, especially when eye-scanning the code fast.
|
||||||
|
|
||||||
For instance:
|
## Modify-in-place
|
||||||
|
|
||||||
```js run
|
We often need to apply an operator to a variable and store the new result in that same variable.
|
||||||
alert( 2 ** 2 ); // 4 (2 * 2)
|
|
||||||
alert( 2 ** 3 ); // 8 (2 * 2 * 2)
|
For example:
|
||||||
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)
|
|
||||||
|
```js
|
||||||
|
let n = 2;
|
||||||
|
n = n + 5;
|
||||||
|
n = n * 2;
|
||||||
```
|
```
|
||||||
|
|
||||||
The operator works for non-integer numbers as well.
|
This notation can be shortened using the operators `+=` and `*=`:
|
||||||
|
|
||||||
For instance:
|
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root, that's maths)
|
let n = 2;
|
||||||
alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)
|
n += 5; // now n = 7 (same as n = n + 5)
|
||||||
|
n *= 2; // now n = 14 (same as n = n * 2)
|
||||||
|
|
||||||
|
alert( n ); // 14
|
||||||
|
```
|
||||||
|
|
||||||
|
Short "modify-and-assign" operators exist for all arithmetical and bitwise operators: `/=`, `-=`, etc.
|
||||||
|
|
||||||
|
Such operators have the same precedence as a normal assignment, so they run after most other calculations:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let n = 2;
|
||||||
|
|
||||||
|
n *= 3 + 5;
|
||||||
|
|
||||||
|
alert( n ); // 16 (right part evaluated first, same as n *= 8)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Increment/decrement
|
## Increment/decrement
|
||||||
|
|
||||||
<!-- Can't use -- in title, because built-in parse turns it into – -->
|
<!-- Can't use -- in title, because the built-in parser turns it into a 'long dash' – -->
|
||||||
|
|
||||||
Increasing or decreasing a number by one is among the most common numerical operations.
|
Increasing or decreasing a number by one is among the most common numerical operations.
|
||||||
|
|
||||||
|
@ -368,41 +428,7 @@ The list of operators:
|
||||||
- RIGHT SHIFT ( `>>` )
|
- RIGHT SHIFT ( `>>` )
|
||||||
- ZERO-FILL RIGHT SHIFT ( `>>>` )
|
- ZERO-FILL RIGHT SHIFT ( `>>>` )
|
||||||
|
|
||||||
These operators are used very rarely, when we need to fiddle with numebers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) article on MDN when a need arises.
|
These operators are used very rarely, when we need to fiddle with numebers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) article on MDN when a need arises.
|
||||||
|
|
||||||
## Modify-in-place
|
|
||||||
|
|
||||||
We often need to apply an operator to a variable and store the new result in that same variable.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
let n = 2;
|
|
||||||
n = n + 5;
|
|
||||||
n = n * 2;
|
|
||||||
```
|
|
||||||
|
|
||||||
This notation can be shortened using the operators `+=` and `*=`:
|
|
||||||
|
|
||||||
```js run
|
|
||||||
let n = 2;
|
|
||||||
n += 5; // now n = 7 (same as n = n + 5)
|
|
||||||
n *= 2; // now n = 14 (same as n = n * 2)
|
|
||||||
|
|
||||||
alert( n ); // 14
|
|
||||||
```
|
|
||||||
|
|
||||||
Short "modify-and-assign" operators exist for all arithmetical and bitwise operators: `/=`, `-=`, etc.
|
|
||||||
|
|
||||||
Such operators have the same precedence as a normal assignment, so they run after most other calculations:
|
|
||||||
|
|
||||||
```js run
|
|
||||||
let n = 2;
|
|
||||||
|
|
||||||
n *= 3 + 5;
|
|
||||||
|
|
||||||
alert( n ); // 16 (right part evaluated first, same as n *= 8)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Comma
|
## Comma
|
||||||
|
|
|
@ -90,10 +90,10 @@ For instance:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
alert( 1 || 0 ); // 1 (1 is truthy)
|
alert( 1 || 0 ); // 1 (1 is truthy)
|
||||||
alert( true || 'no matter what' ); // (true is truthy)
|
|
||||||
|
|
||||||
alert( null || 1 ); // 1 (1 is the first truthy value)
|
alert( null || 1 ); // 1 (1 is the first truthy value)
|
||||||
alert( null || 0 || 1 ); // 1 (the first truthy value)
|
alert( null || 0 || 1 ); // 1 (the first truthy value)
|
||||||
|
|
||||||
alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
|
alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -101,53 +101,40 @@ This leads to some interesting usage compared to a "pure, classical, boolean-onl
|
||||||
|
|
||||||
1. **Getting the first truthy value from a list of variables or expressions.**
|
1. **Getting the first truthy value from a list of variables or expressions.**
|
||||||
|
|
||||||
Imagine we have a list of variables which can either contain data or be `null/undefined`. How can we find the first one with data?
|
For instance, we have `firstName`, `lastName` and `nickName` variables, all optional.
|
||||||
|
|
||||||
We can use OR `||`:
|
Let's use OR `||` to choose the one that has the data and show it (or `anonymous` if nothing set):
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let currentUser = null;
|
let firstName = "";
|
||||||
let defaultUser = "John";
|
let lastName = "";
|
||||||
|
let nickName = "SuperCoder";
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
let name = currentUser || defaultUser || "unnamed";
|
alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert( name ); // selects "John" – the first truthy value
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If both `currentUser` and `defaultUser` were falsy, `"unnamed"` would be the result.
|
If all variables were falsy, `Anonymous` would show up.
|
||||||
|
|
||||||
2. **Short-circuit evaluation.**
|
2. **Short-circuit evaluation.**
|
||||||
|
|
||||||
Operands can be not only values, but arbitrary expressions. OR evaluates and tests them from left to right. The evaluation stops when a truthy value is reached, and the value is returned. This process is called "a short-circuit evaluation" because it goes as short as possible from left to right.
|
Another feature of OR `||` operator is the so-called "short-circuit" evaluation.
|
||||||
|
|
||||||
This is clearly seen when the expression given as the second argument has a side effect like a variable assignment.
|
It means that `||` processes its arguments until the first truthy value is reached, and then the value is returned immediately, without even touching the other argument.
|
||||||
|
|
||||||
In the example below, `x` does not get assigned:
|
That importance of this feature becomes obvious if an operand isn't just a value, but an expression with a side effect, such as a variable assignment or a function call.
|
||||||
|
|
||||||
|
In the example below, the first message is printed, while the second is not:
|
||||||
|
|
||||||
```js run no-beautify
|
```js run no-beautify
|
||||||
let x;
|
*!*true*/!* || alert("printed");
|
||||||
|
*!*false*/!* || alert("not printed");
|
||||||
*!*true*/!* || (x = 1);
|
|
||||||
|
|
||||||
alert(x); // undefined, because (x = 1) not evaluated
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If, instead, the first argument is `false`, `||` evaluates the second one, thus running the assignment:
|
In the first line, the OR `||` operator stops the evaluation immediately upon seeing `true`, so the `alert` isn't run.
|
||||||
|
|
||||||
```js run no-beautify
|
Sometimes, people use this feature to execute commands only if the condition on the left part is truthy.
|
||||||
let x;
|
|
||||||
|
|
||||||
*!*false*/!* || (x = 1);
|
|
||||||
|
|
||||||
alert(x); // 1
|
|
||||||
```
|
|
||||||
|
|
||||||
An assignment is a simple case. There may be side effects, that won't show up if the evaluation doesn't reach them.
|
|
||||||
|
|
||||||
As we can see, such a use case is a "shorter way of doing `if`". The first operand is converted to boolean. If it's false, the second one is evaluated.
|
|
||||||
|
|
||||||
Most of time, it's better to use a "regular" `if` to keep the code easy to understand, but sometimes this can be handy.
|
|
||||||
|
|
||||||
## && (AND)
|
## && (AND)
|
||||||
|
|
||||||
|
@ -236,7 +223,8 @@ The precedence of AND `&&` operator is higher than OR `||`.
|
||||||
So the code `a && b || c && d` is essentially the same as if the `&&` expressions were in parentheses: `(a && b) || (c && d)`.
|
So the code `a && b || c && d` is essentially the same as if the `&&` expressions were in parentheses: `(a && b) || (c && d)`.
|
||||||
````
|
````
|
||||||
|
|
||||||
Just like OR, the AND `&&` operator can sometimes replace `if`.
|
````warn header="Don't replace `if` with || or &&"
|
||||||
|
Sometimes, people use the AND `&&` operator as a "shorter to write `if`".
|
||||||
|
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
|
@ -253,14 +241,12 @@ So we basically have an analogue for:
|
||||||
```js run
|
```js run
|
||||||
let x = 1;
|
let x = 1;
|
||||||
|
|
||||||
if (x > 0) {
|
if (x > 0) alert( 'Greater than zero!' );
|
||||||
alert( 'Greater than zero!' );
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The variant with `&&` appears shorter. But `if` is more obvious and tends to be a little bit more readable.
|
Although, the variant with `&&` appears shorter, `if` is more obvious and tends to be a little bit more readable. So we recommend using every construct for its purpose: use `if` if we want if and use `&&` if we want AND.
|
||||||
|
````
|
||||||
|
|
||||||
So we recommend using every construct for its purpose: use `if` if we want if and use `&&` if we want AND.
|
|
||||||
|
|
||||||
## ! (NOT)
|
## ! (NOT)
|
||||||
|
|
||||||
|
|
117
1-js/02-first-steps/12-nullish-coalescing-operator/article.md
Normal file
117
1-js/02-first-steps/12-nullish-coalescing-operator/article.md
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
# Nullish coalescing operator '??'
|
||||||
|
|
||||||
|
[recent browser="new"]
|
||||||
|
|
||||||
|
The nullish coalescing operator `??` provides a short syntax for selecting a first "defined" variable from the list.
|
||||||
|
|
||||||
|
The result of `a ?? b` is:
|
||||||
|
- `a` if it's not `null` or `undefined`,
|
||||||
|
- `b`, otherwise.
|
||||||
|
|
||||||
|
So, `x = a ?? b` is a short equivalent to:
|
||||||
|
|
||||||
|
```js
|
||||||
|
x = (a !== null && a !== undefined) ? a : b;
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's a longer example.
|
||||||
|
|
||||||
|
Let's say, we have a `firstName`, `lastName` or `nickName`, all of them optional.
|
||||||
|
|
||||||
|
Let's choose the defined one and show it (or "Anonymous" if nothing is set):
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let firstName = null;
|
||||||
|
let lastName = null;
|
||||||
|
let nickName = "Supercoder";
|
||||||
|
|
||||||
|
// show the first not-null/undefined variable
|
||||||
|
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparison with ||
|
||||||
|
|
||||||
|
That's very similar to OR `||` operator. Actually, we can replace `??` with `||` in the code above and get the same result.
|
||||||
|
|
||||||
|
The important difference is that:
|
||||||
|
- `||` returns the first *truthy* value.
|
||||||
|
- `??` returns the first *defined* value.
|
||||||
|
|
||||||
|
This matters a lot when we'd like to treat `null/undefined` differently from `0`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
height = height ?? 100;
|
||||||
|
```
|
||||||
|
|
||||||
|
This sets `height` to `100` if it's not defined. But if `height` is `0`, then it remains "as is".
|
||||||
|
|
||||||
|
Let's compare it with `||`:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let height = 0;
|
||||||
|
|
||||||
|
alert(height || 100); // 100
|
||||||
|
alert(height ?? 100); // 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, `height || 100` treats zero height as unset, same as `null`, `undefined` or any other falsy value, depeding on use cases that may be incorrect.
|
||||||
|
|
||||||
|
The `height ?? 100` returns `100` only if `height` is exactly `null` or `undefined`.
|
||||||
|
|
||||||
|
## Precedence
|
||||||
|
|
||||||
|
The precedence of the `??` operator is rather low: `7` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table).
|
||||||
|
|
||||||
|
That's lower than most operators and a bit higher than `=` and `?`.
|
||||||
|
|
||||||
|
So if we need to use `??` in a complex expression, then consider adding parentheses:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let height = null;
|
||||||
|
let width = null;
|
||||||
|
|
||||||
|
// important: use parentheses
|
||||||
|
let area = (height ?? 100) * (width ?? 50);
|
||||||
|
|
||||||
|
alert(area); // 5000
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise, if we omit parentheses, then `*` has the higher precedence and would run first. That would be the same as:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// not correct
|
||||||
|
let area = height ?? (100 * width) ?? 50;
|
||||||
|
```
|
||||||
|
|
||||||
|
There's also a related language-level limitation. Due to safety reasons, it's forbidden to use `??` together with `&&` and `||` operators.
|
||||||
|
|
||||||
|
The code below triggers a syntax error:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let x = 1 && 2 ?? 3; // Syntax error
|
||||||
|
```
|
||||||
|
|
||||||
|
The limitation is surely debatable, but somewhy was added to the language specification.
|
||||||
|
|
||||||
|
Use explicit parentheses to fix it:
|
||||||
|
|
||||||
|
```js run
|
||||||
|
let x = (1 && 2) ?? 3; // Works
|
||||||
|
alert(x); // 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- The nullish coalescing operator `??` provides a short way to choose a "defined" value from the list.
|
||||||
|
|
||||||
|
It's used to assign default values to variables:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// set height=100, if height is null or undefined
|
||||||
|
height = height ?? 100;
|
||||||
|
```
|
||||||
|
|
||||||
|
- The operator `??` has a very low precedence, a bit higher than `?` and `=`.
|
||||||
|
- It's forbidden to use it with `||` or `&&` without explicit parentheses.
|
|
@ -214,36 +214,48 @@ In JavaScript, a default parameter is evaluated every time the function is calle
|
||||||
In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter.
|
In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter.
|
||||||
```
|
```
|
||||||
|
|
||||||
````smart header="Default parameters old-style"
|
### Alternative default parameters
|
||||||
Old editions of JavaScript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts.
|
|
||||||
|
|
||||||
For instance, an explicit check for being `undefined`:
|
Sometimes it makes sense to set default values for parameters not in the function declaration, but at a later stage, during its execution.
|
||||||
|
|
||||||
```js
|
To check for an omitted parameter, we can compare it with `undefined`:
|
||||||
function showMessage(from, text) {
|
|
||||||
|
```js run
|
||||||
|
function showMessage(text) {
|
||||||
*!*
|
*!*
|
||||||
if (text === undefined) {
|
if (text === undefined) {
|
||||||
text = 'no text given';
|
text = 'empty message';
|
||||||
}
|
}
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert( from + ": " + text );
|
alert(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showMessage(); // empty message
|
||||||
```
|
```
|
||||||
|
|
||||||
...Or the `||` operator:
|
...Or we could use the `||` operator:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function showMessage(from, text) {
|
// if text parameter is omitted or "" is passed, set it to 'empty'
|
||||||
// if text is falsy then text gets the "default" value
|
function showMessage(text) {
|
||||||
text = text || 'no text given';
|
text = text || 'empty';
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Modern JavaScript engines support the [nullish coalescing operator](info:nullish-coalescing-operator) `??`, it's better when falsy values, such as `0`, are considered regular:
|
||||||
|
|
||||||
````
|
```js run
|
||||||
|
// if there's no "count" parameter, show "unknown"
|
||||||
|
function showCount(count) {
|
||||||
|
alert(count ?? "unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
showCount(0); // 0
|
||||||
|
showCount(null); // unknown
|
||||||
|
showCount(); // unknown
|
||||||
|
```
|
||||||
|
|
||||||
## Returning a value
|
## Returning a value
|
||||||
|
|
|
@ -152,6 +152,9 @@ Conditional
|
||||||
Logical operators
|
Logical operators
|
||||||
: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped (not necessary `true`/`false`). Logical NOT `!` converts the operand to boolean type and returns the inverse value.
|
: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped (not necessary `true`/`false`). Logical NOT `!` converts the operand to boolean type and returns the inverse value.
|
||||||
|
|
||||||
|
Nullish coalescing operator
|
||||||
|
: The `??` operator provides a way to choose a defined value from a list of variables. The result of `a ?? b` is `a` unless it's `null/undefined`, then `b`.
|
||||||
|
|
||||||
Comparisons
|
Comparisons
|
||||||
: Equality check `==` for values of different types converts them to a number (except `null` and `undefined` that equal each other and nothing else), so these are equal:
|
: Equality check `==` for values of different types converts them to a number (except `null` and `undefined` that equal each other and nothing else), so these are equal:
|
||||||
|
|
||||||
|
@ -171,7 +174,7 @@ Comparisons
|
||||||
Other operators
|
Other operators
|
||||||
: There are few others, like a comma operator.
|
: There are few others, like a comma operator.
|
||||||
|
|
||||||
More in: <info:operators>, <info:comparison>, <info:logical-operators>.
|
More in: <info:operators>, <info:comparison>, <info:logical-operators>, <info:nullish-coalescing-operator>.
|
||||||
|
|
||||||
## Loops
|
## Loops
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue