From 8a13c992d62548a18d2ec49731d591dcfa7387e0 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Sat, 2 May 2020 17:37:12 +0300 Subject: [PATCH] Add nullish coalescing to multiple articles, refactor operators, renumber the chapter --- 1-js/02-first-steps/03-strict-mode/article.md | 32 +-- 1-js/02-first-steps/05-types/article.md | 45 ++-- .../1-simple-page/solution.md | 0 .../1-simple-page/task.md | 0 .../article.md | 20 +- .../article.md | 4 +- .../1-increment-order/solution.md | 0 .../1-increment-order/task.md | 0 .../2-assignment-result/solution.md | 0 .../2-assignment-result/task.md | 0 .../solution.md | 0 .../3-primitive-conversions-questions/task.md | 0 .../08-operators/4-fix-prompt/solution.md | 32 +++ .../08-operators/4-fix-prompt/task.md | 18 ++ .../{07-operators => 08-operators}/article.md | 200 ++++++++++-------- .../1-comparison-questions/solution.md | 0 .../1-comparison-questions/task.md | 0 .../article.md | 0 .../11-logical-operators/article.md | 60 ++---- .../12-nullish-coalescing-operator/article.md | 117 ++++++++++ .../1-loop-last-value/solution.md | 0 .../1-loop-last-value/task.md | 0 .../2-which-value-while/solution.md | 0 .../2-which-value-while/task.md | 0 .../3-which-value-for/solution.md | 0 .../3-which-value-for/task.md | 0 .../4-for-even/solution.md | 0 .../4-for-even/task.md | 0 .../5-replace-for-while/solution.md | 0 .../5-replace-for-while/task.md | 0 .../6-repeat-until-correct/solution.md | 0 .../6-repeat-until-correct/task.md | 0 .../7-list-primes/solution.md | 0 .../7-list-primes/task.md | 0 .../{12-while-for => 13-while-for}/article.md | 0 .../1-rewrite-switch-if-else/solution.md | 0 .../1-rewrite-switch-if-else/task.md | 0 .../2-rewrite-if-switch/solution.md | 0 .../2-rewrite-if-switch/task.md | 0 .../{13-switch => 14-switch}/article.md | 0 .../1-if-else-required/solution.md | 0 .../1-if-else-required/task.md | 0 .../solution.md | 0 .../2-rewrite-function-question-or/task.md | 0 .../3-min/solution.md | 0 .../3-min/task.md | 0 .../4-pow/solution.md | 0 .../4-pow/task.md | 0 .../article.md | 36 ++-- .../article.md | 0 .../1-rewrite-arrow/solution.md | 0 .../1-rewrite-arrow/task.md | 0 .../article.md | 0 .../article.md | 5 +- 54 files changed, 386 insertions(+), 183 deletions(-) rename 1-js/02-first-steps/{09-alert-prompt-confirm => 06-alert-prompt-confirm}/1-simple-page/solution.md (100%) rename 1-js/02-first-steps/{09-alert-prompt-confirm => 06-alert-prompt-confirm}/1-simple-page/task.md (100%) rename 1-js/02-first-steps/{09-alert-prompt-confirm => 06-alert-prompt-confirm}/article.md (78%) rename 1-js/02-first-steps/{06-type-conversions => 07-type-conversions}/article.md (95%) rename 1-js/02-first-steps/{07-operators => 08-operators}/1-increment-order/solution.md (100%) rename 1-js/02-first-steps/{07-operators => 08-operators}/1-increment-order/task.md (100%) rename 1-js/02-first-steps/{07-operators => 08-operators}/2-assignment-result/solution.md (100%) rename 1-js/02-first-steps/{07-operators => 08-operators}/2-assignment-result/task.md (100%) rename 1-js/02-first-steps/{07-operators => 08-operators}/3-primitive-conversions-questions/solution.md (100%) rename 1-js/02-first-steps/{07-operators => 08-operators}/3-primitive-conversions-questions/task.md (100%) create mode 100644 1-js/02-first-steps/08-operators/4-fix-prompt/solution.md create mode 100644 1-js/02-first-steps/08-operators/4-fix-prompt/task.md rename 1-js/02-first-steps/{07-operators => 08-operators}/article.md (82%) rename 1-js/02-first-steps/{08-comparison => 09-comparison}/1-comparison-questions/solution.md (100%) rename 1-js/02-first-steps/{08-comparison => 09-comparison}/1-comparison-questions/task.md (100%) rename 1-js/02-first-steps/{08-comparison => 09-comparison}/article.md (100%) create mode 100644 1-js/02-first-steps/12-nullish-coalescing-operator/article.md rename 1-js/02-first-steps/{12-while-for => 13-while-for}/1-loop-last-value/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/1-loop-last-value/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/2-which-value-while/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/2-which-value-while/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/3-which-value-for/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/3-which-value-for/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/4-for-even/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/4-for-even/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/5-replace-for-while/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/5-replace-for-while/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/6-repeat-until-correct/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/6-repeat-until-correct/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/7-list-primes/solution.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/7-list-primes/task.md (100%) rename 1-js/02-first-steps/{12-while-for => 13-while-for}/article.md (100%) rename 1-js/02-first-steps/{13-switch => 14-switch}/1-rewrite-switch-if-else/solution.md (100%) rename 1-js/02-first-steps/{13-switch => 14-switch}/1-rewrite-switch-if-else/task.md (100%) rename 1-js/02-first-steps/{13-switch => 14-switch}/2-rewrite-if-switch/solution.md (100%) rename 1-js/02-first-steps/{13-switch => 14-switch}/2-rewrite-if-switch/task.md (100%) rename 1-js/02-first-steps/{13-switch => 14-switch}/article.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/1-if-else-required/solution.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/1-if-else-required/task.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/2-rewrite-function-question-or/solution.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/2-rewrite-function-question-or/task.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/3-min/solution.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/3-min/task.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/4-pow/solution.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/4-pow/task.md (100%) rename 1-js/02-first-steps/{14-function-basics => 15-function-basics}/article.md (93%) rename 1-js/02-first-steps/{15-function-expressions => 16-function-expressions}/article.md (100%) rename 1-js/02-first-steps/{16-arrow-functions-basics => 17-arrow-functions-basics}/1-rewrite-arrow/solution.md (100%) rename 1-js/02-first-steps/{16-arrow-functions-basics => 17-arrow-functions-basics}/1-rewrite-arrow/task.md (100%) rename 1-js/02-first-steps/{16-arrow-functions-basics => 17-arrow-functions-basics}/article.md (100%) rename 1-js/02-first-steps/{17-javascript-specials => 18-javascript-specials}/article.md (97%) diff --git a/1-js/02-first-steps/03-strict-mode/article.md b/1-js/02-first-steps/03-strict-mode/article.md index a9643200..30258bbf 100644 --- a/1-js/02-first-steps/03-strict-mode/article.md +++ b/1-js/02-first-steps/03-strict-mode/article.md @@ -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" 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 -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. -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 'use strict'; @@ -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. -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 (function() { '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. -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. -4. We recommended always starting scripts with `"use strict"`. All examples in this tutorial assume strict mode unless (very rarely) specified otherwise. +**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.** + +As of now, we've got to know about `use strict` in general. + +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. diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md index cce9267d..e3190078 100644 --- a/1-js/02-first-steps/05-types/article.md +++ b/1-js/02-first-steps/05-types/article.md @@ -1,6 +1,10 @@ # 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 // no error @@ -8,9 +12,7 @@ let message = "hello"; 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. - -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. +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. ## Number @@ -64,18 +66,20 @@ We'll see more about working with numbers in the chapter . ## BigInt -In JavaScript, the "number" type cannot represent integer values larger than 253 (or less than -253 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 (253-1) (that's `9007199254740991`), or less than -(-253-1) 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. -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 // the "n" at the end means it's a BigInt const bigInt = 1234567890123456789012345678901234567890n; ``` -As `BigInt` numbers are rarely needed, we devoted them a separate chapter . +As `BigInt` numbers are rarely needed, we don't cover them here, but devoted them a separate chapter . Read it when you need such big numbers. ```smart header="Compatability issues" 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". -The code above states that `age` is unknown or empty for some reason. +The code above states that `age` is unknown. ## 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`: ```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 -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 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 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 , 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] @@ -241,8 +248,8 @@ typeof alert // "function" (3) 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 . 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. -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. +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 also comes from the early days of JavaScript. Technically, such behavior isn't correct, but can be convenient in practice. ## Summary diff --git a/1-js/02-first-steps/09-alert-prompt-confirm/1-simple-page/solution.md b/1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/solution.md similarity index 100% rename from 1-js/02-first-steps/09-alert-prompt-confirm/1-simple-page/solution.md rename to 1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/solution.md diff --git a/1-js/02-first-steps/09-alert-prompt-confirm/1-simple-page/task.md b/1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/task.md similarity index 100% rename from 1-js/02-first-steps/09-alert-prompt-confirm/1-simple-page/task.md rename to 1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/task.md diff --git a/1-js/02-first-steps/09-alert-prompt-confirm/article.md b/1-js/02-first-steps/06-alert-prompt-confirm/article.md similarity index 78% rename from 1-js/02-first-steps/09-alert-prompt-confirm/article.md rename to 1-js/02-first-steps/06-alert-prompt-confirm/article.md index 8ba414e9..acd79ba7 100644 --- a/1-js/02-first-steps/09-alert-prompt-confirm/article.md +++ b/1-js/02-first-steps/06-alert-prompt-confirm/article.md @@ -1,18 +1,10 @@ # Interaction: alert, prompt, confirm -In this part of the tutorial we cover JavaScript language "as is", without environment-specific tweaks. - -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`. +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`. ## alert -Syntax: - -```js -alert(message); -``` - -This shows a message and pauses script execution until the user presses "OK". +This one we've seen already. It shows shows a message and waits for the user to presses "OK". For example: @@ -20,7 +12,7 @@ For example: 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 @@ -38,7 +30,11 @@ It shows a modal window with a text message, an input field for the visitor, and `default` : 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. diff --git a/1-js/02-first-steps/06-type-conversions/article.md b/1-js/02-first-steps/07-type-conversions/article.md similarity index 95% rename from 1-js/02-first-steps/06-type-conversions/article.md rename to 1-js/02-first-steps/07-type-conversions/article.md index e7c38125..723d8863 100644 --- a/1-js/02-first-steps/06-type-conversions/article.md +++ b/1-js/02-first-steps/07-type-conversions/article.md @@ -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. ```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 . +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 we'll see how objects fit in. ``` ## String Conversion diff --git a/1-js/02-first-steps/07-operators/1-increment-order/solution.md b/1-js/02-first-steps/08-operators/1-increment-order/solution.md similarity index 100% rename from 1-js/02-first-steps/07-operators/1-increment-order/solution.md rename to 1-js/02-first-steps/08-operators/1-increment-order/solution.md diff --git a/1-js/02-first-steps/07-operators/1-increment-order/task.md b/1-js/02-first-steps/08-operators/1-increment-order/task.md similarity index 100% rename from 1-js/02-first-steps/07-operators/1-increment-order/task.md rename to 1-js/02-first-steps/08-operators/1-increment-order/task.md diff --git a/1-js/02-first-steps/07-operators/2-assignment-result/solution.md b/1-js/02-first-steps/08-operators/2-assignment-result/solution.md similarity index 100% rename from 1-js/02-first-steps/07-operators/2-assignment-result/solution.md rename to 1-js/02-first-steps/08-operators/2-assignment-result/solution.md diff --git a/1-js/02-first-steps/07-operators/2-assignment-result/task.md b/1-js/02-first-steps/08-operators/2-assignment-result/task.md similarity index 100% rename from 1-js/02-first-steps/07-operators/2-assignment-result/task.md rename to 1-js/02-first-steps/08-operators/2-assignment-result/task.md diff --git a/1-js/02-first-steps/07-operators/3-primitive-conversions-questions/solution.md b/1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md similarity index 100% rename from 1-js/02-first-steps/07-operators/3-primitive-conversions-questions/solution.md rename to 1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md diff --git a/1-js/02-first-steps/07-operators/3-primitive-conversions-questions/task.md b/1-js/02-first-steps/08-operators/3-primitive-conversions-questions/task.md similarity index 100% rename from 1-js/02-first-steps/07-operators/3-primitive-conversions-questions/task.md rename to 1-js/02-first-steps/08-operators/3-primitive-conversions-questions/task.md diff --git a/1-js/02-first-steps/08-operators/4-fix-prompt/solution.md b/1-js/02-first-steps/08-operators/4-fix-prompt/solution.md new file mode 100644 index 00000000..04f73fbd --- /dev/null +++ b/1-js/02-first-steps/08-operators/4-fix-prompt/solution.md @@ -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? diff --git a/1-js/02-first-steps/08-operators/4-fix-prompt/task.md b/1-js/02-first-steps/08-operators/4-fix-prompt/task.md new file mode 100644 index 00000000..b3ea4a3a --- /dev/null +++ b/1-js/02-first-steps/08-operators/4-fix-prompt/task.md @@ -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 +``` diff --git a/1-js/02-first-steps/07-operators/article.md b/1-js/02-first-steps/08-operators/article.md similarity index 82% rename from 1-js/02-first-steps/07-operators/article.md rename to 1-js/02-first-steps/08-operators/article.md index f576ea6c..046e3089 100644 --- a/1-js/02-first-steps/07-operators/article.md +++ b/1-js/02-first-steps/08-operators/article.md @@ -1,8 +1,8 @@ -# Operators +# Basic operators, maths 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" @@ -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. -## 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. @@ -41,7 +87,7 @@ let s = "my" + "string"; 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: @@ -50,22 +96,23 @@ alert( '1' + 2 ); // "12" 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. - -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: +See, it doesn't matter whether the first operand is a string or the second one. +Here's a more complex example: ```js run 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 -alert( 2 - '1' ); // 1 -alert( '6' / '2' ); // 3 +alert( 6 - '2' ); // 4, converts '2' to a number +alert( '6' / '2' ); // 3, converts both operands to numbers ``` ## 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 negation | `-` | +| 16 | exponentiation | `**` | | 15 | multiplication | `*` | | 15 | division | `/` | | 13 | addition | `+` | @@ -162,24 +210,11 @@ let x = 2 * 2 + 1; alert( x ); // 5 ``` -It is possible to chain assignments: +### Assignment = returns a value -```js run -let a, b, c; +The fact of `=` being an operator, not a "magical" language construct has an interesting implication. -*!* -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. +Most operators in JavaScript return a value. That's obvious for `+` and `-`, but also true for `=`. 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. -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`. - -For instance: +Another interesting feature is the ability to chain assignments: ```js run -alert( 5 % 2 ); // 1 is a remainder of 5 divided by 2 -alert( 8 % 3 ); // 2 is a remainder of 8 divided by 3 -alert( 6 % 3 ); // 0 is a remainder of 6 divided by 3 +let a, b, c; + +*!* +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 -alert( 2 ** 2 ); // 4 (2 * 2) -alert( 2 ** 3 ); // 8 (2 * 2 * 2) -alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2) +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; ``` -The operator works for non-integer numbers as well. - -For instance: +This notation can be shortened using the operators `+=` and `*=`: ```js run -alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root, that's maths) -alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root) +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) ``` ## Increment/decrement - + Increasing or decreasing a number by one is among the most common numerical operations. @@ -368,41 +428,7 @@ The list of operators: - 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. - -## 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) -``` +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. ## Comma diff --git a/1-js/02-first-steps/08-comparison/1-comparison-questions/solution.md b/1-js/02-first-steps/09-comparison/1-comparison-questions/solution.md similarity index 100% rename from 1-js/02-first-steps/08-comparison/1-comparison-questions/solution.md rename to 1-js/02-first-steps/09-comparison/1-comparison-questions/solution.md diff --git a/1-js/02-first-steps/08-comparison/1-comparison-questions/task.md b/1-js/02-first-steps/09-comparison/1-comparison-questions/task.md similarity index 100% rename from 1-js/02-first-steps/08-comparison/1-comparison-questions/task.md rename to 1-js/02-first-steps/09-comparison/1-comparison-questions/task.md diff --git a/1-js/02-first-steps/08-comparison/article.md b/1-js/02-first-steps/09-comparison/article.md similarity index 100% rename from 1-js/02-first-steps/08-comparison/article.md rename to 1-js/02-first-steps/09-comparison/article.md diff --git a/1-js/02-first-steps/11-logical-operators/article.md b/1-js/02-first-steps/11-logical-operators/article.md index 25f8ff7f..b0ee346f 100644 --- a/1-js/02-first-steps/11-logical-operators/article.md +++ b/1-js/02-first-steps/11-logical-operators/article.md @@ -90,10 +90,10 @@ For instance: ```js run 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 || 0 || 1 ); // 1 (the first truthy 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.** - 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 - let currentUser = null; - let defaultUser = "John"; + let firstName = ""; + 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.** - 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 - let x; - - *!*true*/!* || (x = 1); - - alert(x); // undefined, because (x = 1) not evaluated + *!*true*/!* || alert("printed"); + *!*false*/!* || alert("not printed"); ``` - 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 - 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. + Sometimes, people use this feature to execute commands only if the condition on the left part is truthy. ## && (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)`. ```` -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: @@ -253,14 +241,12 @@ So we basically have an analogue for: ```js run let x = 1; -if (x > 0) { - alert( 'Greater than zero!' ); -} +if (x > 0) 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) diff --git a/1-js/02-first-steps/12-nullish-coalescing-operator/article.md b/1-js/02-first-steps/12-nullish-coalescing-operator/article.md new file mode 100644 index 00000000..a12ad5fb --- /dev/null +++ b/1-js/02-first-steps/12-nullish-coalescing-operator/article.md @@ -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. diff --git a/1-js/02-first-steps/12-while-for/1-loop-last-value/solution.md b/1-js/02-first-steps/13-while-for/1-loop-last-value/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/1-loop-last-value/solution.md rename to 1-js/02-first-steps/13-while-for/1-loop-last-value/solution.md diff --git a/1-js/02-first-steps/12-while-for/1-loop-last-value/task.md b/1-js/02-first-steps/13-while-for/1-loop-last-value/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/1-loop-last-value/task.md rename to 1-js/02-first-steps/13-while-for/1-loop-last-value/task.md diff --git a/1-js/02-first-steps/12-while-for/2-which-value-while/solution.md b/1-js/02-first-steps/13-while-for/2-which-value-while/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/2-which-value-while/solution.md rename to 1-js/02-first-steps/13-while-for/2-which-value-while/solution.md diff --git a/1-js/02-first-steps/12-while-for/2-which-value-while/task.md b/1-js/02-first-steps/13-while-for/2-which-value-while/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/2-which-value-while/task.md rename to 1-js/02-first-steps/13-while-for/2-which-value-while/task.md diff --git a/1-js/02-first-steps/12-while-for/3-which-value-for/solution.md b/1-js/02-first-steps/13-while-for/3-which-value-for/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/3-which-value-for/solution.md rename to 1-js/02-first-steps/13-while-for/3-which-value-for/solution.md diff --git a/1-js/02-first-steps/12-while-for/3-which-value-for/task.md b/1-js/02-first-steps/13-while-for/3-which-value-for/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/3-which-value-for/task.md rename to 1-js/02-first-steps/13-while-for/3-which-value-for/task.md diff --git a/1-js/02-first-steps/12-while-for/4-for-even/solution.md b/1-js/02-first-steps/13-while-for/4-for-even/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/4-for-even/solution.md rename to 1-js/02-first-steps/13-while-for/4-for-even/solution.md diff --git a/1-js/02-first-steps/12-while-for/4-for-even/task.md b/1-js/02-first-steps/13-while-for/4-for-even/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/4-for-even/task.md rename to 1-js/02-first-steps/13-while-for/4-for-even/task.md diff --git a/1-js/02-first-steps/12-while-for/5-replace-for-while/solution.md b/1-js/02-first-steps/13-while-for/5-replace-for-while/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/5-replace-for-while/solution.md rename to 1-js/02-first-steps/13-while-for/5-replace-for-while/solution.md diff --git a/1-js/02-first-steps/12-while-for/5-replace-for-while/task.md b/1-js/02-first-steps/13-while-for/5-replace-for-while/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/5-replace-for-while/task.md rename to 1-js/02-first-steps/13-while-for/5-replace-for-while/task.md diff --git a/1-js/02-first-steps/12-while-for/6-repeat-until-correct/solution.md b/1-js/02-first-steps/13-while-for/6-repeat-until-correct/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/6-repeat-until-correct/solution.md rename to 1-js/02-first-steps/13-while-for/6-repeat-until-correct/solution.md diff --git a/1-js/02-first-steps/12-while-for/6-repeat-until-correct/task.md b/1-js/02-first-steps/13-while-for/6-repeat-until-correct/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/6-repeat-until-correct/task.md rename to 1-js/02-first-steps/13-while-for/6-repeat-until-correct/task.md diff --git a/1-js/02-first-steps/12-while-for/7-list-primes/solution.md b/1-js/02-first-steps/13-while-for/7-list-primes/solution.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/7-list-primes/solution.md rename to 1-js/02-first-steps/13-while-for/7-list-primes/solution.md diff --git a/1-js/02-first-steps/12-while-for/7-list-primes/task.md b/1-js/02-first-steps/13-while-for/7-list-primes/task.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/7-list-primes/task.md rename to 1-js/02-first-steps/13-while-for/7-list-primes/task.md diff --git a/1-js/02-first-steps/12-while-for/article.md b/1-js/02-first-steps/13-while-for/article.md similarity index 100% rename from 1-js/02-first-steps/12-while-for/article.md rename to 1-js/02-first-steps/13-while-for/article.md diff --git a/1-js/02-first-steps/13-switch/1-rewrite-switch-if-else/solution.md b/1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/solution.md similarity index 100% rename from 1-js/02-first-steps/13-switch/1-rewrite-switch-if-else/solution.md rename to 1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/solution.md diff --git a/1-js/02-first-steps/13-switch/1-rewrite-switch-if-else/task.md b/1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/task.md similarity index 100% rename from 1-js/02-first-steps/13-switch/1-rewrite-switch-if-else/task.md rename to 1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/task.md diff --git a/1-js/02-first-steps/13-switch/2-rewrite-if-switch/solution.md b/1-js/02-first-steps/14-switch/2-rewrite-if-switch/solution.md similarity index 100% rename from 1-js/02-first-steps/13-switch/2-rewrite-if-switch/solution.md rename to 1-js/02-first-steps/14-switch/2-rewrite-if-switch/solution.md diff --git a/1-js/02-first-steps/13-switch/2-rewrite-if-switch/task.md b/1-js/02-first-steps/14-switch/2-rewrite-if-switch/task.md similarity index 100% rename from 1-js/02-first-steps/13-switch/2-rewrite-if-switch/task.md rename to 1-js/02-first-steps/14-switch/2-rewrite-if-switch/task.md diff --git a/1-js/02-first-steps/13-switch/article.md b/1-js/02-first-steps/14-switch/article.md similarity index 100% rename from 1-js/02-first-steps/13-switch/article.md rename to 1-js/02-first-steps/14-switch/article.md diff --git a/1-js/02-first-steps/14-function-basics/1-if-else-required/solution.md b/1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/1-if-else-required/solution.md rename to 1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md diff --git a/1-js/02-first-steps/14-function-basics/1-if-else-required/task.md b/1-js/02-first-steps/15-function-basics/1-if-else-required/task.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/1-if-else-required/task.md rename to 1-js/02-first-steps/15-function-basics/1-if-else-required/task.md diff --git a/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/solution.md b/1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/solution.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/solution.md rename to 1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/solution.md diff --git a/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/task.md b/1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/task.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/task.md rename to 1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/task.md diff --git a/1-js/02-first-steps/14-function-basics/3-min/solution.md b/1-js/02-first-steps/15-function-basics/3-min/solution.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/3-min/solution.md rename to 1-js/02-first-steps/15-function-basics/3-min/solution.md diff --git a/1-js/02-first-steps/14-function-basics/3-min/task.md b/1-js/02-first-steps/15-function-basics/3-min/task.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/3-min/task.md rename to 1-js/02-first-steps/15-function-basics/3-min/task.md diff --git a/1-js/02-first-steps/14-function-basics/4-pow/solution.md b/1-js/02-first-steps/15-function-basics/4-pow/solution.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/4-pow/solution.md rename to 1-js/02-first-steps/15-function-basics/4-pow/solution.md diff --git a/1-js/02-first-steps/14-function-basics/4-pow/task.md b/1-js/02-first-steps/15-function-basics/4-pow/task.md similarity index 100% rename from 1-js/02-first-steps/14-function-basics/4-pow/task.md rename to 1-js/02-first-steps/15-function-basics/4-pow/task.md diff --git a/1-js/02-first-steps/14-function-basics/article.md b/1-js/02-first-steps/15-function-basics/article.md similarity index 93% rename from 1-js/02-first-steps/14-function-basics/article.md rename to 1-js/02-first-steps/15-function-basics/article.md index cbc3cc1e..b56fbc67 100644 --- a/1-js/02-first-steps/14-function-basics/article.md +++ b/1-js/02-first-steps/15-function-basics/article.md @@ -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. ``` -````smart header="Default parameters old-style" -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. +### Alternative default parameters -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 -function showMessage(from, text) { +To check for an omitted parameter, we can compare it with `undefined`: + +```js run +function showMessage(text) { *!* 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 -function showMessage(from, text) { - // if text is falsy then text gets the "default" value - text = text || 'no text given'; +// if text parameter is omitted or "" is passed, set it to 'empty' +function showMessage(text) { + 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 diff --git a/1-js/02-first-steps/15-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md similarity index 100% rename from 1-js/02-first-steps/15-function-expressions/article.md rename to 1-js/02-first-steps/16-function-expressions/article.md diff --git a/1-js/02-first-steps/16-arrow-functions-basics/1-rewrite-arrow/solution.md b/1-js/02-first-steps/17-arrow-functions-basics/1-rewrite-arrow/solution.md similarity index 100% rename from 1-js/02-first-steps/16-arrow-functions-basics/1-rewrite-arrow/solution.md rename to 1-js/02-first-steps/17-arrow-functions-basics/1-rewrite-arrow/solution.md diff --git a/1-js/02-first-steps/16-arrow-functions-basics/1-rewrite-arrow/task.md b/1-js/02-first-steps/17-arrow-functions-basics/1-rewrite-arrow/task.md similarity index 100% rename from 1-js/02-first-steps/16-arrow-functions-basics/1-rewrite-arrow/task.md rename to 1-js/02-first-steps/17-arrow-functions-basics/1-rewrite-arrow/task.md diff --git a/1-js/02-first-steps/16-arrow-functions-basics/article.md b/1-js/02-first-steps/17-arrow-functions-basics/article.md similarity index 100% rename from 1-js/02-first-steps/16-arrow-functions-basics/article.md rename to 1-js/02-first-steps/17-arrow-functions-basics/article.md diff --git a/1-js/02-first-steps/17-javascript-specials/article.md b/1-js/02-first-steps/18-javascript-specials/article.md similarity index 97% rename from 1-js/02-first-steps/17-javascript-specials/article.md rename to 1-js/02-first-steps/18-javascript-specials/article.md index dff66824..91be0aa4 100644 --- a/1-js/02-first-steps/17-javascript-specials/article.md +++ b/1-js/02-first-steps/18-javascript-specials/article.md @@ -152,6 +152,9 @@ Conditional 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. +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 : 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 : There are few others, like a comma operator. -More in: , , . +More in: , , , . ## Loops