From 3dc3018fd123d00abcd8c174e31f9f2857316bc1 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Sat, 2 Jul 2016 18:11:36 +0300 Subject: [PATCH] works --- 1-js/2-first-steps/07-types/article.md | 166 ++---- .../08-type-conversions/article.md | 151 +++++ .../object-user-delete.png | Bin 0 -> 3884 bytes .../object-user-delete@2x.png | Bin 0 -> 8855 bytes .../object-user-isadmin.png | Bin 0 -> 4450 bytes .../object-user-isadmin@2x.png | Bin 0 -> 10202 bytes .../08-type-conversions/object-user.png | Bin 0 -> 3378 bytes .../08-type-conversions/object-user@2x.png | Bin 0 -> 7810 bytes .../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 => 09-operators}/article.md | 0 .../1-comparison-questions/solution.md | 0 .../1-comparison-questions/task.md | 0 .../article.md | 0 .../1-destructuring-assignment/solution.md | 13 + .../1-destructuring-assignment/task.md | 33 ++ .../2-first-steps/11-destructuring/article.md | 273 +++++++++ .../1-simple-page/solution.md | 0 .../1-simple-page/task.md | 0 .../{10-uibasic => 12-uibasic}/article.md | 0 .../1-if-zero-string/solution.md | 0 .../1-if-zero-string/task.md | 0 .../2-check-standard/ifelse_task2.png | Bin .../2-check-standard/ifelse_task2/index.html | 0 .../2-check-standard/ifelse_task2@2x.png | Bin .../2-check-standard/solution.md | 0 .../2-check-standard/task.md | 0 .../3-sign/if_sign/index.html | 0 .../3-sign/solution.md | 0 .../{11-ifelse => 13-ifelse}/3-sign/task.md | 0 .../4-check-login/ifelse_task.png | Bin .../4-check-login/ifelse_task@2x.png | Bin .../4-check-login/solution.md | 0 .../4-check-login/task.md | 0 .../5-rewrite-if-question/solution.md | 0 .../5-rewrite-if-question/task.md | 0 .../6-rewrite-if-else-question/solution.md | 0 .../6-rewrite-if-else-question/task.md | 0 .../{11-ifelse => 13-ifelse}/article.md | 0 .../1-alert-null-2-undefined/solution.md | 0 .../1-alert-null-2-undefined/task.md | 0 .../2-alert-or/solution.md | 0 .../2-alert-or/task.md | 0 .../3-alert-1-null-2/solution.md | 0 .../3-alert-1-null-2/task.md | 0 .../4-alert-and/solution.md | 0 .../4-alert-and/task.md | 0 .../5-alert-and-or/solution.md | 0 .../5-alert-and-or/task.md | 0 .../6-check-if-in-range/solution.md | 0 .../6-check-if-in-range/task.md | 0 .../7-check-if-out-range/solution.md | 0 .../7-check-if-out-range/task.md | 0 .../8-if-question/solution.md | 0 .../8-if-question/task.md | 0 .../article.md | 0 .../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 .../{13-while-for => 15-while-for}/article.md | 110 +++- .../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 .../{14-switch => 16-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 | 55 -- .../function_basics.png | Bin .../function_basics@2x.png | Bin .../20-function-parameters/article.md | 555 ++++++++++++++++++ .../article.md | 0 .../1-string-new-property/solution.md | 0 .../1-string-new-property/task.md | 0 .../article.md | 0 .../article.md | 0 1-js/4-data-structures/3-string/article.md | 24 + 98 files changed, 1182 insertions(+), 198 deletions(-) create mode 100644 1-js/2-first-steps/08-type-conversions/article.md create mode 100644 1-js/2-first-steps/08-type-conversions/object-user-delete.png create mode 100644 1-js/2-first-steps/08-type-conversions/object-user-delete@2x.png create mode 100644 1-js/2-first-steps/08-type-conversions/object-user-isadmin.png create mode 100644 1-js/2-first-steps/08-type-conversions/object-user-isadmin@2x.png create mode 100644 1-js/2-first-steps/08-type-conversions/object-user.png create mode 100644 1-js/2-first-steps/08-type-conversions/object-user@2x.png rename 1-js/2-first-steps/{08-operators => 09-operators}/1-increment-order/solution.md (100%) rename 1-js/2-first-steps/{08-operators => 09-operators}/1-increment-order/task.md (100%) rename 1-js/2-first-steps/{08-operators => 09-operators}/2-assignment-result/solution.md (100%) rename 1-js/2-first-steps/{08-operators => 09-operators}/2-assignment-result/task.md (100%) rename 1-js/2-first-steps/{08-operators => 09-operators}/3-primitive-conversions-questions/solution.md (100%) rename 1-js/2-first-steps/{08-operators => 09-operators}/3-primitive-conversions-questions/task.md (100%) rename 1-js/2-first-steps/{08-operators => 09-operators}/article.md (100%) rename 1-js/2-first-steps/{09-comparison => 10-comparison}/1-comparison-questions/solution.md (100%) rename 1-js/2-first-steps/{09-comparison => 10-comparison}/1-comparison-questions/task.md (100%) rename 1-js/2-first-steps/{09-comparison => 10-comparison}/article.md (100%) create mode 100644 1-js/2-first-steps/11-destructuring/1-destructuring-assignment/solution.md create mode 100644 1-js/2-first-steps/11-destructuring/1-destructuring-assignment/task.md create mode 100644 1-js/2-first-steps/11-destructuring/article.md rename 1-js/2-first-steps/{10-uibasic => 12-uibasic}/1-simple-page/solution.md (100%) rename 1-js/2-first-steps/{10-uibasic => 12-uibasic}/1-simple-page/task.md (100%) rename 1-js/2-first-steps/{10-uibasic => 12-uibasic}/article.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/1-if-zero-string/solution.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/1-if-zero-string/task.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/2-check-standard/ifelse_task2.png (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/2-check-standard/ifelse_task2/index.html (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/2-check-standard/ifelse_task2@2x.png (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/2-check-standard/solution.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/2-check-standard/task.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/3-sign/if_sign/index.html (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/3-sign/solution.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/3-sign/task.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/4-check-login/ifelse_task.png (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/4-check-login/ifelse_task@2x.png (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/4-check-login/solution.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/4-check-login/task.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/5-rewrite-if-question/solution.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/5-rewrite-if-question/task.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/6-rewrite-if-else-question/solution.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/6-rewrite-if-else-question/task.md (100%) rename 1-js/2-first-steps/{11-ifelse => 13-ifelse}/article.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/1-alert-null-2-undefined/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/1-alert-null-2-undefined/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/2-alert-or/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/2-alert-or/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/3-alert-1-null-2/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/3-alert-1-null-2/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/4-alert-and/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/4-alert-and/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/5-alert-and-or/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/5-alert-and-or/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/6-check-if-in-range/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/6-check-if-in-range/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/7-check-if-out-range/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/7-check-if-out-range/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/8-if-question/solution.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/8-if-question/task.md (100%) rename 1-js/2-first-steps/{12-logical-ops => 14-logical-ops}/article.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/1-loop-last-value/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/1-loop-last-value/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/2-which-value-while/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/2-which-value-while/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/3-which-value-for/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/3-which-value-for/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/4-for-even/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/4-for-even/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/5-replace-for-while/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/5-replace-for-while/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/6-repeat-until-correct/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/6-repeat-until-correct/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/7-list-primes/solution.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/7-list-primes/task.md (100%) rename 1-js/2-first-steps/{13-while-for => 15-while-for}/article.md (72%) rename 1-js/2-first-steps/{14-switch => 16-switch}/1-rewrite-switch-if-else/solution.md (100%) rename 1-js/2-first-steps/{14-switch => 16-switch}/1-rewrite-switch-if-else/task.md (100%) rename 1-js/2-first-steps/{14-switch => 16-switch}/2-rewrite-if-switch/solution.md (100%) rename 1-js/2-first-steps/{14-switch => 16-switch}/2-rewrite-if-switch/task.md (100%) rename 1-js/2-first-steps/{14-switch => 16-switch}/article.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/1-if-else-required/solution.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/1-if-else-required/task.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/2-rewrite-function-question-or/solution.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/2-rewrite-function-question-or/task.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/3-min/solution.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/3-min/task.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/4-pow/solution.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/4-pow/task.md (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/article.md (87%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/function_basics.png (100%) rename 1-js/2-first-steps/{18-function-basics => 19-function-basics}/function_basics@2x.png (100%) create mode 100644 1-js/2-first-steps/20-function-parameters/article.md rename 1-js/2-first-steps/{19-function-expression => 21-function-expression}/article.md (100%) rename 1-js/2-first-steps/{20-primitives-methods => 22-primitives-methods}/1-string-new-property/solution.md (100%) rename 1-js/2-first-steps/{20-primitives-methods => 22-primitives-methods}/1-string-new-property/task.md (100%) rename 1-js/2-first-steps/{20-primitives-methods => 22-primitives-methods}/article.md (100%) rename 1-js/2-first-steps/{22-javascript-specials => 23-javascript-specials}/article.md (100%) diff --git a/1-js/2-first-steps/07-types/article.md b/1-js/2-first-steps/07-types/article.md index 40b82e45..177d9510 100644 --- a/1-js/2-first-steps/07-types/article.md +++ b/1-js/2-first-steps/07-types/article.md @@ -233,6 +233,37 @@ Most of time, the dot is used to access object properties, but when we need a co Objects in JavaScript are very powerful. Here we've just scratched the surface of the topic that is really huge. We'll be closely working with objects and learning more about them in further parts of the tutorial. +## Arrays + +As we’ve just seen, objects in Javascript store arbitrary keyed values. + +But quite often we find that we need an *ordered collection*, where we have a 1st, a 2nd, a 3rd element and so on. For example, we need that to store a list of something: users, goods, HTML elements etc. It not convenient to use an object here, because it provides no methods to manage the order of elements. We can’t easily access the n-th element in an object. Also we can’t insert a new property “before” the existing ones, and so on. Objects are just not meant for such use. + +There exists a special data structure named "an array", to store ordered collections. + +An array is created using square brackets: + +```js +let empty = []; // empty array + +let fruits = ["Apple", "Orange", "Plum"]; // array with 3 values +``` + +Individual items are accessed using brackets `[]`, the first item has zero index: + +```js run +let fruits = ["Apple", "Orange", "Plum"]; // array with 3 values + +alert( fruits[0] ); // Apple +alert( fruits[1] ); // Orange +alert( fruits[2] ); // Plum + +// how many elements (last index + 1) +alert( fruits.length ); // 3 +``` + +Please note that arrays do not form a separate language type. They are based on objects, but have many features of their own including methods to add, remove, extract elements from the array, to sort arrays and more. We'll cover them in the chapter . + ## Symbol type The `symbol` type is used in conjunction with objects. Probably we won't need them any time soon, but it's the 7th and the last type of the language, so we must mention it here for the sake of completeness. @@ -319,140 +350,24 @@ typeof Symbol("id") // "symbol" typeof {} // "object" *!* -typeof null // "object" (1) +typeof [] // "object" (1) */!* *!* -typeof alert // "function" (2) +typeof null // "object" (2) */!* -``` - -Please note the last two lines, because `typeof` behaves a little bit strange there. - -1. The result of `typeof null` equals to `"object"`. That is an officially recognized error in `typeof` implementation, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So `typeof` just says it wrong here. -2. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the near future and see that actually functions belong to the object type. But `typeof` treats them differently. That's very convenient in practice. - - -## Type conversions - -A variable in JavaScript can contain any data. A variable can at one moment be a string and later recieve a numeric value: - -```js -// no error -let message = "hello"; -message = 123456; -``` - -...But sometimes we need to convert a value from one type to another. For example, `alert` automatically converts any value to a string, to show it. Or, so to say, an `if(value)` test converts the `value` to boolean type to see if it's `true` or `false`. - -There are also cases when we need to explicitly convert between types to ensure that we store the right data the right way or to use special features of a certain type. - -There are many type conversions in JavaScript, fully listed in [the specification](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-type-conversion). - -Three conversions that happen the most often: - -1. String conversion. -2. Numeric conversion. -3. Boolean conversion. - -Let's see how they work and when they happen. - -### String conversion - -The string conversion happens when we need a string form of a value. - -For example, `alert` does it: - -```js run -let a = true; - -alert( a ); // "true" -``` - -We can also use a call `String(value)` function for that: - -```js run -let a = true; -alert(typeof a); // boolean *!* -a = String(a); // now: a = "true" -alert(typeof a); // string +typeof alert // "function" (3) */!* ``` -The string conversion is obvious. A `false` becomes `"false"`, `null` becomes `"null"` etc. +Please note the last lines. -### Numeric conversion +1. The array is not a type of its own, but a subtype of object, that's why `typeof []` is `"object"`. +2. The result of `typeof null` equals to `"object"`. That's wrong. It is an officially recognized error in `typeof` implementation, kept for compatibility. Of course, `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 of the language. We'll study functions in the near future and see that actually functions belong to the object type. But `typeof` treats them differently. That's very convenient in practice. -Numeric conversion happens in mathematical functions and expressions automatically. - -For example, a mathematical operation like division '/' can be applied to non-numbers: - -```js run -alert( "6" / "2" ); // 3, strings become numbers -``` - -We can use a `Number(value)` function to convert any `value` to a number: - -```js run -let str = "123"; -alert(typeof str); // string - -let n = Number(str); // becomes a number 123 - -alert(typeof n); // number -``` - -The conversion is usually applied when we have a numeric value coming from a text form field or another string-based source. - -If the string is not a number, the result of such conversion is `NaN`, for instance: - -```js run -let age = Number("an arbitrary string instead of a number"); - -alert(age); // NaN, conversion failed -``` - -The numeric conversion rules: - -| Value | Becomes... | -|-------|-------------| -|`undefined`|`NaN`| -|`null`|`0`| -|true / false | `1 / 0` | -| `string` | Whitespaces from the start and the end are removed. Then, if the remaining string is empty, the result is `0`, otherwise –- the number is "read" from the string. An error gives `NaN`. | - -Examples: - -```js run -alert( Number(" 123 ") ); // 123 -alert( Number("123z") ); // NaN (error reading a number at "z") -alert( Number(true) ); // 1 -alert( Number(false) ); // 0 -``` - -Please note that `null` and `undefined` behave differently here: `null` becomes a zero, while `undefined` becomes `NaN`. - -### Boolean conversion - -Boolean conversion is the simplest one. - -It happens in logical operations (later we'll meet `if` tests and other kinds), but also can be performed manually with the call of `Boolean(value)`. - -The conversion rule: - -- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined` and `NaN` become `false`. -- Other values become `true`. - -````warn header="Please note: a string `\"0\"` is `true`" -Some languages (namely PHP) treat `"0"` as `false`. But in JavaScript a non-empty string is always `false`, no matter what is in it. - -```js run -alert( Boolean("0") ); // true -alert( Boolean(" ") ); // any non-empty string, even whitespaces are true -``` -```` ## Summary @@ -464,9 +379,8 @@ There are 7 basic types in JavaScript. - `boolean` for `true`/`false`, can convert into it using `Boolean(value)`. - `null` for unknown values. - `undefined` for unassigned values. -- `object` for complex data structures. - `symbol` for unique identifiers. +- `object` for more complex data structures (there exist many, we saw arrays). -The `typeof` operator allows to see which type is stored in the variable, but note that it mistakingly returns `"object"` for `null`. +The `typeof` operator allows to see which type is stored in the variable. -Now let's study operators and other language constructs that actually form our code. diff --git a/1-js/2-first-steps/08-type-conversions/article.md b/1-js/2-first-steps/08-type-conversions/article.md new file mode 100644 index 00000000..57525e33 --- /dev/null +++ b/1-js/2-first-steps/08-type-conversions/article.md @@ -0,0 +1,151 @@ +# Type conversions + +A variable in JavaScript can contain any data. A variable can at one moment be a string and later recieve a numeric value: + +```js +// no error +let message = "hello"; +message = 123456; +``` + +...But sometimes we need to convert a value from one type to another. For example, `alert` automatically converts any value to a string, to show it. Or, so to say, an `if(value)` test converts the `value` to boolean type to see if it's `true` or `false`. + +There are also cases when we need to explicitly convert between types to ensure that we store the right data the right way or to use special features of a certain type. + +There are many type conversions in JavaScript, fully listed in [the specification](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-type-conversion). + +Three conversions that happen the most often: + +1. String conversion. +2. Numeric conversion. +3. Boolean conversion. + +Let's see how they work and when they happen. + +## String conversion + +The string conversion happens when we need a string form of a value. + +For example, `alert` does it: + +```js run +let a = true; + +alert( a ); // "true" +``` + +We can also use a call `String(value)` function for that: + +```js run +let a = true; +alert(typeof a); // boolean + +*!* +a = String(a); // now: a = "true" +alert(typeof a); // string +*/!* +``` + +The string conversion is obvious. A `false` becomes `"false"`, `null` becomes `"null"` etc. + +## Numeric conversion + +Numeric conversion happens in mathematical functions and expressions automatically. + +For example, a mathematical operation like division '/' can be applied to non-numbers: + +```js run +alert( "6" / "2" ); // 3, strings become numbers +``` + +We can use a `Number(value)` function to convert any `value` to a number: + +```js run +let str = "123"; +alert(typeof str); // string + +let n = Number(str); // becomes a number 123 + +alert(typeof n); // number +``` + +The conversion is usually applied when we have a numeric value coming from a text form field or another string-based source. + +If the string is not a number, the result of such conversion is `NaN`, for instance: + +```js run +let age = Number("an arbitrary string instead of a number"); + +alert(age); // NaN, conversion failed +``` + +The numeric conversion rules: + +| Value | Becomes... | +|-------|-------------| +|`undefined`|`NaN`| +|`null`|`0`| +|true and false | `1` and `0` | +| `string` | Whitespaces from the start and the end are removed. Then, if the remaining string is empty, the result is `0`, otherwise -- the number is "read" from the string. An error gives `NaN`. | + +Examples: + +```js run +alert( Number(" 123 ") ); // 123 +alert( Number("123z") ); // NaN (error reading a number at "z") +alert( Number(true) ); // 1 +alert( Number(false) ); // 0 +``` + +Please note that `null` and `undefined` behave differently here: `null` becomes a zero, while `undefined` becomes `NaN`. + +## Boolean conversion + +Boolean conversion is the simplest one. + +It happens in logical operations (later we'll meet `if` tests and other kinds), but also can be performed manually with the call of `Boolean(value)`. + +The conversion rule: + +- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined` and `NaN` become `false`. +- Other values become `true`. + +````warn header="Please note: the string with zero `\"0\"` is `true`" +Some languages (namely PHP) treat `"0"` as `false`. But in JavaScript a non-empty string is always `true`. + +```js run +alert( Boolean("0") ); // true +alert( Boolean(" ") ); // any non-empty string, even whitespaces are true +``` +```` + +## Summary + +There exist three most widely used type conversions: to string, to number and to boolean. + +The conversion to string is usully obvious. + +To number follows the rules: + +| Value | Becomes... | +|-------|-------------| +|`undefined`|`NaN`| +|`null`|`0`| +|true / false | `1 / 0` | +| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string is `0`. An error gives `NaN`. | + +To boolean: + +| Value | Becomes... | +|-------|-------------| +|`0`, `null`, `undefined`, `NaN`, `""` |`false`| +|any other value| `true` | + +Objects provide advanced means to specify how they are converted to string and number, we'll see them later, when study objects in-depth. + +Most of these rules are easy to understand and memorize. The notable exceptions where people usually make mistakes are: + +- `undefined` is `NaN` as a number. +- `"0"` is true as a boolean. + +In the next chapter we'll study operators. You will find enough tasks for type conversion there. \ No newline at end of file diff --git a/1-js/2-first-steps/08-type-conversions/object-user-delete.png b/1-js/2-first-steps/08-type-conversions/object-user-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..3022fef2a1e1aa7ef747f72d77c65684f0635f0a GIT binary patch literal 3884 zcmb7{_ct4E*#C*p*a@Mi5kV_av-XIDAZpZ3Ytv94(H2!&JGED(sslBuMeU&4s*xi0 zsMQL!N_5&q&3f`Z=llEt&kxu2I`_HX*KhaxKG!?N#@dXRON@(!g@xA~hqYsp%&ck< z2eW$=?+!4*ddtqth^1y&{3i~?ZMscmbK{PZ!r^;V|VJ(3H4;4d7e0gKE(jB=7E3#r7sBa zEM~DFEY^>U6>ej{Ve1VC2NfZJ$!M!~vy>DxjZ_MT0W{d9h_= z%9XCA9q*wy4YCEg(wPT>a~yd8@-(DZuE!F%N73`m*VVMX zOO2jx&zc>`1u>wXWz2EO=X^uA%<~a)A8$}-}Q(a8Poym z(xz7B`6^U=KTo7c3c?Q|#RE!}@JqWp8sxps>fH;E&dWi1ec~9Xa4EGD_od+SVIecC zr=9`a&7rXmMD8tY$FT;g)%7o%DgNhRvVmuT;3%z$>&FNv#~b6x>zN$|zm)`@HAhZC zNWd?$+RsnJ9Ij$EG0l>4Ch({g%uR7-3C4;ZU#iHmV% zh&Jyb!&aew`E@B`xr^>8jN`YrvVNFJc)-(yiAmc7l`Q(d-i1b=@Fkx|)yncmct#7? zq}msAAXnCsj)o;hLN_0QpXqX|-K2J`3O>^mOdkY6H{3ky55FMN1H{HEC0S*39J-!p zTdPzoWW&f#E0oX>Je`Ki45SLDIK?-ARkiC>iJZ*vWCUpyr=-P<%Z?;r{K2n?aLTB) z|EEr{&QI|hiIFiOw zrvt^eB}MPZ%ygDuj(!_%cL#h0(T1<^{k&aC5w0lE4`|+wnCq2$=imc^q7Dc@L<~jM zYEj(#q)U4<7L0e}(%MTZ?c^(ie20eRRKw&b3J>G(t)miAKue;DHhWJOXi8b-)Sa)*(D*I3!cS} zyeN`t1_rO+jNi71smxLc-`%QEG31cPz~0>H>lMt^7Kc>7;0~FASD0L#Q^yO9MXrg4bs7{#>>4hIZDYQU|3cY1Vhe%twrr|Z88lSy z0tSWpqt6wol}DLruFbO+7o!h~mCF+5BO T4=&l$%~iUWq3}2=p7D)!#Nji?kLy~ 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 R4!$&jC_Yt{Es-|y{U47f`hoxe literal 0 HcmV?d00001 diff --git a/1-js/2-first-steps/08-type-conversions/object-user-isadmin.png b/1-js/2-first-steps/08-type-conversions/object-user-isadmin.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f3bcb672c9b0de35153cff3c42f3acc1f55dfb GIT binary patch literal 4450 zcmb`LS5yiu`V2aDJbpj|h(|}oWg;%&@C;GfvEX5e1Ig>`c$NPV{=SGU3|e9^<@9;qkFzAp z8yTaxFo19su5xJs9XWHa$kluDU??t}9)Fvt9}Bj+A{0Ie0c51%n)|BxRBIxh)_mRK zv(1KQ1|lxz_%Ygot*(c@Am68m)IjlpZ77|l2GUe8=!ZM_ z>qjp1W48n8B<{gn6TwdP6Q+0xM@as2;Xy)Dk&YZeoqx^x$w0`8&Pr+~uDk+7se2Un z=k&=J$((P`V>QBoMkI^nm{$gSYm#{!Pw$wCnvw zQKi7s%r<4$3kMkwM>V?A9xCFI@y}=9wdVw+_B=Vh3)0PhestUkuj0{P<|kJM)dWwJ+=G86 zbVU%`PV?Z~0b#*BXy6+@i@d(ydwdrN26Um6n@e7sO!?9Aic-~yz5L@<8k7?~IKbmN z!E36^)?UN6_J+leE*(_ZoXj>|kGrDmFtexjYTRLN{x{+&uuhqH_p4vb<45Ri5?iAr0?tevwjG&f9=UFFKzG*;IUV)9sU*mDknfJG$}2C>RF{KI9+rVmWRhM z&V(_t+;?spm2dHp@r#s^jL9BN$0KZzyh#UdR$!A8w@b7y^IX;gN`Xrj8Sz0Tpv&$H z3a8b;I1tTGy#yJ_`ncPU_}xQxy0o?FGG$mX0p9feA{UFhd$GU(Z2-_y_KnX%B0+vE zIZ)V$6`-`ogrwl%5!`@sQePFxZ;FMsl-h1N17>LrQF;yMA~j}zO-Jon8C2iu?39^9 z;alo1YxA6Po?JdASC(80Q{iUGNAiu6)eokg%~*Pr!l0Jq<#`$5H>-_=NiV;%6S)r? z;Ijjw#@e=Bq%H9~ixSZhH2tssUEnWP)#1{Y#uXb*m0EN~0V|lu5rl7I3J;qP{G`b( z^r^Jn6~LjHy1;rallFYPvT#cTlk*1nCJOT5-%NPv$E!cz!RzzBrjM2~>SXlD-IC0R zc^MOPr8|MypwUm>$bJ_HaAW`!upPUVqsb4xh|d%38yS_M-Q4uc?!XO181d-Hxz3pM zS+6wY9&Y^CO54!D1tT3TiOvn;=MSq7jxVV%sDtyb+d9|{n{D2%=9h!A-kki|#EqR) zUK@3!CdcQhYQ^^~e8hd}%)C$fezsFZhVM!!Z>+C|mRteuF0K*2?|`T?5%mU+_xC=$ zR8bZwfk7u_-4|&W1(?^Vyks`>-Ppa%JV21L=KWX3Q_R!R3>Z=%GL%irNWMwt0d1tO ziN8hbU8OhyI|i0+c9&LZxKE)-dxSMG2)a^cvl1RT@Nj!|j8-6KxHFSeI8dCzdJyXR z^K||Mpx}!InXgmQGA|*i3%O>?v#ox)fg0iKdF?SjM0YN9bm}GPtXE|Q^02-g-|{Rb z5snv~49Lz9Tn-Ucog7WWLM2l@^Rt{|QmO`$7MlAwX$-oGrhk?s!X4kanM>Ddg6eH& zK&@BJ25yX&jj#5l!s>TFiWyr1$;^fr7^u82I*@a}fxk>n^to>T95JUM>V-N^Y9$sG zeTCT7!2Z&hdw#Q8%RlO6ttNBbSU%1^iJ6)Z;lLOl-aBEiF43<1@WMf+R^kTmJyytp z#sMsM9^aLnjgbOV*Gbb&pe*NTU|q;%n7igUJ>w%Fm}nJ*F)=^&*U%ShA)}QVNI

D;Dr!^DcH>? z2j~0ubX}Y<&FJxPOWNRMec>if0~+xc)U!Ex z{_=u%TJwgx#S*e2n~P^*5W>Pu)n1IHgEE_0VbcKb)6YX(6YK z_aM=d+FWqU3~un4lig0HD)UK9?t!!F^=#C(B7WXVRb_+eyR)X*YDdfmV?EE^{!{-$ zS$t4cg^6=f(mWCz_45jk;s84?et&qZ06jnSjBxDxY*~x^WUyZH{GyEF#$7K5EX>NW zHrMGB)jPV;KZH=v78z{E%rO`Nh<~?DU1-3VT93z=yICg~~xty2Ku62bn{Jo0|=aLU{os{jbkWu05=JzAra`Wt91tB5sf?3n;|0aHJ ze%QRISt@L9Djbbx#Vka)%3{&`ofIo;xlJsO){l|WH?-VT)X02$2Q_zJ_)sd?rCP?} zFNP7J?}V*TGuha*kP|p> zJ1!D7&Yrt-3_3nAGQ~(~)=_pc3&azpRmH};D#8(d)$>~DnFkga7J!%S_!|h9s3sG< z*Fd$YVz+>%p%5Id{5D4UWBv4`I@r^dCl}_jbr26fY3*D;@PbLj1eaCnHIDKCgw5f2K5kKe>Y; zA)fp-{tb~NSZ$IfF;@U}Zj^qfA>||8Mg>Vo7>mOIwQa9$@I9^nPSs}b%<7)*ElsSrGSIRm%|_}fX|?PKfq0%)*&A)C@wvm@-6Vu0x@TS( zRJh%hb&xYaSIRvml5b&f&DSt(wkdWZ=B0L6 za}7K?F1D7lPPfpguB0#=iUZO+OSvYapSc=hc3}W!Kr5EYfs^jcid)A3Ie?L+_#h84 z)LzZ+eW^Sp@R~cf!pR>p^wqtShf!+)H$#btwsLs?|J^$OcVBIL$3_2}^@r%4#N74; z2wFVx<2b*^$H~MHUC4zJORt?$7(sp*SpTnC5_;&q`cKlBbzB!jr`FR3!BK6Z+hC7R5<{~x4_Y5lHU^^#fm8krFIqUnbAu2}) zD~a>Iaq~YXhL2rN<`hJ+#{f+e_tIs;O=g<6Hf|67d0LnoxX#RQofdYInByB|R)xHv zpr5a9k>)E~V2KMvWL9qhjo!{su0b!*l+s!gSuHP7!UIZHV`{8{~HCkbXH}+$;gkA>43tKlloN1rJ0TEC_zqwcS!drc z5-Dc&?e;CXNpDS)*X{BR&{xIx*r;yo@gkHgu|0ppGfm>ScdO$mw!o&ZA-DD^yeY({ z51ExYQBzy=6_|2E4K~;?_D=BemJkD6Ij=8iEle|@=|VXfNy?teJ~`qz(uE-xyeHo> z@X&v*B4h|9H0=6k_x23FjWkWH9Ae(;+Vl)uu1=yXB~pK+$v{SJAGt-0V#FtycZrsqp!#LL;ySP*0304XnAP|-i? z^HWUDd=aKw=k?j+*(xu3kmuc74LRSN_*^4Kbppri|9z_l4;`;|JuImS>oq_)3b)1$8iLrkbaVMNC2%HX|lbY(qLP{VIy(@aL zV0TU_qw-Wbb^{*n6vY%e_8v*>Q&S##5dvJ6(~I+*7A2A-I6xQXWG6W&dCp=33zXCO zK-~P=yu{+1`j1}*HlGi-fi6V`#pg^D(OU~V4`Z!E`?3BxdG%5T*F@03!Nf$7^m8Io zI7^503QKfy{4x+3o1dh5E2ORCbp-3trgh~;y(7lD4XCsns3YLRXaGrV9y_J-nmM;>OangFw?(4|WK_F5#-N6f(g0oWWO z%KA5ja1&SwzMfJAWH;d7;}XsRTe08av}G0{sBFq;|2m^1hCMoi^}pab|1_a9)HBs3 IYyT7XUpkjBjQ{`u literal 0 HcmV?d00001 diff --git a/1-js/2-first-steps/08-type-conversions/object-user-isadmin@2x.png b/1-js/2-first-steps/08-type-conversions/object-user-isadmin@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..79dc9a5baca5b9199f247e63b2c7080d91de6c9a GIT binary patch literal 10202 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 GPyY?%I%sGB literal 0 HcmV?d00001 diff --git a/1-js/2-first-steps/08-type-conversions/object-user.png b/1-js/2-first-steps/08-type-conversions/object-user.png new file mode 100644 index 0000000000000000000000000000000000000000..2d4023e12e6914230728fb4372fbb0c655862337 GIT binary patch literal 3378 zcmb`~S3Da~`v>qOVpBwjSwYmOEvT8;t9DzpirTxVRV!kJs-i85+I!XB)l#d(s+esl zYLB*x&>H{z@7~+@^La1M^SwF0b9Fw?b55d(kq$i#2MquKpx4vYG$WZxTD4RZq-s}m zGD-p%V5XxEs2k_n1_0>x^fcA(gaG$#L%p~x*solkH_UbQI12Wf8kH6bkIkf_r}>e0 zJQh&^SvWZkeWz%$3R|UX5{niASAr7#TbM42Q%&OJ5=B}>3K5kc7O;q0i77QF3DLG`q2Fdv-BJA29CGPsg85R-zfjh~{_I8<4*NE#R_)On_409yTD$3Amawe3G?0K`Sh0IaCg-~IX3=Av{{ zpoRxn3Vx~dn-vjtOa;|WphqaSqUc|1gaK*Dao%V87h5JN>`W%*v>$a;%7QNEAKkb6 z%{1*NmVw!`vjYup;%{|+PryinL~PhG=k_S%asx}Y>WMIO;jeBj6RuG-@aGw%{&+MW zMILua1VF>{Dy40+Sj9Ua9{V+udQv%3s-A{pEWaOw4|7K`ryDnl2liKtZ<#S1^oq+e zG#D>$#!=VJ72c*T3B+SfbmU9y7U|DuPv=s2QI9wpDNoQ9wPf=V#$>x@!48>8F`*Ib zI%8EWAvc|#a{-2*<@ib43Gu_V)knV(Ib`YyP0u-Vlh5}Ypwq(1#7Kbcjv1xC?arVv z$4UKFUj(!5&N@)WXoJ?dQ&L;~@$uN?qAcg&0~M+>gH2w73T5_e6jvWDYD+=KB{SRY zZN-;8vm8g3-;I$b`e=+NnlTamc%1@gBx%Mqs($cI9_~M;Z>%8QML?Zj%l7G7R#8tYMm{=IiPK8`evi0%q($7M%q9^EXi|$WUNim)D20 z#)-O>EYXWT--4`(IRf@%Rb2NgkqjqlYbx_>OFmrtHIFifQD*U|FXqt%<)hgE*n2E@ z#vQiKhq!Y0kK6^z^;1HnxANkSmblx$D~!5De3m$f#b1{5s)77*(wkmh%^M;T> z!4&s$%-03xyKb?r#JdBbOug5d2Hqb@HhVdAw6tneG|la`CX*XW(D^l7a}HX2 zT4}1GtZ034u~__J{Hhss=!p~Unaw5dz^yfF$?!JJY%=;BrSM#EmgHZoH*Y(4RvOX9 z?uv_QzO{|njQVB5e!a{!cDvdKi!^$bBOf(>K1xi27aORw!)PodiX05J+p?9;e20no z(ethc#1T4+T~lqe7q{+H?Prc$gPpY39Swg*^s$k#Zx${9#pT2gC6fAX}y5!;0u;nTLWT`Ymt@qfB8|ZA7+V86d9U6oa zu+tk4qGlsU780XYayEueTNBXlBO~0yThBkbbnn4Ns46f+3RxlZ7H+G=a7s90{v7Z; zQ&TW#-5F-sae*zg@v(}SE3^#Yg&M!SUIEVz*$L39B9N{q-SNEOK{O%2cop>Lyc$@NS|7$;CXPOXW~5-2s*ySe%fo!U}$2X`oop6NkRuBPrmhR{pwm! zlZA2bR;7i>ZHv$qmufC1??&ek?!*#UYW!OyZenPY@1(XCI*yHhi^0ittk-#hIJh}tfBbT8+mjnL6zycO+NhI8&2^)B2R3UzW`5X~B+dLW zrx)@RoB#xB{-BpzW6~w-fkb70`a4wmLndVWD2fmAKTcECUeYmxKGA@nc=-4nI1OZXYujm zKW36gN2Y#s%>8OHQmD3WS(AL1_BJRf{s8A@E|w62$8$hZGiAhYG9E5CuqmGCR9nlg z-G7oXQ423Jl#N)IlnLlg-8xRLW~F-F8(b)vhiw&TQ)453@Q71BNTlb9VjqkjpVjXZ zd!U))p&+jyv%77L{V81cUS;Z$<#KN>XL$_Fs8h*J_1*i7iHzU)v-#ZJ!q8bWT=Nko zUZ$Dv%WXqjEdINcE|I6!H~v;sK%ffW;vMhO;w)VR&9?xU!_r^YUtBHdNPN4CdRz;x zlGc|EB~yC5(}RlxOJWtB;C>ey<+8|g zo3iu}etXeRga+4pQWT2K{{*}D3lE`M_S3VJ^b(IR5Y3j ziT%(#eQFr&>sjJ8Qq2fTIN5JJinoFr+!y*R4nn}YbWIfvz`E#+dXo}cl0j)jk26Sb zSy6{V-7b=Qd|KP0OmLuOpL$vl$px*X&z5{>P-AQy-~Rvm6k6J(i2*xN(`qehk%S5B zyCwpthas#<%}+^+o4p)|03oRYqEL4jN!t>kHv*vP>q1REXe?PM0n|~N zhk0oLqM@4d>0qxAui?^c>x8}S`sAN~-d@H!%s^nNdI2tBd>z@Y4muQXW1Xxl73BW33;%f_zIMj7Z8)va#v|IvUeBIW4-I<3 zALEXIv)_lzYeP~${1~?9pw^|x0Jo-r5t0hhS)}$AEfDRE08-yhp({(n{CBb36JeAYAqWynWjR(6;@MPVl=|(G7cG_=HGk7ohFX`J<01eH t{=sviPq+;-!)jmU!hvTA?;x^Q46^n(?fN;WH|Y}u(9<%~tW&qg{vUQ5FKPe) literal 0 HcmV?d00001 diff --git a/1-js/2-first-steps/08-type-conversions/object-user@2x.png b/1-js/2-first-steps/08-type-conversions/object-user@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a3ce20edc5c0cd6c6b41783efd3478636b3d0099 GIT binary patch literal 7810 zcmeHMWmJ?=x1Jdg7(iMOBnFT!DJdzD?q+C|5Ri~=21E>`TL}?{kZwd|1f)x1L~`hE zfq|j!>-XLJ|GR75d)NK({dm{=uKk|a=Q;cAy`Qt+=;^55BxWE6fj~Fa)gBpuKwuc~ zm=h5Il2&O17w`gm8>l`6RSYq1fI!R-)E_At1%P+5p(z~3f!(OaqpeVej0k$a2=EU{ zenIXgP0M>fZkv)u>MO-T8SyQt@^h%!E3)v#2q@#=Lj|LF1=tM`ha4 z+7dK71%+Ow%~;G<;*O7kXZKFN8e>~O+hmXZ*_>@Yp541@4Z1G*T)A7WWh~GR0TU^F z2S=2>xbI8_p+G1ofWV6i2oQc2r2--=ugH$*ui*Coz5qrJ5ryc^gq2K^K})~kIMy1+ z*(K|{N;op06+h_pB421uz~*JZ_&r#n1r~fNEf844({qCXKZFYbI%8(Nc%cvpg(*PE z1g%~m_V6iS81|@e3blJ+eD1b3q$|aKHfR_OkJGDg>Z$1r7)<3-ee6u3Q*C?FN{Qd& z_1Z-CS~g9f%T=&~kZ6I%!!pz@R`Z?>`wJTiH83#54aLG3iv3g&WZBhzp9I1KLx7O5 z9v@0bE0qEwB$hNx5q1Ng;v)@yrr^WxrVyfp%EUGyq5=d6k`f6UQzkmq0D%w1MNV%- z&`>BK3@GfIiNH31x~(b%C|CjnLZn9=sYS;+&j+k;qGz5C-vB^eLos244L^hfSRVuZ zMWg~T5ln%HNW>}%Q3OWs4#aWTsx28+(}7$=zX{rv~qW&uC($ zZ3@GVSV(?wB@d3HGvGU+m-I=!Ls8E+Pd?B-D*{2}r~yNHr}JE+@anwlXKnidSO0uq zZgS2<3p;;lxxFdN-AObdp-um^gr={(lN)s|#eNQ8Zg#KxrX|!JLiqRjlZQ1i^mH0m z#Y>MIhkZ_bq#F0YcKU(Sg`U~Bh)#77!3xYO#Wmi+>&6qp!|7Tc;iun5H2lz;RZSw& zj1@%=NNHit6>V~L_^eR>(SRd#f|<_%rn!DD4A|H0yb#lMW5-J4g`nEh%^v|xJY%&@ zW-o6gSBXef)I{Z`Z`fd1(P!!pp|w#@zB+hy92?-u`>3o>bzdhrJzt|5s6{;W_u6dL zapUm_scM)ys%<%2@U(Cr9Ju^g1(JIFuBv;FcSGCpd~3gWj=Cz5J-I%CXI|_| z6tp~XH8Ytz$9yxf z+>?{F?T07bNa>a*icG{al=I99GAA(&Gr?0|kpWm;bn?)Wfk3*$;;QQ!n&qp;>~OJ# z$hXi@>?*2^Pkq-V@VpBVvzsTkwI#C@IltF#!XNK`#=p1_st_Yy$^zjV6&si8Q9HLL) z4Ldrs!V>4pjVGv7emmzeOU~*rjLuGY(uE2_`tJM8IdE^K72SpJ>;A+qnO60vb*>+! z$fWm$j~t+Tmzh4<`-jmx+8C_7MxE2{bpem&Z;I$wFNqRfDVBUOGA5r&Wo|L$?T|q> zTgWc7td05AzxBn#&|El{%L zBfrt7(qZ)B{&k8U993S{6^%QFGd+J`^Gc z#G;Vb5Aj$&f6YnTJbhZFT=b!cVcgj$g%&*Ofmbp##4!0U^@uHkKlW_i3+WL#pmL7#)N;weGD;P~V)P>Q0Oh#7_0uh#0Qah+p33x!^eyLX;YUC_Owd3nVs(_!(%_Qd_8IYLvvraY}m&w>)t%9cmEGLZO1uJ|m z28|jpxgbfEJ(g^quR@oe`x!6h@`?${*c3>9b{Zf+osp9*iM<~x_4B{Qw8bq+T$J|Q zET8;+-rt*xZTehjUoJ4ov5L1DcIGVdd?~f9iuSUm+x9_5bIOj?F)97!CKsM)>SS%+ zdu_QT_U~p@r)GER#g1bvkTsgI2q(A#Y)t-k+6Fxyt<^Z=ce{t&RDF`D877OE+z#CG+MuKdl*#YO2V#CuE1l z)`yjQce!#I`BmSb$g#XM*R>sna!x}K1 zmX`9y!dI^ELN>R5x-+;x+#1@{GSNp4^RbJj+oU@A_58qA5KD=fkDRY74-3LSXzPdX znPVScwk-l#+cKzGJsFqtvelBvS~;INt-tuWR_3nt$R0TPt@OG2)=eXEoE54;O}Bfh zPwCA|x|WB7cghRxjbp+@Rrc--CG>u{md)Ve4qvWTl)C<*3j)8*4eS@taXW3$n(?VO zD&n-5QA5CwC>DX%_ynd8WC3A<8~zzeML7o%QLal-Q<7*?CH%#=`PMY0+o@ z;nZ4MAS>baTP_zjYuV}+xyrTiDEE5nx{(rsfwQEvjtwUs`pI@_4swvbn_Ef_O_OWj8&WwjjB?^;mhN@-g#+y;=hSowqq@56M3du=u?@YCXQJ zw>mAO{0V<}EO$DUWGv)kfA9)`P?!IqF0V|(%Pk!1m$1usG0pEXu8xIX9B%)dOZuSA zghlN=so5e~>s{7$*OM^9ChwY}q-N4@r5=pJ+jWPb-sUw?*;K*!J>6>PZ*#1-Ev19W z^QEPPm)zV1p9OslTQgQ3BrD##gVaVGX)hoCQbisfQNNAtqoQ@JjpEfbK|9Gi4^rU* zEG71xch%gh64@m1k7yX{k@p2kudIU!P4@G7(;wAQY>bEGGTcGpa|d`_)G-uiCh@3p zd3?FAhD_!tV-m>5_L|)zf072T_Lr15aVUD<=y>u@4Hc;(gd>#j1$;I3u#2$ci`!9E z)S;nwx(Bo0;CoHnU^O-7j3A!djD53h-#2d6tI2 z79EWXm;tpbaxA^Lg+_K?B+lUE^cd3K?A>;RlFJvaNW>IG5+2={Rv+urG3p2-Id=-ECW^-5`BntJ; zpV=hLd=^)PTMwSkoc}^;NWYKUVu36>_Ye;Ue_8&;$S+$N`hiC00mo6zT78jbMH@VB zDD4=zOlT75;=b>ez!5U6%5lBD_9o1x#X6EdFNl*D<(J(D3*+bha4{MCDVN{rAO@6f z8`jBw#Oc32;*!yJYXLi@;kV*KfAN!}?R)>>6Y|g76T7zUn2R*_vfFStVBPfZkZ zBeO&TP=mo;zn^Mz!xD|;k72=Y!vDig7GS5KKvEUf_R%`>EbERV)PuMoo#mU&?7+k@ zQOS1R5Y;c)WqO*!ctc1QSgOQRlOIgT@^egFj$5!zU=mxuoiherI}@ zpS~BG1tD8Fkn#atqgrK7fVC6U=9D+H*=?1+1lTe1->EeAP&yg8km+d98EqmwT!Vau zJ>N8>hGXQQjwG=eSsOKm#c;gzZrIe_@wnR3&-}0HGv3HupmqN#P6xQSWDPy1>mXz);R)zuI5J&oNfO-9i`zZ*yc1>H=Ia`B~DPiHLZQP7hlKkQqP4m*&E9)Az zTd?_mk_aF^pLTeVbqS&yjQwtE9?VU<*n9{(k(g~KAUah=Xx_ViOchW-s8gc=+rXE^ z+e8peh&*PR=LM+yYY@afs$Y90FQ%1#=wz)6&-|r=7?4aoZEA26PhQ$=a(jLIAH2-@ z^$Bhf`{01fuavBTciq3Td<&&x zldKO32(Y3AAKrbCsilG=57Xc0N`g0-nl}-5w_0`GzZN+yH7V_HSXqkmJQU{b$3ns8 zax$*Ljx~XkTNx6c`^%O1C&wS3Jl!#JbSXYvPWF>>-TY`84sRP zsd?$PVtJfqhpzU!zTavhKUBNJ=ix%hyP;(9+j>76eD7qpelMvf+QdX(#rpJ(>O+ij z1pD^m1a@ZF4tNEv@XpmS;BM93WOt=TbO}ioDO-^{%O>XaRk=_5s4%2Jh}BQ7x|%wp zVS8zQq0+!NJ-p+~O0?0P7q3t?$D29msN_I}BahBs4vm3Z<$EKn5Tn$hM)_Zq3Kq(_ zd(*13cjr*(O}B|Li2~mb*$v;F11ZNA^TS2i!kiRk9wMT1r`V9AM~7?+8`iR=adESv zbZ!mP>U45npVnIG#GXu`=r5-a0uQVaK3%RZUIR|i{fFiEeCBITT%EXprc0G`6EBAa zr=F!7)?OZas9r~hShdi8EO2PqB#(S%S9RsezXkkld?Fa)H{$p;i*_2bHjvQ>NvV4` zkwd6f5o|mBsRsp2Hmmbxe^U9wj+ePlc)aKnYhpbrQR`r47~0^%*?`V%chX~Q@9!9e zJn1XrSYgrCJP?P_5_;X1ht6MuH?D2~=pQ`YkpJ&kj(Lp3-9Ju&+rgY^x8!fSshPO zP4%FEv9nZP;_tXo?ku)XTk4JjUqDFKCG<801I8;pr8}QxvU2)1CdflnqDAPHp%1H9 zHoZ5$!bVSkxJ*dhY21S&JYODKD-G*uvZ*RD7QNcmN5D~8UvD0ICw1#%oqY?fOh{pO zPSOHq4o20vl2}vXwsl`RG{Vq_(kGMNn^VELFF?R|oyOlS(J8Ffn%D3o=jLcbowl0{ z51@BULFqsSHCV%YW^R3_~L6Il)$G@V? zxJXCnE19NcgqRqkL&vZk=wg#2Qp6=;Huo&w1cSJ6{U3kcTEACX@p8^}x%w+gI&S6C zS>{X2cIC#dWXYDMthB?Avs2^->4lP?x`63TsC%7ALPyIv(||9iJd8No8uqZ2D>JclJjpBG@K}3RuIx%T+33oK5s#8L!R8 zE&S4&|J#p{MRV7=eqG7Qo08uq$-h${mbpbIv`+#9G&!BC@ zTBV^qQJMnr-HWIgQ*m{33*$wjX%8{#4=9nL)jy5ZCQ^WLLU0m{=#1*ZVX#}%YEnkC zswhyvFel1793olu6|WKf7+Ai4<8M&|4u#|FTtZQS1A1KOv$zbS9gF;Obz-a+o7)-IB3Gi}npZ%KdnT4ah{2kC v$-#|)R*e_VOpublMj(CR!whkUUdT_P1H{Y4< 5) { @@ -264,14 +258,14 @@ if (i > 5) { } ``` -...And rewrote it using a question mark: +...And rewrite it using a question mark: ```js no-beautify (i > 5) ? alert(i) : *!*continue*/!*; // continue not allowed here ``` -...Then it won't work. The code like this will give a syntax error: +...Then it stops working. The code like this will give a syntax error: That's just another reason not to use a question mark operator `'?'` instead of `if`. @@ -290,7 +284,7 @@ for (let i = 0; i < 3; i++) { let input = prompt(`Value at coords (${i},${j})`, ''); - // what if I want to exit from here? + // what if I want to exit from here to Done (below)? } } @@ -355,15 +349,97 @@ label: for(...) The call to a `break/continue` is only possible from inside the loop, and the label must be somewhere upwards from the directive. ```` +## The "for..in" loop + +To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we've studied before. + +The syntax: + +```js +for(key in object) { + // executes the body for each key among object properties +} +``` + +For instance, let's output all properties of `user`: + +```js run +let user = { + name: "John", + age: 30, + isAdmin: true +}; + +for(let key in user) { + // keys + alert( key ); // name, age, 30 + // values for the keys + alert( user[key] ); // John, 30, true +} +``` + +Note that all "for" constructs allow to declare the looping variable inside the loop, like `let key` here. The name "key" for the variable is not mandatory, we could use any variable name here, usually "key" or "prop" names are used for such iterations. + + +## The "for..of" loop + +And the third (the last one) kind of the `for` loop. Again it has a totally different meaning from what we've seen before. + +This form iterates over arrays. + +Actually, we can do it with the `for(;;)` loop: + +```js run +let fruits = ["Apple", "Orange", "Plum"]; + +// iterates over all elements: +// i is the number of the current element +// fruits[i] is the value of the current element +for(let i = 0; i < fruits.length; i++) { + alert( fruits[i] ); // Apple, then Orange, then Plum +} +``` + +The "generic" `for(;;)` loop works well even in most outdated browsers. + +The `for..of` syntax is shorter: + +```js run +let fruits = ["Apple", "Orange", "Plum"]; + +// iterates over all elements: +// fruit is the value of the current element +for(let fruit of fruits) { + alert( fruit ); +} +``` + +The `for..of` doesn't give access to the number of the current element, just its value, but in most cases that's enough. + +````smart header="Iterables" +Later we'll learn the concept of *iterable* objects in Javascript. An iterable object must implement special functionality that allows to use `for..of` on it. + +There are many iterable objects. For instance, a string is iterable, `for..of` will list characters in the example: + +```js run +for(let char of "test") { + alert( char ); t, then e, then s, then t +} +``` +```` + + ## Summary -There are 3 types of loops in JavaScript: +There are 5 types of loops in JavaScript: - `while` -- the condition is checked before each iteration. - `do..while` -- the condition is checked after each iteration. -- `for` -- the condition is checked before each iteration, additional settings available. +- `for(;;)` -- the condition is checked before each iteration, additional settings available. +- `for(key in obj)` -- to iterate over object properties. +- `for(item of array)` -- to iterate over array items. -To make in "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive. +To make an "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive. If we don't want to do anything more on this iteration and would like to forward on to the next one -- the `continue` directive does it. diff --git a/1-js/2-first-steps/14-switch/1-rewrite-switch-if-else/solution.md b/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md similarity index 100% rename from 1-js/2-first-steps/14-switch/1-rewrite-switch-if-else/solution.md rename to 1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md diff --git a/1-js/2-first-steps/14-switch/1-rewrite-switch-if-else/task.md b/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md similarity index 100% rename from 1-js/2-first-steps/14-switch/1-rewrite-switch-if-else/task.md rename to 1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md diff --git a/1-js/2-first-steps/14-switch/2-rewrite-if-switch/solution.md b/1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md similarity index 100% rename from 1-js/2-first-steps/14-switch/2-rewrite-if-switch/solution.md rename to 1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md diff --git a/1-js/2-first-steps/14-switch/2-rewrite-if-switch/task.md b/1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md similarity index 100% rename from 1-js/2-first-steps/14-switch/2-rewrite-if-switch/task.md rename to 1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md diff --git a/1-js/2-first-steps/14-switch/article.md b/1-js/2-first-steps/16-switch/article.md similarity index 100% rename from 1-js/2-first-steps/14-switch/article.md rename to 1-js/2-first-steps/16-switch/article.md diff --git a/1-js/2-first-steps/18-function-basics/1-if-else-required/solution.md b/1-js/2-first-steps/19-function-basics/1-if-else-required/solution.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/1-if-else-required/solution.md rename to 1-js/2-first-steps/19-function-basics/1-if-else-required/solution.md diff --git a/1-js/2-first-steps/18-function-basics/1-if-else-required/task.md b/1-js/2-first-steps/19-function-basics/1-if-else-required/task.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/1-if-else-required/task.md rename to 1-js/2-first-steps/19-function-basics/1-if-else-required/task.md diff --git a/1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/solution.md b/1-js/2-first-steps/19-function-basics/2-rewrite-function-question-or/solution.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/solution.md rename to 1-js/2-first-steps/19-function-basics/2-rewrite-function-question-or/solution.md diff --git a/1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/task.md b/1-js/2-first-steps/19-function-basics/2-rewrite-function-question-or/task.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/task.md rename to 1-js/2-first-steps/19-function-basics/2-rewrite-function-question-or/task.md diff --git a/1-js/2-first-steps/18-function-basics/3-min/solution.md b/1-js/2-first-steps/19-function-basics/3-min/solution.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/3-min/solution.md rename to 1-js/2-first-steps/19-function-basics/3-min/solution.md diff --git a/1-js/2-first-steps/18-function-basics/3-min/task.md b/1-js/2-first-steps/19-function-basics/3-min/task.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/3-min/task.md rename to 1-js/2-first-steps/19-function-basics/3-min/task.md diff --git a/1-js/2-first-steps/18-function-basics/4-pow/solution.md b/1-js/2-first-steps/19-function-basics/4-pow/solution.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/4-pow/solution.md rename to 1-js/2-first-steps/19-function-basics/4-pow/solution.md diff --git a/1-js/2-first-steps/18-function-basics/4-pow/task.md b/1-js/2-first-steps/19-function-basics/4-pow/task.md similarity index 100% rename from 1-js/2-first-steps/18-function-basics/4-pow/task.md rename to 1-js/2-first-steps/19-function-basics/4-pow/task.md diff --git a/1-js/2-first-steps/18-function-basics/article.md b/1-js/2-first-steps/19-function-basics/article.md similarity index 87% rename from 1-js/2-first-steps/18-function-basics/article.md rename to 1-js/2-first-steps/19-function-basics/article.md index 2b0884b1..9c8e51ab 100644 --- a/1-js/2-first-steps/18-function-basics/article.md +++ b/1-js/2-first-steps/19-function-basics/article.md @@ -176,61 +176,6 @@ showMessage(from, "Hello"); // *Ann*: Hello alert( from ); // Ann ``` -### Default values - -A function can be called with any number of arguments. If a parameter is not provided, but listed in the declaration, then its value becomes `undefined`. - -For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument: - -```js -showMessage("Ann"); -``` - -That's not an error. Such call would output `"Ann: undefined"`, because `text === undefined`. - -If we want to track when the function is called with a single argument and use a "default" value in this case, then we can check if `text` is defined, like here: - -```js run -function showMessage(from, text) { -*!* - if (text === undefined) { - text = 'no text given'; - } -*/!* - - alert( from + ": " + text ); -} - -showMessage("Ann", "Hello!"); // Ann: Hello! -*!* -showMessage("Ann"); // Ann: no text given -*/!* -``` - -There are also other ways to supply "default values" for missing arguments: - -- Use operator `||`: - - ```js - function showMessage(from, text) { - text = text || 'no text given'; - ... - } - ``` - - This way is shorter, but the argument is considered missing also if it's falsy, like an empty line, `0` or `null`. -- ES-2015 introduced a neater syntax for default values: - - ```js run - function showMessage(from, *!*text = 'no text given'*/!*) { - alert( from + ": " + text ); - } - - showMessage("Ann"); // Ann: no text given - ``` - - Here `'no text given'` is a string, but it can be any other value or expression, which is only evaluated and assigned if the parameter is missing. - ## Returning a value A function can return a value back into the calling code as the result. diff --git a/1-js/2-first-steps/18-function-basics/function_basics.png b/1-js/2-first-steps/19-function-basics/function_basics.png similarity index 100% rename from 1-js/2-first-steps/18-function-basics/function_basics.png rename to 1-js/2-first-steps/19-function-basics/function_basics.png diff --git a/1-js/2-first-steps/18-function-basics/function_basics@2x.png b/1-js/2-first-steps/19-function-basics/function_basics@2x.png similarity index 100% rename from 1-js/2-first-steps/18-function-basics/function_basics@2x.png rename to 1-js/2-first-steps/19-function-basics/function_basics@2x.png diff --git a/1-js/2-first-steps/20-function-parameters/article.md b/1-js/2-first-steps/20-function-parameters/article.md new file mode 100644 index 00000000..db0969fb --- /dev/null +++ b/1-js/2-first-steps/20-function-parameters/article.md @@ -0,0 +1,555 @@ +# Function parameters + +The syntax of function parameters is very versatile. + +It allows: + +- To specify values if the parameter if missing. +- To gather parameters into an array and deal with it instead of variables. +- To destructurize the object into parameters. +- And more. + +All these features aim to help us in writing good-looking and concise code. + +## Default values + +A function can be called with any number of arguments. If a parameter is not provided, but listed in the declaration, then its value becomes `undefined`. + +For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument: + +```js +showMessage("Ann"); +``` + +That's not an error. Such call would output `"Ann: undefined"`, because `text === undefined`. + +If we want to track when the function is called with a single argument and use a "default" value in this case, then we can check if `text` is defined, like here: + +```js run +function showMessage(from, text) { +*!* + if (text === undefined) { + text = 'no text given'; + } +*/!* + + alert( from + ": " + text ); +} + +showMessage("Ann", "Hello!"); // Ann: Hello! +*!* +showMessage("Ann"); // Ann: no text given +*/!* +``` + +There are also other ways to supply "default values" for missing arguments: + +- Use operator `||`: + + ```js + function showMessage(from, text) { + text = text || 'no text given'; + ... + } + ``` + + This way is shorter, but the argument is considered missing even if it exists, but is falsy, like an empty line, `0` or `null`. + +- Specify the default value after `=`: + + ```js run + function showMessage(from, *!*text = 'no text given'*/!*) { + alert( from + ": " + text ); + } + + showMessage("Ann"); // Ann: no text given + ``` + + Here `'no text given'` is a string, but it can be a more complex expression, which is only evaluated and assigned if the parameter is missing. So, this is also possible: + + ```js run + function showMessage(from, text = anotherFunction()) { + // anotherFunction() is executed if no text given + } + ``` + +## Arbitrary number of arguments + +To support any number of arguments, we can use the rest operator `...`, similar to [destructuring](info:destructuring): + +```js run +function sumAll(...args) { + let sum = 0; + + for(let arg of args) sum += arg; + + return sum; +} + +alert( sumAll(1) ); // 1 +alert( sumAll(1, 2) ); // 3 +alert( sumAll(1, 2, 3) ); // 6 +``` + +We also can put few first arguments into variables and gather only the rest: + +```js run +function showName(firstName, lastName, ...rest) { + alert( firstName + ' ' + lastName ); // Julius Caesar + + // the rest = ["Consul", "of the Roman Republic"] + alert( rest[0] ); // Consul + alert( rest[1] ); // of the Roman Republic +} + +showName("Julius", "Caesar", "Consul", "of the Roman Republic"); +``` + +````warn header="The rest operator … must be at the end" +The rest operator `…` gathers all remaining arguments, so the following has no sense: + +```js +function f(arg1, ...rest, arg2) { // arg2 after ...rest ?! + // error +} +``` + +The `...rest` must always be the last. +```` + +````smart header="The `arguments` variable" + +In old times, there were no rest operator. But there was a special variable named `arguments` that contained all arguments by their index. It is still supported and can be used like this: + +```js run +function showName() { + alert( arguments[0] ); + alert( arguments[1] ); + alert( arguments.length ); +} + +// shows: Julius, Caesar, 2 +showName("Julius", "Caesar"); + +// shows: Ilya, undefined, 1 +showName("Ilya"); +``` + +The downside is that `arguments` looks like an array, but it's not. It does not support many useful array features. It only exists for backwards compatibility. The rest operator is better. +```` + +## Destructuring in parameters + +There are times when a function may have many parameters. Imagine a function that creates a menu. It may have a width, a height, a title, items list and so on. + +Here's a bad way to write such function: + +```js +function showMenu(title = "Untitled", width = 200, height = 100, items = []) { + // ... +} +``` + +The real-life problem is how to remember the order of arguments. Usually IDEs try to help us, especially if the code is well-documented, but still... Another problem is how to call a function when most parameters are ok by default. + +Like this? + +```js +showMenu("My Menu", undefined, undefined, ["Item1", "Item2"]) +``` + +That's ugly. And becomes unreadable if we have not 4 but 10 parameters. + +Destructuring comes to the rescue! + +We can pass parameters as an object, and the function immediately destructurizes them into variables: + +```js run +let options = { + title: "My menu", + items: ["Item1", "Item2"] +}; + +*!* +function showMenu({title = "Untitled", width = 200, height = 100, items = []}) { +*/!* + alert( title + ' ' + width + ' ' + height ); // My Menu 100 200 + alert( items ); // Item1, Item2 +} + +showMenu(options); +``` + +We can also use the more complex destructuring with nestings and colon mappings: + +```js run +let options = { + title: "My menu", + items: ["Item1", "Item2"] +}; + +*!* +function showMenu({ + title = "Untitled", + width:w = 100, // width goes to w + height:h = 200, // height goes to h + items: [item1, item2] // items first element goes to item1, second to item2 +}) { +*/!* + alert( title + ' ' + w + ' ' + h ); // My Menu 100 200 + alert( item1 ); // Item1 + alert( item2 ); // Item2 +} + +showMenu(options); +``` + +The syntax is the same as for a destructuring assignment: +```js +function({ + incoming property: parameterName = defaultValue + ... +}) +``` + +Please note that such destructuring assumes that `showMenu()` does have an argument. If we want all values by default, then we should specify an empty object: + +```js +showMenu({}); + +// that would give an error +showMenu(); +``` + +We can fix this of course, by making an empty object a value by default for the whole destructuring thing: + + +```js run +// simplified parameters a bit for clarity +function showMenu(*!*{ title="Menu", width=100, height=200 } = {}*/!*) { + alert( title + ' ' + width + ' ' + height ); +} + +showMenu(); // Menu 100 200 +``` + +In the code above, the whole arguments object is `{}` by default, so there's always something to destructurize. + +## The spread operator + +// TODO!!! + +Выше мы увидели использование `...` для чтения параметров в объявлении функции. Но этот же оператор можно использовать и при вызове функции, для передачи массива параметров как списка, например: + +```js run +'use strict'; + +let numbers = [2, 3, 15]; + +// Оператор ... в вызове передаст массив как список аргументов +// Этот вызов аналогичен Math.max(2, 3, 15) +let max = Math.max(*!*...numbers*/!*); + +alert( max ); // 15 +``` + +Формально говоря, эти два вызова делают одно и то же: + +```js +Math.max(...numbers); +Math.max.apply(Math, numbers); +``` + +Похоже, что первый -- короче и красивее. + +## Деструктуризация в параметрах + + +## Имя "name" + +В свойстве `name` у функции находится её имя. + +Например: + +```js run +'use strict'; + +function f() {} // f.name == "f" + +let g = function g() {}; // g.name == "g" + +alert(f.name + ' ' + g.name) // f g +``` + +В примере выше показаны Function Declaration и Named Function Expression. В синтаксисе выше довольно очевидно, что у этих функций есть имя `name`. В конце концов, оно указано в объявлении. + +Но современный JavaScript идёт дальше, он старается даже анонимным функциям дать разумные имена. + +Например, при создании анонимной функции с одновременной записью в переменную или свойство -- её имя равно названию переменной (или свойства). + +Например: + +```js +'use strict'; + +// свойство g.name = "g" +let g = function() {}; + +let user = { + // свойство user.sayHi.name == "sayHi" + sayHi: function() {} +}; +``` + +## Функции в блоке + +Объявление функции Function Declaration, сделанное в блоке, видно только в этом блоке. + +Например: + +```js run +'use strict'; + +if (true) { + + sayHi(); // работает + + function sayHi() { + alert("Привет!"); + } + +} +sayHi(); // ошибка, функции не существует +``` + +То есть, иными словами, такое объявление -- ведёт себя в точности как если бы `let sayHi = function() {…}` было сделано в начале блока. + +## Функции через => + +Появился новый синтаксис для задания функций через "стрелку" `=>`. + +Его простейший вариант выглядит так: +```js run +'use strict'; + +*!* +let inc = x => x+1; +*/!* + +alert( inc(1) ); // 2 +``` + +Эти две записи -- примерно аналогичны: + +```js +let inc = x => x+1; + +let inc = function(x) { return x + 1; }; +``` + +Как видно, `"x => x+1"` -- это уже готовая функция. Слева от `=>` находится аргумент, а справа -- выражение, которое нужно вернуть. + +Если аргументов несколько, то нужно обернуть их в скобки, вот так: + +```js run +'use strict'; + +*!* +let sum = (a,b) => a + b; +*/!* + +// аналог с function +// let inc = function(a, b) { return a + b; }; + +alert( sum(1, 2) ); // 3 +``` + +Если нужно задать функцию без аргументов, то также используются скобки, в этом случае -- пустые: + +```js run +'use strict'; + +*!* +// вызов getTime() будет возвращать текущее время +let getTime = () => new Date().getHours() + ':' + new Date().getMinutes(); +*/!* + +alert( getTime() ); // текущее время +``` + +Когда тело функции достаточно большое, то можно его обернуть в фигурные скобки `{…}`: + +```js run +'use strict'; + +*!* +let getTime = () => { + let date = new Date(); + let hours = date.getHours(); + let minutes = date.getMinutes(); + return hourse + ':' + minutes; +}; +*/!* + +alert( getTime() ); // текущее время +``` + +Заметим, что как только тело функции оборачивается в `{…}`, то её результат уже не возвращается автоматически. Такая функция должна делать явный `return`, как в примере выше, если конечно хочет что-либо возвратить. + +Функции-стрелки очень удобны в качестве коллбеков, например: + +```js run +`use strict`; + +let arr = [5, 8, 3]; + +*!* +let sorted = arr.sort( (a,b) => a - b ); +*/!* + +alert(sorted); // 3, 5, 8 +``` + +Такая запись -- коротка и понятна. Далее мы познакомимся с дополнительными преимуществами использования функций-стрелок для этой цели. + +## Функции-стрелки не имеют своего this + +Внутри функций-стрелок -- тот же `this`, что и снаружи. + +Это очень удобно в обработчиках событий и коллбэках, например: + +```js run +'use strict'; + +let group = { + title: "Наш курс", + students: ["Вася", "Петя", "Даша"], + + showList: function() { +*!* + this.students.forEach( + student => alert(this.title + ': ' + student) + ) +*/!* + } +} + +group.showList(); +// Наш курс: Вася +// Наш курс: Петя +// Наш курс: Даша +``` + +Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` в коллбэке -- тот же, что и во внешней функции `showList`. То есть, в данном случае -- `group.title`. + +Если бы в `forEach` вместо функции-стрелки была обычная функция, то была бы ошибка: + +```js run +'use strict'; + +let group = { + title: "Наш курс", + students: ["Вася", "Петя", "Даша"], + + showList: function() { +*!* + this.students.forEach(function(student) { + alert(this.title + ': ' + student); // будет ошибка + }) +*/!* + } +} + +group.showList(); +``` + +При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`. То есть, `this` внутри `forEach` будет `undefined`. + +```warn header="Функции стрелки нельзя запускать с `new`" +Отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть нельзя вызывать через `new`. +``` + +```smart header="=> это не то же самое, что `.bind(this)`" +Есть тонкое различие между функцией стрелкой `=>` и обычной функцией, у которой вызван `.bind(this)`: + +- Вызовом `.bind(this)` мы передаём текущий `this`, привязывая его к функции. +- При `=>` привязки не происходит, так как функция стрелка вообще не имеет контекста `this`. Поиск `this` в ней осуществляется так же, как и поиск обычной переменной, то есть, выше в замыкании. До появления стандарта ES-2015 такое было невозможно. +``` + +## Функции-стрелки не имеют своего arguments + +В качестве `arguments` используются аргументы внешней "обычной" функции. + +Например: + +```js run +'use strict'; + +function f() { + let showArg = () => alert(arguments[0]); + showArg(); +} + +f(1); // 1 +``` + +Вызов `showArg()` выведет `1`, получив его из аргументов функции `f`. Функция-стрелка здесь вызвана без параметров, но это не важно: `arguments` всегда берутся из внешней "обычной" функции. + +Сохранение внешнего `this` и `arguments` удобно использовать для форвардинга вызовов и создания декораторов. + +Например, декоратор `defer(f, ms)` ниже получает функцию `f` и возвращает обёртку вокруг неё, откладывающую вызов на `ms` миллисекунд: + +```js run +'use strict'; + +*!* +function defer(f, ms) { + return function() { + setTimeout(() => f.apply(this, arguments), ms) + } +} +*/!* + +function sayHi(who) { + alert('Привет, ' + who); +} + +let sayHiDeferred = defer(sayHi, 2000); +sayHiDeferred("Вася"); // Привет, Вася через 2 секунды +``` + +Аналогичная реализация без функции-стрелки выглядела бы так: + +```js +function defer(f, ms) { + return function() { +*!* + let args = arguments; + let ctx = this; +*/!* + setTimeout(function() { + return f.apply(ctx, args); + }, ms); + } +} +``` + +В этом коде пришлось создавать дополнительные переменные `args` и `ctx` для передачи внешних аргументов и контекста через замыкание. + +## Итого + +Основные улучшения в функциях: + +- Можно задавать параметры по умолчанию, а также использовать деструктуризацию для чтения приходящего объекта. +- Оператор spread (троеточие) в объявлении позволяет функции получать оставшиеся аргументы в массив: `function f(arg1, arg2, ...rest)`. +- Тот же оператор spread в вызове функции позволяет передать её массив как список аргументов (вместо `apply`). +- У функции есть свойство `name`, оно содержит имя, указанное при объявлении функции, либо, если его нет, то имя свойства или переменную, в которую она записана. Есть и некоторые другие ситуации, в которых интерпретатор подставляет "самое подходящее" имя. +- Объявление Function Declaration в блоке `{...}` видно только в этом блоке. +- Появились функции-стрелки: + - Без фигурных скобок возвращают выражение `expr`: `(args) => expr`. + - С фигурными скобками требуют явного `return`. + - Не имеют своих `this` и `arguments`, при обращении получают их из окружающего контекста. + - Не могут быть использованы как конструкторы, с `new`. + + + diff --git a/1-js/2-first-steps/19-function-expression/article.md b/1-js/2-first-steps/21-function-expression/article.md similarity index 100% rename from 1-js/2-first-steps/19-function-expression/article.md rename to 1-js/2-first-steps/21-function-expression/article.md diff --git a/1-js/2-first-steps/20-primitives-methods/1-string-new-property/solution.md b/1-js/2-first-steps/22-primitives-methods/1-string-new-property/solution.md similarity index 100% rename from 1-js/2-first-steps/20-primitives-methods/1-string-new-property/solution.md rename to 1-js/2-first-steps/22-primitives-methods/1-string-new-property/solution.md diff --git a/1-js/2-first-steps/20-primitives-methods/1-string-new-property/task.md b/1-js/2-first-steps/22-primitives-methods/1-string-new-property/task.md similarity index 100% rename from 1-js/2-first-steps/20-primitives-methods/1-string-new-property/task.md rename to 1-js/2-first-steps/22-primitives-methods/1-string-new-property/task.md diff --git a/1-js/2-first-steps/20-primitives-methods/article.md b/1-js/2-first-steps/22-primitives-methods/article.md similarity index 100% rename from 1-js/2-first-steps/20-primitives-methods/article.md rename to 1-js/2-first-steps/22-primitives-methods/article.md diff --git a/1-js/2-first-steps/22-javascript-specials/article.md b/1-js/2-first-steps/23-javascript-specials/article.md similarity index 100% rename from 1-js/2-first-steps/22-javascript-specials/article.md rename to 1-js/2-first-steps/23-javascript-specials/article.md diff --git a/1-js/4-data-structures/3-string/article.md b/1-js/4-data-structures/3-string/article.md index 4b382158..d812af1a 100644 --- a/1-js/4-data-structures/3-string/article.md +++ b/1-js/4-data-structures/3-string/article.md @@ -49,6 +49,30 @@ let guestList = "Guests: // Error: Unexpected token ILLEGAL Single and double quotes come from ancient times of language creation, and the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile. +Backticks also allow to specify a "template function" at the beginning. + +Its name is put before the first backtick. Then it receives the string and embedded expressions can can process them. + +The syntax is: +```js run +function love(string, value1, value2) { + alert( string[0] ); // Hello + alert( string[1] ); // and + alert( value1 ); // Ilya + alert( value2 ); // Julia + return value1 + ' ♥ ' + value2; +} + +let mom = "Julia"; +let dad = "Ilya"; + +let str = love`Hello ${mom} and ${dad}`; + +alert(str); // 'Julia ♥ Ilya' +``` + +In the example above, `love` is the name for the function. It is called with an array + ## Special characters It is still possible to create multiline strings with single quotes, using a so-called "newline character" written as `\n`, that denotes a line break: