From 9146d06c82ca7def9e4a0473acccb6b2dba99db0 Mon Sep 17 00:00:00 2001 From: Maksim Litvinov Date: Wed, 27 Dec 2023 14:38:15 +0300 Subject: [PATCH] new structure --- .../10-basics/10-hello-world/ru/EXERCISE.md | 7 + modules/10-basics/10-hello-world/ru/README.md | 9 ++ modules/10-basics/10-hello-world/ru/data.yml | 5 + modules/10-basics/20-comments/ru/EXERCISE.md | 1 + modules/10-basics/20-comments/ru/README.md | 42 ++++++ modules/10-basics/20-comments/ru/data.yml | 22 +++ .../10-basics/40-instructions/ru/EXERCISE.md | 9 ++ .../10-basics/40-instructions/ru/README.md | 27 ++++ modules/10-basics/40-instructions/ru/data.yml | 15 ++ modules/10-basics/45-testing/ru/EXERCISE.md | 7 + modules/10-basics/45-testing/ru/README.md | 35 +++++ modules/10-basics/45-testing/ru/data.yml | 11 ++ .../10-basics/50-syntax-errors/ru/EXERCISE.md | 4 + .../10-basics/50-syntax-errors/ru/README.md | 18 +++ .../10-basics/50-syntax-errors/ru/data.yml | 11 ++ .../20-arithmetics/20-basic/ru/EXERCISE.md | 2 + modules/20-arithmetics/20-basic/ru/README.md | 44 ++++++ modules/20-arithmetics/20-basic/ru/data.yml | 19 +++ .../20-arithmetics/25-operator/ru/EXERCISE.md | 1 + .../20-arithmetics/25-operator/ru/README.md | 22 +++ .../20-arithmetics/25-operator/ru/data.yml | 14 ++ .../27-commutativity/ru/EXERCISE.md | 2 + .../27-commutativity/ru/README.md | 7 + .../27-commutativity/ru/data.yml | 11 ++ .../30-composition/ru/EXERCISE.md | 8 ++ .../30-composition/ru/README.md | 23 +++ .../20-arithmetics/30-composition/ru/data.yml | 6 + .../20-arithmetics/40-priority/ru/EXERCISE.md | 4 + .../20-arithmetics/40-priority/ru/README.md | 32 +++++ .../20-arithmetics/40-priority/ru/data.yml | 10 ++ .../20-arithmetics/50-float/ru/EXERCISE.md | 2 + modules/20-arithmetics/50-float/ru/README.md | 25 ++++ modules/20-arithmetics/50-float/ru/data.yml | 9 ++ .../20-arithmetics/60-infinity/ru/EXERCISE.md | 2 + .../20-arithmetics/60-infinity/ru/README.md | 18 +++ .../20-arithmetics/60-infinity/ru/data.yml | 11 ++ modules/20-arithmetics/70-nan/ru/EXERCISE.md | 2 + modules/20-arithmetics/70-nan/ru/README.md | 15 ++ modules/20-arithmetics/70-nan/ru/data.yml | 4 + .../20-arithmetics/80-linting/ru/EXERCISE.md | 2 + .../20-arithmetics/80-linting/ru/README.md | 38 +++++ modules/20-arithmetics/80-linting/ru/data.yml | 4 + modules/25-strings/10-quotes/ru/EXERCISE.md | 12 ++ modules/25-strings/10-quotes/ru/README.md | 87 ++++++++++++ modules/25-strings/10-quotes/ru/data.yml | 5 + .../15-escape-characters/ru/EXERCISE.md | 9 ++ .../15-escape-characters/ru/README.md | 126 +++++++++++++++++ .../15-escape-characters/ru/data.yml | 13 ++ .../20-string-concatenation/ru/EXERCISE.md | 8 ++ .../20-string-concatenation/ru/README.md | 48 +++++++ .../20-string-concatenation/ru/data.yml | 10 ++ modules/25-strings/30-encoding/ru/EXERCISE.md | 16 +++ modules/25-strings/30-encoding/ru/README.md | 37 +++++ modules/25-strings/30-encoding/ru/data.yml | 9 ++ .../30-variables/10-definition/ru/EXERCISE.md | 2 + .../30-variables/10-definition/ru/README.md | 49 +++++++ .../30-variables/10-definition/ru/data.yml | 9 ++ modules/30-variables/11-change/ru/EXERCISE.md | 2 + modules/30-variables/11-change/ru/README.md | 16 +++ modules/30-variables/11-change/ru/data.yml | 6 + .../13-variables-naming/ru/EXERCISE.md | 2 + .../13-variables-naming/ru/README.md | 36 +++++ .../13-variables-naming/ru/data.yml | 13 ++ modules/30-variables/14-errors/ru/EXERCISE.md | 10 ++ modules/30-variables/14-errors/ru/README.md | 21 +++ modules/30-variables/14-errors/ru/data.yml | 9 ++ .../15-variables-expressions/ru/EXERCISE.md | 13 ++ .../15-variables-expressions/ru/README.md | 70 ++++++++++ .../15-variables-expressions/ru/data.yml | 9 ++ .../18-variable-concatenation/ru/EXERCISE.md | 18 +++ .../18-variable-concatenation/ru/README.md | 28 ++++ .../18-variable-concatenation/ru/data.yml | 13 ++ .../19-naming-style/ru/EXERCISE.md | 4 + .../30-variables/19-naming-style/ru/README.md | 11 ++ .../30-variables/19-naming-style/ru/data.yml | 7 + .../20-magic-numbers/ru/EXERCISE.md | 23 +++ .../20-magic-numbers/ru/README.md | 31 +++++ .../30-variables/20-magic-numbers/ru/data.yml | 5 + .../30-variables/23-constants/ru/EXERCISE.md | 2 + .../30-variables/23-constants/ru/README.md | 42 ++++++ modules/30-variables/23-constants/ru/data.yml | 6 + .../25-interpolation/ru/EXERCISE.md | 6 + .../25-interpolation/ru/README.md | 34 +++++ .../30-variables/25-interpolation/ru/data.yml | 10 ++ .../30-variables/30-symbols/ru/EXERCISE.md | 2 + modules/30-variables/30-symbols/ru/README.md | 50 +++++++ modules/30-variables/30-symbols/ru/data.yml | 7 + .../10-primitive-data-types/ru/EXERCISE.md | 1 + .../10-primitive-data-types/ru/README.md | 33 +++++ .../10-primitive-data-types/ru/data.yml | 18 +++ .../33-data-types/45-undefined/ru/EXERCISE.md | 1 + .../33-data-types/45-undefined/ru/README.md | 35 +++++ .../33-data-types/45-undefined/ru/data.yml | 9 ++ .../47-data-types-immutability/ru/EXERCISE.md | 9 ++ .../47-data-types-immutability/ru/README.md | 20 +++ .../47-data-types-immutability/ru/data.yml | 8 ++ .../50-data-types-weak-typing/ru/EXERCISE.md | 2 + .../50-data-types-weak-typing/ru/README.md | 29 ++++ .../50-data-types-weak-typing/ru/data.yml | 10 ++ .../100-call/ru/EXERCISE.md | 2 + .../100-call/ru/README.md | 64 +++++++++ .../35-calling-functions/100-call/ru/data.yml | 14 ++ .../110-math/ru/EXERCISE.md | 8 ++ .../110-math/ru/README.md | 14 ++ .../35-calling-functions/110-math/ru/data.yml | 14 ++ .../120-function-signature/ru/EXERCISE.md | 6 + .../120-function-signature/ru/README.md | 25 ++++ .../120-function-signature/ru/data.yml | 10 ++ .../ru/EXERCISE.md | 2 + .../ru/README.md | 23 +++ .../ru/data.yml | 8 ++ .../ru/EXERCISE.md | 9 ++ .../ru/README.md | 55 ++++++++ .../ru/data.yml | 6 + .../180-variadic-parameters/ru/EXERCISE.md | 2 + .../180-variadic-parameters/ru/README.md | 18 +++ .../180-variadic-parameters/ru/data.yml | 8 ++ .../270-deterministic/ru/EXERCISE.md | 8 ++ .../270-deterministic/ru/README.md | 22 +++ .../270-deterministic/ru/data.yml | 10 ++ .../350-stdlib/ru/EXERCISE.md | 8 ++ .../350-stdlib/ru/README.md | 14 ++ .../350-stdlib/ru/data.yml | 13 ++ .../100-properties-syntax/ru/EXERCISE.md | 2 + .../100-properties-syntax/ru/README.md | 37 +++++ .../100-properties-syntax/ru/data.yml | 7 + .../200-properties-methods/ru/EXERCISE.md | 1 + .../200-properties-methods/ru/README.md | 39 ++++++ .../200-properties-methods/ru/data.yml | 5 + .../ru/EXERCISE.md | 3 + .../300-properties-immutability/ru/README.md | 27 ++++ .../300-properties-immutability/ru/data.yml | 5 + .../400-properties-expressions/ru/EXERCISE.md | 9 ++ .../400-properties-expressions/ru/README.md | 22 +++ .../400-properties-expressions/ru/data.yml | 9 ++ .../ru/EXERCISE.md | 5 + .../ru/README.md | 50 +++++++ .../ru/data.yml | 6 + .../ru/EXERCISE.md | 8 ++ .../100-define-functions-syntax/ru/README.md | 65 +++++++++ .../100-define-functions-syntax/ru/data.yml | 5 + .../ru/EXERCISE.md | 7 + .../150-define-functions-return/ru/README.md | 116 ++++++++++++++++ .../150-define-functions-return/ru/data.yml | 5 + .../ru/EXERCISE.md | 30 ++++ .../ru/README.md | 104 ++++++++++++++ .../ru/data.yml | 5 + .../ru/EXERCISE.md | 17 +++ .../ru/README.md | 54 ++++++++ .../ru/data.yml | 8 ++ .../ru/EXERCISE.md | 19 +++ .../ru/README.md | 38 +++++ .../ru/data.yml | 4 + modules/45-logic/10-bool-type/ru/EXERCISE.md | 9 ++ modules/45-logic/10-bool-type/ru/README.md | 57 ++++++++ modules/45-logic/10-bool-type/ru/data.yml | 8 ++ modules/45-logic/15-predicates/ru/EXERCISE.md | 9 ++ modules/45-logic/15-predicates/ru/README.md | 33 +++++ modules/45-logic/15-predicates/ru/data.yml | 8 ++ .../ru/EXERCISE.md | 7 + .../20-logic-combine-expressions/ru/README.md | 67 +++++++++ .../20-logic-combine-expressions/ru/data.yml | 9 ++ .../25-logical-operators/ru/EXERCISE.md | 19 +++ .../25-logical-operators/ru/README.md | 99 +++++++++++++ .../45-logic/25-logical-operators/ru/data.yml | 13 ++ .../28-logical-negation/ru/EXERCISE.md | 30 ++++ .../45-logic/28-logical-negation/ru/README.md | 25 ++++ .../45-logic/28-logical-negation/ru/data.yml | 9 ++ .../70-logical-expressions/ru/EXERCISE.md | 18 +++ .../70-logical-expressions/ru/README.md | 131 ++++++++++++++++++ .../70-logical-expressions/ru/data.yml | 7 + modules/48-conditionals/30-if/ru/EXERCISE.md | 7 + modules/48-conditionals/30-if/ru/README.md | 43 ++++++ modules/48-conditionals/30-if/ru/data.yml | 8 ++ .../48-conditionals/40-if-else/ru/EXERCISE.md | 13 ++ .../48-conditionals/40-if-else/ru/README.md | 54 ++++++++ .../48-conditionals/40-if-else/ru/data.yml | 9 ++ .../48-conditionals/50-else-if/ru/EXERCISE.md | 19 +++ .../48-conditionals/50-else-if/ru/README.md | 63 +++++++++ .../48-conditionals/50-else-if/ru/data.yml | 8 ++ .../60-ternary-operator/ru/EXERCISE.md | 27 ++++ .../60-ternary-operator/ru/README.md | 72 ++++++++++ .../60-ternary-operator/ru/data.yml | 10 ++ .../48-conditionals/65-switch/ru/EXERCISE.md | 15 ++ .../48-conditionals/65-switch/ru/README.md | 98 +++++++++++++ modules/48-conditionals/65-switch/ru/data.yml | 5 + modules/50-loops/10-while/ru/EXERCISE.md | 8 ++ modules/50-loops/10-while/ru/README.md | 105 ++++++++++++++ modules/50-loops/10-while/ru/data.yml | 8 ++ .../20-aggregation-numbers/ru/EXERCISE.md | 8 ++ .../20-aggregation-numbers/ru/README.md | 82 +++++++++++ .../20-aggregation-numbers/ru/data.yml | 7 + .../23-aggregation-strings/ru/EXERCISE.md | 8 ++ .../23-aggregation-strings/ru/README.md | 38 +++++ .../23-aggregation-strings/ru/data.yml | 7 + .../25-iteration-over-string/ru/EXERCISE.md | 14 ++ .../25-iteration-over-string/ru/README.md | 26 ++++ .../25-iteration-over-string/ru/data.yml | 4 + .../26-conditions-inside-loops/ru/EXERCISE.md | 7 + .../26-conditions-inside-loops/ru/README.md | 40 ++++++ .../26-conditions-inside-loops/ru/data.yml | 4 + .../50-loops/28-build-strings/ru/EXERCISE.md | 2 + .../50-loops/28-build-strings/ru/README.md | 36 +++++ modules/50-loops/28-build-strings/ru/data.yml | 4 + .../50-loops/30-syntax-sugar/ru/EXERCISE.md | 8 ++ modules/50-loops/30-syntax-sugar/ru/README.md | 10 ++ modules/50-loops/30-syntax-sugar/ru/data.yml | 9 ++ modules/50-loops/50-mutators/ru/EXERCISE.md | 10 ++ modules/50-loops/50-mutators/ru/README.md | 62 +++++++++ modules/50-loops/50-mutators/ru/data.yml | 10 ++ .../55-return-from-loops/ru/EXERCISE.md | 12 ++ .../55-return-from-loops/ru/README.md | 40 ++++++ .../50-loops/55-return-from-loops/ru/data.yml | 6 + modules/50-loops/70-for/ru/EXERCISE.md | 14 ++ modules/50-loops/70-for/ru/README.md | 38 +++++ modules/50-loops/70-for/ru/data.yml | 13 ++ 216 files changed, 4405 insertions(+) create mode 100644 modules/10-basics/10-hello-world/ru/EXERCISE.md create mode 100644 modules/10-basics/10-hello-world/ru/README.md create mode 100644 modules/10-basics/10-hello-world/ru/data.yml create mode 100644 modules/10-basics/20-comments/ru/EXERCISE.md create mode 100644 modules/10-basics/20-comments/ru/README.md create mode 100644 modules/10-basics/20-comments/ru/data.yml create mode 100644 modules/10-basics/40-instructions/ru/EXERCISE.md create mode 100644 modules/10-basics/40-instructions/ru/README.md create mode 100644 modules/10-basics/40-instructions/ru/data.yml create mode 100644 modules/10-basics/45-testing/ru/EXERCISE.md create mode 100644 modules/10-basics/45-testing/ru/README.md create mode 100644 modules/10-basics/45-testing/ru/data.yml create mode 100644 modules/10-basics/50-syntax-errors/ru/EXERCISE.md create mode 100644 modules/10-basics/50-syntax-errors/ru/README.md create mode 100644 modules/10-basics/50-syntax-errors/ru/data.yml create mode 100644 modules/20-arithmetics/20-basic/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/20-basic/ru/README.md create mode 100644 modules/20-arithmetics/20-basic/ru/data.yml create mode 100644 modules/20-arithmetics/25-operator/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/25-operator/ru/README.md create mode 100644 modules/20-arithmetics/25-operator/ru/data.yml create mode 100644 modules/20-arithmetics/27-commutativity/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/27-commutativity/ru/README.md create mode 100644 modules/20-arithmetics/27-commutativity/ru/data.yml create mode 100644 modules/20-arithmetics/30-composition/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/30-composition/ru/README.md create mode 100644 modules/20-arithmetics/30-composition/ru/data.yml create mode 100644 modules/20-arithmetics/40-priority/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/40-priority/ru/README.md create mode 100644 modules/20-arithmetics/40-priority/ru/data.yml create mode 100644 modules/20-arithmetics/50-float/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/50-float/ru/README.md create mode 100644 modules/20-arithmetics/50-float/ru/data.yml create mode 100644 modules/20-arithmetics/60-infinity/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/60-infinity/ru/README.md create mode 100644 modules/20-arithmetics/60-infinity/ru/data.yml create mode 100644 modules/20-arithmetics/70-nan/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/70-nan/ru/README.md create mode 100644 modules/20-arithmetics/70-nan/ru/data.yml create mode 100644 modules/20-arithmetics/80-linting/ru/EXERCISE.md create mode 100644 modules/20-arithmetics/80-linting/ru/README.md create mode 100644 modules/20-arithmetics/80-linting/ru/data.yml create mode 100644 modules/25-strings/10-quotes/ru/EXERCISE.md create mode 100644 modules/25-strings/10-quotes/ru/README.md create mode 100644 modules/25-strings/10-quotes/ru/data.yml create mode 100644 modules/25-strings/15-escape-characters/ru/EXERCISE.md create mode 100644 modules/25-strings/15-escape-characters/ru/README.md create mode 100644 modules/25-strings/15-escape-characters/ru/data.yml create mode 100644 modules/25-strings/20-string-concatenation/ru/EXERCISE.md create mode 100644 modules/25-strings/20-string-concatenation/ru/README.md create mode 100644 modules/25-strings/20-string-concatenation/ru/data.yml create mode 100644 modules/25-strings/30-encoding/ru/EXERCISE.md create mode 100644 modules/25-strings/30-encoding/ru/README.md create mode 100644 modules/25-strings/30-encoding/ru/data.yml create mode 100644 modules/30-variables/10-definition/ru/EXERCISE.md create mode 100644 modules/30-variables/10-definition/ru/README.md create mode 100644 modules/30-variables/10-definition/ru/data.yml create mode 100644 modules/30-variables/11-change/ru/EXERCISE.md create mode 100644 modules/30-variables/11-change/ru/README.md create mode 100644 modules/30-variables/11-change/ru/data.yml create mode 100644 modules/30-variables/13-variables-naming/ru/EXERCISE.md create mode 100644 modules/30-variables/13-variables-naming/ru/README.md create mode 100644 modules/30-variables/13-variables-naming/ru/data.yml create mode 100644 modules/30-variables/14-errors/ru/EXERCISE.md create mode 100644 modules/30-variables/14-errors/ru/README.md create mode 100644 modules/30-variables/14-errors/ru/data.yml create mode 100644 modules/30-variables/15-variables-expressions/ru/EXERCISE.md create mode 100644 modules/30-variables/15-variables-expressions/ru/README.md create mode 100644 modules/30-variables/15-variables-expressions/ru/data.yml create mode 100644 modules/30-variables/18-variable-concatenation/ru/EXERCISE.md create mode 100644 modules/30-variables/18-variable-concatenation/ru/README.md create mode 100644 modules/30-variables/18-variable-concatenation/ru/data.yml create mode 100644 modules/30-variables/19-naming-style/ru/EXERCISE.md create mode 100644 modules/30-variables/19-naming-style/ru/README.md create mode 100644 modules/30-variables/19-naming-style/ru/data.yml create mode 100644 modules/30-variables/20-magic-numbers/ru/EXERCISE.md create mode 100644 modules/30-variables/20-magic-numbers/ru/README.md create mode 100644 modules/30-variables/20-magic-numbers/ru/data.yml create mode 100644 modules/30-variables/23-constants/ru/EXERCISE.md create mode 100644 modules/30-variables/23-constants/ru/README.md create mode 100644 modules/30-variables/23-constants/ru/data.yml create mode 100644 modules/30-variables/25-interpolation/ru/EXERCISE.md create mode 100644 modules/30-variables/25-interpolation/ru/README.md create mode 100644 modules/30-variables/25-interpolation/ru/data.yml create mode 100644 modules/30-variables/30-symbols/ru/EXERCISE.md create mode 100644 modules/30-variables/30-symbols/ru/README.md create mode 100644 modules/30-variables/30-symbols/ru/data.yml create mode 100644 modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md create mode 100644 modules/33-data-types/10-primitive-data-types/ru/README.md create mode 100644 modules/33-data-types/10-primitive-data-types/ru/data.yml create mode 100644 modules/33-data-types/45-undefined/ru/EXERCISE.md create mode 100644 modules/33-data-types/45-undefined/ru/README.md create mode 100644 modules/33-data-types/45-undefined/ru/data.yml create mode 100644 modules/33-data-types/47-data-types-immutability/ru/EXERCISE.md create mode 100644 modules/33-data-types/47-data-types-immutability/ru/README.md create mode 100644 modules/33-data-types/47-data-types-immutability/ru/data.yml create mode 100644 modules/33-data-types/50-data-types-weak-typing/ru/EXERCISE.md create mode 100644 modules/33-data-types/50-data-types-weak-typing/ru/README.md create mode 100644 modules/33-data-types/50-data-types-weak-typing/ru/data.yml create mode 100644 modules/35-calling-functions/100-call/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/100-call/ru/README.md create mode 100644 modules/35-calling-functions/100-call/ru/data.yml create mode 100644 modules/35-calling-functions/110-math/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/110-math/ru/README.md create mode 100644 modules/35-calling-functions/110-math/ru/data.yml create mode 100644 modules/35-calling-functions/120-function-signature/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/120-function-signature/ru/README.md create mode 100644 modules/35-calling-functions/120-function-signature/ru/data.yml create mode 100644 modules/35-calling-functions/135-calling-functions-default-arguments/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/135-calling-functions-default-arguments/ru/README.md create mode 100644 modules/35-calling-functions/135-calling-functions-default-arguments/ru/data.yml create mode 100644 modules/35-calling-functions/150-calling-functions-expression/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/150-calling-functions-expression/ru/README.md create mode 100644 modules/35-calling-functions/150-calling-functions-expression/ru/data.yml create mode 100644 modules/35-calling-functions/180-variadic-parameters/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/180-variadic-parameters/ru/README.md create mode 100644 modules/35-calling-functions/180-variadic-parameters/ru/data.yml create mode 100644 modules/35-calling-functions/270-deterministic/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/270-deterministic/ru/README.md create mode 100644 modules/35-calling-functions/270-deterministic/ru/data.yml create mode 100644 modules/35-calling-functions/350-stdlib/ru/EXERCISE.md create mode 100644 modules/35-calling-functions/350-stdlib/ru/README.md create mode 100644 modules/35-calling-functions/350-stdlib/ru/data.yml create mode 100644 modules/38-properties/100-properties-syntax/ru/EXERCISE.md create mode 100644 modules/38-properties/100-properties-syntax/ru/README.md create mode 100644 modules/38-properties/100-properties-syntax/ru/data.yml create mode 100644 modules/38-properties/200-properties-methods/ru/EXERCISE.md create mode 100644 modules/38-properties/200-properties-methods/ru/README.md create mode 100644 modules/38-properties/200-properties-methods/ru/data.yml create mode 100644 modules/38-properties/300-properties-immutability/ru/EXERCISE.md create mode 100644 modules/38-properties/300-properties-immutability/ru/README.md create mode 100644 modules/38-properties/300-properties-immutability/ru/data.yml create mode 100644 modules/38-properties/400-properties-expressions/ru/EXERCISE.md create mode 100644 modules/38-properties/400-properties-expressions/ru/README.md create mode 100644 modules/38-properties/400-properties-expressions/ru/data.yml create mode 100644 modules/38-properties/500-properties-chain-of-methods/ru/EXERCISE.md create mode 100644 modules/38-properties/500-properties-chain-of-methods/ru/README.md create mode 100644 modules/38-properties/500-properties-chain-of-methods/ru/data.yml create mode 100644 modules/40-define-functions/100-define-functions-syntax/ru/EXERCISE.md create mode 100644 modules/40-define-functions/100-define-functions-syntax/ru/README.md create mode 100644 modules/40-define-functions/100-define-functions-syntax/ru/data.yml create mode 100644 modules/40-define-functions/150-define-functions-return/ru/EXERCISE.md create mode 100644 modules/40-define-functions/150-define-functions-return/ru/README.md create mode 100644 modules/40-define-functions/150-define-functions-return/ru/data.yml create mode 100644 modules/40-define-functions/320-define-functions-parameters/ru/EXERCISE.md create mode 100644 modules/40-define-functions/320-define-functions-parameters/ru/README.md create mode 100644 modules/40-define-functions/320-define-functions-parameters/ru/data.yml create mode 100644 modules/40-define-functions/340-define-functions-default-parameters/ru/EXERCISE.md create mode 100644 modules/40-define-functions/340-define-functions-default-parameters/ru/README.md create mode 100644 modules/40-define-functions/340-define-functions-default-parameters/ru/data.yml create mode 100644 modules/40-define-functions/450-define-functions-short-syntax/ru/EXERCISE.md create mode 100644 modules/40-define-functions/450-define-functions-short-syntax/ru/README.md create mode 100644 modules/40-define-functions/450-define-functions-short-syntax/ru/data.yml create mode 100644 modules/45-logic/10-bool-type/ru/EXERCISE.md create mode 100644 modules/45-logic/10-bool-type/ru/README.md create mode 100644 modules/45-logic/10-bool-type/ru/data.yml create mode 100644 modules/45-logic/15-predicates/ru/EXERCISE.md create mode 100644 modules/45-logic/15-predicates/ru/README.md create mode 100644 modules/45-logic/15-predicates/ru/data.yml create mode 100644 modules/45-logic/20-logic-combine-expressions/ru/EXERCISE.md create mode 100644 modules/45-logic/20-logic-combine-expressions/ru/README.md create mode 100644 modules/45-logic/20-logic-combine-expressions/ru/data.yml create mode 100644 modules/45-logic/25-logical-operators/ru/EXERCISE.md create mode 100644 modules/45-logic/25-logical-operators/ru/README.md create mode 100644 modules/45-logic/25-logical-operators/ru/data.yml create mode 100644 modules/45-logic/28-logical-negation/ru/EXERCISE.md create mode 100644 modules/45-logic/28-logical-negation/ru/README.md create mode 100644 modules/45-logic/28-logical-negation/ru/data.yml create mode 100644 modules/45-logic/70-logical-expressions/ru/EXERCISE.md create mode 100644 modules/45-logic/70-logical-expressions/ru/README.md create mode 100644 modules/45-logic/70-logical-expressions/ru/data.yml create mode 100644 modules/48-conditionals/30-if/ru/EXERCISE.md create mode 100644 modules/48-conditionals/30-if/ru/README.md create mode 100644 modules/48-conditionals/30-if/ru/data.yml create mode 100644 modules/48-conditionals/40-if-else/ru/EXERCISE.md create mode 100644 modules/48-conditionals/40-if-else/ru/README.md create mode 100644 modules/48-conditionals/40-if-else/ru/data.yml create mode 100644 modules/48-conditionals/50-else-if/ru/EXERCISE.md create mode 100644 modules/48-conditionals/50-else-if/ru/README.md create mode 100644 modules/48-conditionals/50-else-if/ru/data.yml create mode 100644 modules/48-conditionals/60-ternary-operator/ru/EXERCISE.md create mode 100644 modules/48-conditionals/60-ternary-operator/ru/README.md create mode 100644 modules/48-conditionals/60-ternary-operator/ru/data.yml create mode 100644 modules/48-conditionals/65-switch/ru/EXERCISE.md create mode 100644 modules/48-conditionals/65-switch/ru/README.md create mode 100644 modules/48-conditionals/65-switch/ru/data.yml create mode 100644 modules/50-loops/10-while/ru/EXERCISE.md create mode 100644 modules/50-loops/10-while/ru/README.md create mode 100644 modules/50-loops/10-while/ru/data.yml create mode 100644 modules/50-loops/20-aggregation-numbers/ru/EXERCISE.md create mode 100644 modules/50-loops/20-aggregation-numbers/ru/README.md create mode 100644 modules/50-loops/20-aggregation-numbers/ru/data.yml create mode 100644 modules/50-loops/23-aggregation-strings/ru/EXERCISE.md create mode 100644 modules/50-loops/23-aggregation-strings/ru/README.md create mode 100644 modules/50-loops/23-aggregation-strings/ru/data.yml create mode 100644 modules/50-loops/25-iteration-over-string/ru/EXERCISE.md create mode 100644 modules/50-loops/25-iteration-over-string/ru/README.md create mode 100644 modules/50-loops/25-iteration-over-string/ru/data.yml create mode 100644 modules/50-loops/26-conditions-inside-loops/ru/EXERCISE.md create mode 100644 modules/50-loops/26-conditions-inside-loops/ru/README.md create mode 100644 modules/50-loops/26-conditions-inside-loops/ru/data.yml create mode 100644 modules/50-loops/28-build-strings/ru/EXERCISE.md create mode 100644 modules/50-loops/28-build-strings/ru/README.md create mode 100644 modules/50-loops/28-build-strings/ru/data.yml create mode 100644 modules/50-loops/30-syntax-sugar/ru/EXERCISE.md create mode 100644 modules/50-loops/30-syntax-sugar/ru/README.md create mode 100644 modules/50-loops/30-syntax-sugar/ru/data.yml create mode 100644 modules/50-loops/50-mutators/ru/EXERCISE.md create mode 100644 modules/50-loops/50-mutators/ru/README.md create mode 100644 modules/50-loops/50-mutators/ru/data.yml create mode 100644 modules/50-loops/55-return-from-loops/ru/EXERCISE.md create mode 100644 modules/50-loops/55-return-from-loops/ru/README.md create mode 100644 modules/50-loops/55-return-from-loops/ru/data.yml create mode 100644 modules/50-loops/70-for/ru/EXERCISE.md create mode 100644 modules/50-loops/70-for/ru/README.md create mode 100644 modules/50-loops/70-for/ru/data.yml diff --git a/modules/10-basics/10-hello-world/ru/EXERCISE.md b/modules/10-basics/10-hello-world/ru/EXERCISE.md new file mode 100644 index 0000000..55762e3 --- /dev/null +++ b/modules/10-basics/10-hello-world/ru/EXERCISE.md @@ -0,0 +1,7 @@ +Наберите в редакторе код из задания символ в символ и нажмите «Проверить». + +```javascript +console.log('Hello, World!'); +``` + +Внимание: если вы напишете `heLLo, woRld!` вместо `Hello, World!`, то это будет считаться другим текстом, потому что заглавные и строчные буквы — это разные символы. Размер буквы называют *регистром*, и говорят: *регистр — важен!* Это касается почти всего в коде, поэтому привыкайте всегда обращать внимание на регистр. diff --git a/modules/10-basics/10-hello-world/ru/README.md b/modules/10-basics/10-hello-world/ru/README.md new file mode 100644 index 0000000..5a88708 --- /dev/null +++ b/modules/10-basics/10-hello-world/ru/README.md @@ -0,0 +1,9 @@ +Изучение нового языка программирования традиционно начинается с 'Hello, World!'. Это простая программа, которая выводит приветствие на экран и заодно знакомит с новым языком — его синтаксисом и структурой программы. Этой традиции уже больше сорока лет, поэтому и мы не будем ее нарушать — в первом же уроке напишем программу `Hello, World!`. + +Эта программа будет выводить на экран текст: + +
+  Hello, World!
+
+ +Чтобы вывести что-то на экран, нужно дать компьютеру специальную команду. В языке JavaScript такая команда — `console.log()`. diff --git a/modules/10-basics/10-hello-world/ru/data.yml b/modules/10-basics/10-hello-world/ru/data.yml new file mode 100644 index 0000000..1a060c7 --- /dev/null +++ b/modules/10-basics/10-hello-world/ru/data.yml @@ -0,0 +1,5 @@ +name: Привет, Мир! +tips: + - > + [Немного о 'Hello, + World!'](https://ru.hexlet.io/blog/posts/moy-chelovek-menya-ponimaet-istoriya-frazy-hello-world-i-ee-analogov) diff --git a/modules/10-basics/20-comments/ru/EXERCISE.md b/modules/10-basics/20-comments/ru/EXERCISE.md new file mode 100644 index 0000000..b326c80 --- /dev/null +++ b/modules/10-basics/20-comments/ru/EXERCISE.md @@ -0,0 +1 @@ +Создайте однострочный комментарий с текстом: `You know nothing, Jon Snow!`. diff --git a/modules/10-basics/20-comments/ru/README.md b/modules/10-basics/20-comments/ru/README.md new file mode 100644 index 0000000..fadb17a --- /dev/null +++ b/modules/10-basics/20-comments/ru/README.md @@ -0,0 +1,42 @@ + +Кроме кода, в файлах с исходным кодом могут находиться комментарии. Это текст, который не является частью программы и нужен программистам для пометок. С их помощью добавляют пояснения, как работает код, какие здесь ошибки нужно поправить или не забыть что-то добавить позже. + +```javascript +// Удалить строку ниже после реализации задачи по регистрации +console.log(10); +``` + +Комментарии в JavaScript бывают двух видов: + +## Однострочные комментарии + +*Однострочные комментарии* начинаются с `//`. После этих двух символов может следовать любой текст, вся строчка не будет анализироваться и исполняться. + +Комментарий может занимать всю строчку. Если одной строчки мало, то создаются несколько комментариев: + +```javascript +// For Winterfell! +// For Lanisters! +``` + +Комментарий может находиться на строчке после какого-нибудь кода: + +```javascript +console.log('I am the King'); // For Lannisters! +``` + +## Многострочные комментарии + +*Многострочные комментарии* начинаются с `/*` и заканчиваются на `*/`. + +```javascript +/* + The night is dark and + full of terrors. +*/ +console.log('I am the King'); +``` + +https://replit.com/@hexlet/helloworld + +Такие комментарии, обычно, используют для документирования кода, например, функций. diff --git a/modules/10-basics/20-comments/ru/data.yml b/modules/10-basics/20-comments/ru/data.yml new file mode 100644 index 0000000..c3d969c --- /dev/null +++ b/modules/10-basics/20-comments/ru/data.yml @@ -0,0 +1,22 @@ +name: Комментарии +tips: + - | + [Подробнее о комментариях](https://www.w3schools.com/js/js_comments.asp) +definitions: + - name: Комментарий + description: > + текст в коде программы, который не влияет на функциональность и + добавляется программистами для себя и своих коллег. + + + `// однострочный комментарий` + + + ``` + + /* + многострочный комментарий + многострочный комментарий + */ + + ``` diff --git a/modules/10-basics/40-instructions/ru/EXERCISE.md b/modules/10-basics/40-instructions/ru/EXERCISE.md new file mode 100644 index 0000000..f49eca8 --- /dev/null +++ b/modules/10-basics/40-instructions/ru/EXERCISE.md @@ -0,0 +1,9 @@ +Выведите на экран друг за другом три имени: *Robert*, *Stannis*, *Renly*. В результате на экране должно отобразиться: + +
+Robert
+Stannis
+Renly
+
+ +Для каждого имени используйте свой собственный вызов `console.log()`. diff --git a/modules/10-basics/40-instructions/ru/README.md b/modules/10-basics/40-instructions/ru/README.md new file mode 100644 index 0000000..0c39d45 --- /dev/null +++ b/modules/10-basics/40-instructions/ru/README.md @@ -0,0 +1,27 @@ +Инструкция — это команда для компьютера выполнить что-то. Код на JavaScript — это набор инструкций, которые, как правило, отделяются друг от друга символом `;`. + +Вот пример кода с двумя инструкциями. + +```javascript +console.log('Mother of Dragons.'); +console.log('Dracarys!'); +``` + +https://replit.com/@hexlet/js-basics-instructions + +При запуске этого кода, на экран последовательно выводятся два предложения: + +
+Mother of Dragons.
+Dracarys!
+
+ +Теоретически, инструкции можно написать друг за другом без переноса на новую строчку: + +```javascript +console.log('Mother of Dragons.'); console.log('Drakarys!'); +``` + +Результат на экране будет таким же, но такой код неудобен для чтения, поэтому инструкции располагают друг под другом. + +Почему это важно знать? Инструкция — это единица исполнения. Интерпретатор, программа которая запускает код на JavaScript, выполняет инструкции строго по очереди. И мы, как разработчики, должны понимать этот порядок и уметь мысленно разделять программу на независимые части, удобные для анализа. diff --git a/modules/10-basics/40-instructions/ru/data.yml b/modules/10-basics/40-instructions/ru/data.yml new file mode 100644 index 0000000..84b236e --- /dev/null +++ b/modules/10-basics/40-instructions/ru/data.yml @@ -0,0 +1,15 @@ +name: Инструкции (Statements) +tips: + - | + [Немного об интерпретаторах](https://ru.wikipedia.org/wiki/Интерпретатор) + - > + [Инструкции и объявления по + категориям](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements) +definitions: + - name: Интерпретатор + description: | + программа, выполняющая код на JavaScript. + - name: Инструкция (statement) + description: > + команда для компьютера, написанная на языке программирования. Код на + JavaScript — это набор инструкций, разделенных (чаще всего) символом `;`. diff --git a/modules/10-basics/45-testing/ru/EXERCISE.md b/modules/10-basics/45-testing/ru/EXERCISE.md new file mode 100644 index 0000000..806aa22 --- /dev/null +++ b/modules/10-basics/45-testing/ru/EXERCISE.md @@ -0,0 +1,7 @@ +Просто тренировка. Выведите на экран число 9780262531962. + +
+9780262531962
+
+ +Поэкспериментируйте с выводом. Передайте туда другое число или строку. Посмотрите на ответ системы, попробуйте его перевести и понять. diff --git a/modules/10-basics/45-testing/ru/README.md b/modules/10-basics/45-testing/ru/README.md new file mode 100644 index 0000000..6e86eb8 --- /dev/null +++ b/modules/10-basics/45-testing/ru/README.md @@ -0,0 +1,35 @@ + +Сайт автоматически проверяет ваши решения. Как это работает? + +В самом простом случае, система просто запускает ваш код и смотрит на то, что вывелось на экран. А потом сверяет с тем, что мы «ожидали» по заданию. + +В следующих, более сложных уроках, вы будете писать функции — некие мини-программы, принимающие информацию из внешнего мира и производящие какие-то операции. Проверка ваших решений в таких случаях выглядит немного сложнее: система запускает ваше решение и передаёт какую-то информацию. Система также знает — «ожидает» — какой именно ответ должна дать правильная функция при таких входных данных. + +Например, если ваша задача — написать функцию сложения двух чисел, то проверочная система будет передавать ей разные комбинации чисел и сверять ответ вашей функции с реальными суммами. Если во всех случаях ответы совпадут, то решение считается верным. + +Такой подход называется тестированием, и он используется в реальной повседневной разработке. Обычно программист сначала пишет тест — проверочную программу, а потом уже ту программу, которую хотел написать. В процессе он постоянно запускает тесты и смотрит, приблизился ли он к решению. + +Именно поэтому наш сайт говорит «Тесты пройдены», когда вы правильно решили задачу. + +Вот простой пример: в одном из будущих уроков вам нужно будет написать функцию, которая производит вычисления и выдаёт ответ. Предположим, вы допустили небольшую ошибку, и функция выдала неправильное число. Система ответит примерно так: + +
+  ● test
+
+  expect(received).toBe(expected) // Object.is equality
+
+  Expected value to be:
+    "Hello, World!"
+  Received:
+    "ello, World!"
+
+ +Expected – ожидаемое значение, а Received, то которое выдал ваш код. + +Кроме наших тестов, будет крайне полезно экспериментировать с кодом в консоли [браузера](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console). В любой ситуации, когда вы недопоняли, или хотите попробовать разные варианты использования, смело открывайте консоль и вводите туда код. Идеально, если вы выполните самостоятельно весь код, который присутствует в уроках. Кроме консоли, полезно использовать сервис [repl.it](https://repl.it/languages/javascript). + +--- + +Иногда в процессе решения будет казаться, что вы сделали все правильно, но система "капризничает" и не принимает решение. Подобное поведение практически исключено. Нерабочие тесты просто не могут попасть на сайт, они автоматически запускаются после каждого изменения. В подавляющем большинстве таких случаев, (а все наши проекты в сумме провели миллионы проверок за много лет), ошибка содержится в коде решения. Она может быть очень незаметной, вместо английской буквы случайно ввели русскую, вместо верхнего регистра использовали нижний или забыли вывести запятую. Другие случаи сложнее. Возможно ваше решение работает для одного набора входных данных, но не работает для другого. Поэтому всегда внимательно читайте условие задачи и вывод тестов. Там почти наверняка есть указание на ошибку. + +Однако, если вы уверены в ошибке или нашли какую-то неточность, то вы всегда можете указать на нее. В конце каждой теории есть ссылка на содержимое урока на гитхабе (этот проект полностью открытый!). Перейдя туда, вы можете написать issue, посмотреть содержимое тестов (там видно, как вызывается ваш код) и даже отправить pullrequest. Если для вас это пока темный лес, то подключитесь в наше сообщество [Telegram] (https://t.me/hexletcommunity), там в канале *Обратная связь* мы всегда поможем. diff --git a/modules/10-basics/45-testing/ru/data.yml b/modules/10-basics/45-testing/ru/data.yml new file mode 100644 index 0000000..708a386 --- /dev/null +++ b/modules/10-basics/45-testing/ru/data.yml @@ -0,0 +1,11 @@ +name: Как мы проверяем ваши решения +definitions: + - name: Тесты + description: > + специальный код, проверяющий программы на корректность, сверяя правильный + результат с реальным. +tips: + - | + [TDD](https://ru.wikipedia.org/wiki/Разработка_через_тестирование) + - | + [Сообщество Хекслета в Telegram](https://t.me/hexletcommunity) diff --git a/modules/10-basics/50-syntax-errors/ru/EXERCISE.md b/modules/10-basics/50-syntax-errors/ru/EXERCISE.md new file mode 100644 index 0000000..aff6b2f --- /dev/null +++ b/modules/10-basics/50-syntax-errors/ru/EXERCISE.md @@ -0,0 +1,4 @@ + +Это задание не связано с уроком напрямую. Но будет полезным потренироваться с выводом на экран. + +Выведите на экран *What Is Dead May Never Die* diff --git a/modules/10-basics/50-syntax-errors/ru/README.md b/modules/10-basics/50-syntax-errors/ru/README.md new file mode 100644 index 0000000..c6e7f16 --- /dev/null +++ b/modules/10-basics/50-syntax-errors/ru/README.md @@ -0,0 +1,18 @@ + +Если программа на JavaScript написана синтаксически некорректно, то интерпретатор выводит на экран соответствующее сообщение, а также указание на файл и строчку в нём, где, по его мнению, произошла ошибка. *Синтаксическая ошибка* возникает в том случае, когда код был записан с нарушением грамматических правил. В человеческих языках грамматика важна, но текст с ошибками чаще всего можно понять и прочитать. В программировании всё строго. Любое мельчайшее нарушение, и программа даже не запустится. Примером может быть забытая `;`, неправильно расставленные скобки и другие детали. + +Вот пример кода с синтаксической ошибкой: + +```javascript +console.log('Hodor' +``` + +Если запустить код выше, то мы увидим следующее сообщение: `SyntaxError: missing ) after argument list`, а также указание на строку и файл, где возникла эта ошибка. Подобные синтаксические ошибки в JavaScript относятся к разряду SyntaxError. + +*По техническим причинам, такой код, запущенный на https://code-basics.com не укажет на строку и файл. Проверить этот вывод можно на https://repl.it* + +https://replit.com/@hexlet/js-basics-syntax-errors + +С одной стороны, ошибки SyntaxError — самые простые, потому что они связаны исключительно с грамматическими правилами написания кода, а не с самим смыслом кода. Их легко исправить: нужно лишь найти нарушение в записи. + +С другой стороны, интерпретатор не всегда может чётко указать на это нарушение. Поэтому бывает, что забытую скобку нужно поставить не туда, куда указывает сообщение об ошибке. diff --git a/modules/10-basics/50-syntax-errors/ru/data.yml b/modules/10-basics/50-syntax-errors/ru/data.yml new file mode 100644 index 0000000..4321094 --- /dev/null +++ b/modules/10-basics/50-syntax-errors/ru/data.yml @@ -0,0 +1,11 @@ +name: Синтаксические ошибки +tips: + - | + [Ошибки в JavaScript](https://habr.com/ru/post/249525/) +definitions: + - name: Синтаксическая ошибка + description: нарушение грамматических правил языка программирования. + - name: SyntaxError (ошибка парсинга) + description: >- + тип ошибок в JavaScript, возникающих при наличии синтаксических ошибок в + коде. diff --git a/modules/20-arithmetics/20-basic/ru/EXERCISE.md b/modules/20-arithmetics/20-basic/ru/EXERCISE.md new file mode 100644 index 0000000..c6e757d --- /dev/null +++ b/modules/20-arithmetics/20-basic/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Выведите на экран результат деления числа `81` на `9`. diff --git a/modules/20-arithmetics/20-basic/ru/README.md b/modules/20-arithmetics/20-basic/ru/README.md new file mode 100644 index 0000000..a002fe9 --- /dev/null +++ b/modules/20-arithmetics/20-basic/ru/README.md @@ -0,0 +1,44 @@ +На базовом уровне компьютеры оперируют только числами. Даже в прикладных программах на высокоуровневых языках внутри много чисел и операций над ними. К счастью, для старта достаточно знать обычную арифметику — с нее и начнем. + +Для сложения двух чисел в математике мы пишем, например, `3 + 4`. В программировании — то же самое. Вот программа, складывающая два числа: + +```javascript +// Не забываем точку с запятой в конце, +// так как каждая строчка в коде - инструкция +3 + 4; +``` + +Инструкция `3 + 4;` заставит компьютер сложить числа и узнать результат. Если запустить эту программу, то ничего не произойдет. А если быть точными, то компьютер вычислит сумму, но на этом всё. Результат сложения никак не используется, и такая программа не представляет никакого интереса. Нам нужно попросить компьютер сложить `3 + 4` **и** дать команду сделать что-то с результатом. Например, вывести его на экран: + +```javascript +// Сначала вычисляется сумма, +// затем она передается в функцию печати +console.log(3 + 4); +``` + +После запуска на экране появится результат: + +
+7
+
+ +Кроме сложения, доступны следующие операции: + +* `*` — умножение +* `/` — деление +* `-` — вычитание +* `%` — [остаток от деления](https://ru.wikipedia.org/wiki/Деление_с_остатком) +* `**` — возведение в степень + +Теперь давайте выведем на экран результат деления, а потом результат возведения в степень: + +```javascript +console.log(8 / 2); // => 4 +console.log(3 ** 2); // => 9 +``` + +https://replit.com/@hexlet/js-basics-arithmetics-basics + +Иногда для удобства мы будем показывать в комментариях результат запуска строчек кода, вот так: `=> РЕЗУЛЬТАТ`. Например, `// => 4`. + +Первая инструкция выведет на экран `4` (потому что 8 / 2 это 4), а вторая инструкция выведет на экран 9 (потому что 32 это 9). diff --git a/modules/20-arithmetics/20-basic/ru/data.yml b/modules/20-arithmetics/20-basic/ru/data.yml new file mode 100644 index 0000000..8b8fbf2 --- /dev/null +++ b/modules/20-arithmetics/20-basic/ru/data.yml @@ -0,0 +1,19 @@ +name: Арифметические операции +tips: + - > + Всегда отбивайте арифметические операторы пробелами от самих чисел + (операндов) – это хороший стиль программирования. Поэтому в наших примерах + `console.log(3 + 4)`, а не `console.log(3+4)`. + - > + Деление на ноль — это `Infinity` (бесконечность). Мы разберёмся с тем, что + это значит, в будущих уроках. + - > + [Арифметические + операции](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators#arithmetic_operators) + - | + [Деление с остатком](https://ru.wikipedia.org/wiki/Деление_с_остатком) +definitions: + - name: Инструкция + description: > + наименьшая автономная часть языка программирования; команда или набор + команд. Программа обычно представляет собой последовательность инструкций. diff --git a/modules/20-arithmetics/25-operator/ru/EXERCISE.md b/modules/20-arithmetics/25-operator/ru/EXERCISE.md new file mode 100644 index 0000000..003cfc9 --- /dev/null +++ b/modules/20-arithmetics/25-operator/ru/EXERCISE.md @@ -0,0 +1 @@ +Напишите программу, которая посчитает разность между числами `6` и `-81` и выведет ответ на экран. diff --git a/modules/20-arithmetics/25-operator/ru/README.md b/modules/20-arithmetics/25-operator/ru/README.md new file mode 100644 index 0000000..105580f --- /dev/null +++ b/modules/20-arithmetics/25-operator/ru/README.md @@ -0,0 +1,22 @@ + +Перед тем как двигаться дальше, разберем базовую терминологию. Знак операции, такой как `+`, называют **оператором**. Операторы выполняют операции над определенными значениями, которые называются **операндами**. Сами операторы, обычно, представлены одним или несколькими символами. Реже словом. Подавляющее большинство операторов соответствуют математическим операциям. + +```javascript +console.log(8 + 2); +``` + +https://replit.com/@hexlet/js-basics-arithmetics-operator + +В этом примере `+` — это **оператор**, а числа `8` и `2` — это **операнды**. + +В случае сложения у нас есть два операнда: один слева, другой справа от знака `+`. Операции, которые требуют наличия двух операндов, называются **бинарными**. Если пропустить хотя бы один операнд, например, `3 + ;`, то программа завершится с синтаксической ошибкой. + +Операции (не операторы) бывают не только бинарными, но и унарными (с одним операндом), и даже тернарными (с тремя операндами)! Причем операторы могут выглядеть одинаково, но обозначать разные операции. + + ```javascript + console.log(-3); // => -3 + ``` + +Выше пример применения унарной операции к числу `3`. Оператор минус перед тройкой говорит интерпретатору взять число `3` и найти противоположное, то есть `-3`. + +Это немного может сбить с толку, потому что `-3` — это одновременно и число само по себе, и оператор с операндом, но у языков программирования такая структура. diff --git a/modules/20-arithmetics/25-operator/ru/data.yml b/modules/20-arithmetics/25-operator/ru/data.yml new file mode 100644 index 0000000..35a6a3b --- /dev/null +++ b/modules/20-arithmetics/25-operator/ru/data.yml @@ -0,0 +1,14 @@ +name: Операторы +tips: + - > + [Операторы в + JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators) +definitions: + - name: Арифметическая операция + description: сложение, вычитание, умножение и деление. + - name: Унарная операция + description: >- + операция с одним операндом. Например, `-3` — унарная операция для + получения числа, противоположного числу три. + - name: Бинарная операция + description: операция с двумя операндами. Например, `3 + 9`. diff --git a/modules/20-arithmetics/27-commutativity/ru/EXERCISE.md b/modules/20-arithmetics/27-commutativity/ru/EXERCISE.md new file mode 100644 index 0000000..c3c76d8 --- /dev/null +++ b/modules/20-arithmetics/27-commutativity/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Напишите программу, которая считает и выводит последовательно на экран значения следующих математических выражений: «3 в степени 5» и «-8 разделить на -4». diff --git a/modules/20-arithmetics/27-commutativity/ru/README.md b/modules/20-arithmetics/27-commutativity/ru/README.md new file mode 100644 index 0000000..0103e66 --- /dev/null +++ b/modules/20-arithmetics/27-commutativity/ru/README.md @@ -0,0 +1,7 @@ +Мы все помним со школы: «от перемены мест слагаемых сумма не меняется». Это один из базовых и интуитивно понятных законов арифметики, он называется **коммутативным законом**. + +Бинарная операция считается коммутативной, если поменяв местами операнды, вы получаете тот же самый результат. Очевидно, что сложение - коммутативная операция: *3 + 2 = 2 + 3*. + +А вот является ли коммутативной операция вычитания? Конечно, нет: *2 - 3 ≠ 3 - 2*. В программировании этот закон работает точно так же, как в арифметике. + +Более того, большинство операций, с которыми мы будем сталкиваться в реальной жизни, не являются коммутативными. Отсюда вывод: всегда обращайте внимание на порядок того, с чем работаете. diff --git a/modules/20-arithmetics/27-commutativity/ru/data.yml b/modules/20-arithmetics/27-commutativity/ru/data.yml new file mode 100644 index 0000000..ba4caf0 --- /dev/null +++ b/modules/20-arithmetics/27-commutativity/ru/data.yml @@ -0,0 +1,11 @@ +name: Коммутативная операция +tips: + - > + [Подробнее про + коммутативность](https://ru.wikipedia.org/wiki/Коммутативность) +definitions: + - name: Коммутативность + description: > + свойство операции, когда изменение порядка операндов не влияет на + результат. Например, сложение — коммутативная операция: от перемены мест + слагаемых сумма не меняется. diff --git a/modules/20-arithmetics/30-composition/ru/EXERCISE.md b/modules/20-arithmetics/30-composition/ru/EXERCISE.md new file mode 100644 index 0000000..a12d8c8 --- /dev/null +++ b/modules/20-arithmetics/30-composition/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Реализуйте программу, которая вычисляет и выводит на экран значение выражения: + +``` +8 / 2 + 5 - -3 / 2 +``` + +Не вычисляйте ничего самостоятельно, ваша программа должна производить все вычисления сама. diff --git a/modules/20-arithmetics/30-composition/ru/README.md b/modules/20-arithmetics/30-composition/ru/README.md new file mode 100644 index 0000000..3d6b317 --- /dev/null +++ b/modules/20-arithmetics/30-composition/ru/README.md @@ -0,0 +1,23 @@ +А что, если понадобится вычислить такое выражение: `3 * 5 - 2`? Именно так мы и запишем: + +```javascript +console.log(3 * 5 - 2); // => 13 +``` + +Обратите внимание, что интерпретатор производит арифметические вычисления в правильном порядке: сначала деление и умножение, потом сложение и вычитание. Иногда этот порядок нужно изменить — об этом следующий урок. + +Или другой пример: + +```javascript +console.log(2 * 4 * 5 * 10); +``` + +https://replit.com/@hexlet/js-basics-arithmetics-composition + +Как видно, операции можно соединять друг с другом, получая возможность вычислять все более сложные составные выражения. Чтобы представить себе то, как происходят вычисления внутри интерпретатора, давайте разберем пример: `2 * 4 * 5 * 10`. + +1. Сначала вычисляется `2 * 4` и получается выражение `8 * 5 * 10`. +1. Затем `8 * 5`. В итоге имеем `40 * 10`. +3. В конце концов происходит последнее умножение, и получается результат `400`. + +Таким образом, интерпретатор соединяет сложные составные выражения, последовательно выполняя заложенные в них арифметические действия, по умолчанию соблюдая правильный порядок: сначала умножение и деление, затем - сложение и вычитание. diff --git a/modules/20-arithmetics/30-composition/ru/data.yml b/modules/20-arithmetics/30-composition/ru/data.yml new file mode 100644 index 0000000..3dda1ff --- /dev/null +++ b/modules/20-arithmetics/30-composition/ru/data.yml @@ -0,0 +1,6 @@ +name: Композиция операций +tips: [] +definitions: + - name: Композиция + description: | + метод объединения нескольких простых операций в одну сложную. diff --git a/modules/20-arithmetics/40-priority/ru/EXERCISE.md b/modules/20-arithmetics/40-priority/ru/EXERCISE.md new file mode 100644 index 0000000..0b63f8c --- /dev/null +++ b/modules/20-arithmetics/40-priority/ru/EXERCISE.md @@ -0,0 +1,4 @@ + +Дано выражение `70 * 3 + 4 / 8 + 2`. + +Расставьте скобки так, чтобы оба сложения (`3 + 4`) и (`8 + 2`) высчитывались в первую очередь. Выведите результат на экран. diff --git a/modules/20-arithmetics/40-priority/ru/README.md b/modules/20-arithmetics/40-priority/ru/README.md new file mode 100644 index 0000000..2eaa208 --- /dev/null +++ b/modules/20-arithmetics/40-priority/ru/README.md @@ -0,0 +1,32 @@ +Посмотрите внимательно на выражение `2 + 2 * 2` и посчитайте в уме ответ. + +Правильный ответ: `6`. + +Если у вас получилось `8`, то этот урок для вас. В школьной математике мы изучали понятие «приоритет операции». Приоритет определяет то, в какой последовательности должны выполняться операции. Например, умножение и деление имеют больший приоритет, чем сложение и вычитание, а приоритет возведения в степень выше всех остальных арифметических операций: `2 ** 3 * 2` вычислится в `16`. + +Но нередко вычисления должны происходить в порядке, отличном от стандартного приоритета. В сложных ситуациях приоритет можно (и нужно) задавать круглыми скобками, точно так же, как в школе, например: `(2 + 2) * 2`. + +Скобки можно ставить вокруг любой операции. Они могут вкладываться друг в друга сколько угодно раз. Вот пара примеров: + +```javascript +console.log(3 ** (4 - 2)); // => 9 +console.log(7 * 3 + (4 / 2) - (8 + (2 - 1))); // => 14 +``` + +Иногда выражение сложно воспринимать визуально. Тогда можно расставить скобки, не повлияв на приоритет. Например, задание из прошлого урока можно сделать немного понятнее, если расставить скобки. + +Было: + +```javascript +console.log(8 / 2 + 5 - -3 / 2); // => 10.5 +``` + +Стало: + +```javascript +console.log(((8 / 2) + 5) - (-3 / 2)); // => 10.5 +``` + +https://replit.com/@hexlet/js-basics-arithmetics#index.js + +Запомните: код пишется для людей, потому что код будут читать люди, а машины будут только исполнять его. Для машин код — или корректный, или не корректный, для них нет «более» понятного или «менее» понятного кода. diff --git a/modules/20-arithmetics/40-priority/ru/data.yml b/modules/20-arithmetics/40-priority/ru/data.yml new file mode 100644 index 0000000..0d715b9 --- /dev/null +++ b/modules/20-arithmetics/40-priority/ru/data.yml @@ -0,0 +1,10 @@ +name: Приоритет операций +tips: + - > + [Приоритет + операторов](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Operator_Precedence) +definitions: + - name: Выражение + description: > + последовательность действий над данными, приводящая к каком-то результату, + который можно использовать. diff --git a/modules/20-arithmetics/50-float/ru/EXERCISE.md b/modules/20-arithmetics/50-float/ru/EXERCISE.md new file mode 100644 index 0000000..6b472cb --- /dev/null +++ b/modules/20-arithmetics/50-float/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Вычислите и выведите на экран произведение двух чисел: *0.39* и *0.22* diff --git a/modules/20-arithmetics/50-float/ru/README.md b/modules/20-arithmetics/50-float/ru/README.md new file mode 100644 index 0000000..042805f --- /dev/null +++ b/modules/20-arithmetics/50-float/ru/README.md @@ -0,0 +1,25 @@ + +JavaScript не делает различий между рациональными (0.5) и натуральными числами (10), для него и то, и другое - числа (в других языках это не так). Благодаря этому их можно использовать совместно в любых операциях: + +```javascript +3 * 0.5; // 1.5 +``` + +Но как бы от нас ни скрывали, рациональные числа, в силу своих особенностей, устроены совсем по-другому. Нам, как прикладным программистам, это было бы не особенно важно, если бы не одна деталь. Посмотрите на этот пример: + +```javascript +// Проверьте этот код в консоли браузера +0.2 * 0.2 // 0.04000000000000001 +``` + +Операция умножения двух рациональных чисел внезапно привела к неточному вычислению результата. Тот же самый результат выдадут и другие языки программирования. Такое поведение обуславливается ограничениями вычислительных мощностей. Объем памяти, в отличие от чисел, конечен (бесконечное количество чисел требует бесконечного количества памяти для своего хранения). И если с натуральными числами эта проблема решается простым ограничением по верхней границе (есть некоторое максимальное число, которое можно ввести), то с рациональными такой финт не пройдет. + +```javascript +// Максимальное возможное целое число +console.log(Number.MAX_SAFE_INTEGER); +9007199254740991 +``` + +Рациональные числа не выстроены в непрерывную цепочку, между _0.1_ и _0.2_ бесконечное множество чисел. Соответственно возникает серьезная проблема, а как хранить рациональные числа? Это интересный вопрос сам по себе. В интернете множество статей, посвященных организации памяти в таких случаях. Более того, существует стандарт, в котором описано, как это делать правильно, и подавляющее число языков на него опирается. + +Для нас, как для разработчиков, важно понимать, что операции с плавающими числами неточны (эту точность можно регулировать), а значит при решении задач, связанных с подобными числами, необходимо прибегать к специальным трюкам, которые позволяют добиться необходимой точности. diff --git a/modules/20-arithmetics/50-float/ru/data.yml b/modules/20-arithmetics/50-float/ru/data.yml new file mode 100644 index 0000000..8e11b15 --- /dev/null +++ b/modules/20-arithmetics/50-float/ru/data.yml @@ -0,0 +1,9 @@ +name: Числа с плавающей точкой +tips: + - > + [Что нужно знать про арифметику с плавающей + запятой](https://habr.com/post/112953/) +definitions: + - name: Рациональное число + description: | + число, которое можно представить в виде обыкновенной дроби. diff --git a/modules/20-arithmetics/60-infinity/ru/EXERCISE.md b/modules/20-arithmetics/60-infinity/ru/EXERCISE.md new file mode 100644 index 0000000..ec116af --- /dev/null +++ b/modules/20-arithmetics/60-infinity/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Распечатайте на экран сумму бесконечностей, поделенную на 10 diff --git a/modules/20-arithmetics/60-infinity/ru/README.md b/modules/20-arithmetics/60-infinity/ru/README.md new file mode 100644 index 0000000..077f64f --- /dev/null +++ b/modules/20-arithmetics/60-infinity/ru/README.md @@ -0,0 +1,18 @@ + +В программировании широко известна ошибка "деление на ноль". В низкоуровневых языках она приводит к краху программы и необходимости ее перезапуска. Там, где другие падают, JavaScript продолжает работать. + +```javascript +console.log(1 / 0); // ? +``` + +https://replit.com/@hexlet/js-basics-arithmetics-inifinity + +Попробуйте выполнить этот код в браузере. На экран выведется `Infinity` (бесконечность)! Для тех, кто изучал высшую математику (привет, матан!), в этом нет ничего удивительного. Деление на ноль действительно создает бесконечность. Бесконечность в JavaScript — самое настоящее число, с которым возможно проводить различные операции. В повседневных задачах смысла от этого мало, так как большинство операций с бесконечностью завершаются созданием бесконечности, например, при прибавлении любого числа к бесконечности мы все равно получим бесконечность. + +```javascript +Infinity + 4; // Infinity +Infinity - 4; // Infinity +Infinity * Infinity; // Infinity +``` + +Однако есть несколько примеров, где бесконечность нужна. Подробнее этот вопрос рассматривается на Хекслете. diff --git a/modules/20-arithmetics/60-infinity/ru/data.yml b/modules/20-arithmetics/60-infinity/ru/data.yml new file mode 100644 index 0000000..7f34a60 --- /dev/null +++ b/modules/20-arithmetics/60-infinity/ru/data.yml @@ -0,0 +1,11 @@ +name: Бесконечность (Infinity) +tips: + - > + [Infinity](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Infinity) +definitions: + - name: Бесконечность + description: > + Бесконечность в математике и физике не является числом и означает "без + конца" или "без границ".Бесконечность обычно рассматривается как число, + поскольку оно используется для обозначения чисел вещей, но это не реальное + число. diff --git a/modules/20-arithmetics/70-nan/ru/EXERCISE.md b/modules/20-arithmetics/70-nan/ru/EXERCISE.md new file mode 100644 index 0000000..8574dd9 --- /dev/null +++ b/modules/20-arithmetics/70-nan/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Выполните операцию, которая приводит к NaN, и распечатайте её результат на экран с помощью `console.log()`. diff --git a/modules/20-arithmetics/70-nan/ru/README.md b/modules/20-arithmetics/70-nan/ru/README.md new file mode 100644 index 0000000..64c0cc7 --- /dev/null +++ b/modules/20-arithmetics/70-nan/ru/README.md @@ -0,0 +1,15 @@ +Некоторые операции с бесконечностями приводят к странному результату, например, деление бесконечности на бесконечность. В математике такая операция не имеет никакого числового эквивалента. В JavaScript вернется `NaN`. + +```javascript +Infinity / Infinity; // NaN +``` + +`NaN` - специальное значение "не число", которое обычно говорит о том, что была выполнена бессмысленная операция. Результатом практически любой операции, в которой участвует `NaN`, будет `NaN`. + +```javascript +NaN + 1; // NaN +``` + +https://replit.com/@hexlet/js-basics-arithmetics-NaN + +`NaN` интересное значение, хотя оно обозначает "не число" — с точки зрения типов, оно является числом. Парадокс. `NaN` никогда не является желаемым значением и появляется только в результате ошибок. Если вы его встретили, то нужно отследить момент, в котором выполнилась операция, недопустимая для чисел, и поправить это место. diff --git a/modules/20-arithmetics/70-nan/ru/data.yml b/modules/20-arithmetics/70-nan/ru/data.yml new file mode 100644 index 0000000..57e666f --- /dev/null +++ b/modules/20-arithmetics/70-nan/ru/data.yml @@ -0,0 +1,4 @@ +name: NaN +tips: + - > + [NaN](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/NaN) diff --git a/modules/20-arithmetics/80-linting/ru/EXERCISE.md b/modules/20-arithmetics/80-linting/ru/EXERCISE.md new file mode 100644 index 0000000..4926498 --- /dev/null +++ b/modules/20-arithmetics/80-linting/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Выведите на экран результат следующего вычисления: «разница между пятью в квадрате и произведением трёх и семи». Расставьте скобки таким образом, чтобы не нарушать правило `no-mixed-operators`. diff --git a/modules/20-arithmetics/80-linting/ru/README.md b/modules/20-arithmetics/80-linting/ru/README.md new file mode 100644 index 0000000..a0cc2ad --- /dev/null +++ b/modules/20-arithmetics/80-linting/ru/README.md @@ -0,0 +1,38 @@ +Теперь, когда мы уже научились писать простые программы, можно немного поговорить о том, как их писать. + +Код программы следует оформлять определенным образом, чтобы он был достаточно понятным и простым в поддержке. Специальные наборы правил — стандарты — описывают различные аспекты написания кода. Конкретно в JavaScript самым распространенным стандартом является стандарт от [AirBnb](https://github.com/airbnb/javascript). + +В любом языке программирования существуют утилиты — так называемые **линтеры**. Они проверяют код на соответствие стандартам. В JavaScript это [eslint](https://eslint.org/). + +Взгляните на пример из предыдущего урока: + +```javascript +console.log(8/2+5 - -3 / 2); // => 10.5 +``` + +Линтер будет «ругаться» на нарушение сразу нескольких правил: + + * [space-infix-ops](https://eslint.org/docs/rules/space-infix-ops) – Отсутствие пробелов между оператором и операндами. + * [no-mixed-operators](https://eslint.org/docs/rules/no-mixed-operators) – По стандарту нельзя писать код, в котором разные операции используются в одном выражении без явного разделения скобками. + +В прошлом уроке мы сами признали, что такое обилие цифр и символов запутывает, и решили добавить скобки исключительно для удобства чтения: + +```javascript +console.log(((8 / 2) + 5) - (-3 / 2)); // => 10.5 +``` + +Этот вариант уже не нарушает правил, и линтер будет «молчать». + +В упражнении прошлого урока у вас скорее всего получилось так: + +```javascript +console.log(70 * (3 + 4) / (8 + 2)); +``` + +Есть ли здесь нарушение стандарта? + +К сожалению, да. На этот раз операции `*` и `/` находятся в одном выражении без разделения скобками. Вы можете решить эту проблему, добавив дополнительные скобки. Но в какой-то момент количество скобок может быть уже настолько большим, что код снова станет неудобным и непонятным. В этот момент разумнее будет разделить выражение на отдельные части. Мы научимся это делать в следующих уроках. + +[no-mixed-operators](https://eslint.org/docs/rules/no-mixed-operators) — лишь одно из большого количества правил. Другие правила описывают отступы, названия создаваемых сущностей, скобки, математические операции, длину строк и множество иных аспектов. Каждое отдельное правило кажется довольно мелким, не очень важным. Но вместе они составляют основу хорошего кода. + +Сейчас сайт не будет проверять ваш код линтером, но в ваших будущих практиках на [Хекслете](https://ru.hexlet.io) и в реальной разработке линтер будет работать и сообщать вам о нарушениях. diff --git a/modules/20-arithmetics/80-linting/ru/data.yml b/modules/20-arithmetics/80-linting/ru/data.yml new file mode 100644 index 0000000..7909b71 --- /dev/null +++ b/modules/20-arithmetics/80-linting/ru/data.yml @@ -0,0 +1,4 @@ +name: Линтер +tips: + - | + [eslint](https://eslint.org/) diff --git a/modules/25-strings/10-quotes/ru/EXERCISE.md b/modules/25-strings/10-quotes/ru/EXERCISE.md new file mode 100644 index 0000000..9ce89ad --- /dev/null +++ b/modules/25-strings/10-quotes/ru/EXERCISE.md @@ -0,0 +1,12 @@ + +Напишите программу, которая выведет на экран: + +``` +"Khal Drogo's favorite word is "athjahakar"" +``` + +Программа должна в точности вывести на экран именно эту фразу. Обратите внимание на кавычки в начале и в конце фразы: + +
+"Khal Drogo's favorite word is "athjahakar""
+
diff --git a/modules/25-strings/10-quotes/ru/README.md b/modules/25-strings/10-quotes/ru/README.md new file mode 100644 index 0000000..2ed57ef --- /dev/null +++ b/modules/25-strings/10-quotes/ru/README.md @@ -0,0 +1,87 @@ + +```javascript +'Hello' +'Goodbye' +'G' +' ' +'' +``` + +Какие из этих пяти вариантов — строки? + +С первыми двумя все понятно, это точно строки, мы уже работали с подобными конструкциями и говорили, что строки - это наборы символов. + +Любой одиночный символ в кавычках — это строка. Пустая строка `''` — это тоже строка. То есть строкой мы считаем всё, что находится внутри кавычек, даже если это пробел, один символ или вообще отсутствие символов. + +Ранее в уроках мы записывали строки в одинарных кавычках, но это не единственный способ. Можно использовать и двойные: + +```javascript +// Стандарт кодирования airbnb, рекомендует +// использовать, по возможности, одинарные +console.log("Dracarys!"); +``` + +Представьте, что вы хотите напечатать строчку _Dragon's mother_. Апостроф перед буквой **s** — это такой же символ, как одинарная кавычка. Попробуем: + +```javascript +console.log('Dragon's mother'); +// Uncaught SyntaxError: missing ) after argument list +``` + +Такая программа не будет работать. С точки зрения JavaScript, строка началась с одинарной кавычки, а потом закончилась после буквы **n**. Дальше были символы `s mother` без кавычек — значит, это не строка. А потом была одна открывающая строку кавычка, которая так и не закрылась: `');`. Этот код синтаксически некорректен (это видно даже по тому, как подсвечен код). + +Здесь нам помогут двойные кавычки. Такой вариант программы отработает корректно: + +```javascript +console.log("Dragon's mother"); +``` + +Теперь интерпретатор знает, что строка началась с двойной кавычки — значит, и закончиться должна на двойной кавычке. А одинарная кавычка внутри стала частью строки. + +Верно и обратное. Если внутри строки мы хотим использовать двойные кавычки, то саму строку надо делать в одинарных. Причем количество кавычек внутри самой строки не важно. + +А что, если мы хотим создать такую строку: + +``` +Dragon's mother said "No" +``` + +В ней есть и одинарные и двойные кавычки. Как быть в этой ситуации? Нужно каким-то образом сказать интерпретатору считать каждую кавычку частью строки, а не началом или концом строки. + +Для этого **экранируют** специальные символы. В нашем случае тот символ, который является признаком конца и начала строки, это либо одинарная кавычка, либо двойная, в зависимости от ситуации. Для экранирования используется обратный слеш `\`. + +```javascript +// Экранируется только ", так как в этой ситуации +// двойные кавычки имеют специальное значение +console.log("Dragon's mother said \"No\""); +// => Dragon's mother said "No" +``` + +Посмотрите внимательно: нам нужно было добавить `\` для двойных кавычек, но не для одинарной (апостроф), потому что сама строка создана с двойными кавычками. Если бы строка создавалась с одинарными кавычками, то символ экранирования нужен был бы перед апострофом, но не перед двойными кавычками. + +```javascript +// \ не выводится, если после него идет обычный, +// а не специальный символ +console.log("Death is \so terribly final"); +// => Death is so terribly final +``` + +А что, если нужно вывести сам обратный слеш? Точно так же, как и любой другой специальный символ, его надо экранировать самим собой. + +```javascript +console.log("\\"); +// => \ +``` + +Вопрос на самопроверку, что выведет этот код? + +```javascript +console.log("\\ \\ \\\\ \\\ \'\""); +``` + +
+Ответ + +Этот код выведет такую строку: `\ \ \\ \ '"`. + +
diff --git a/modules/25-strings/10-quotes/ru/data.yml b/modules/25-strings/10-quotes/ru/data.yml new file mode 100644 index 0000000..05fc531 --- /dev/null +++ b/modules/25-strings/10-quotes/ru/data.yml @@ -0,0 +1,5 @@ +name: Кавычки +tips: + - > + [Шаблонные + строки](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/template_strings) diff --git a/modules/25-strings/15-escape-characters/ru/EXERCISE.md b/modules/25-strings/15-escape-characters/ru/EXERCISE.md new file mode 100644 index 0000000..02e168d --- /dev/null +++ b/modules/25-strings/15-escape-characters/ru/EXERCISE.md @@ -0,0 +1,9 @@ + +Напишите программу, которая выводит на экран: + +``` +- Did Joffrey agree? +- He did. He also said "I love using \n". +``` + +При этом программа использует только один `console.log()`, но результат на экране должен выглядеть в точности, как показано выше. diff --git a/modules/25-strings/15-escape-characters/ru/README.md b/modules/25-strings/15-escape-characters/ru/README.md new file mode 100644 index 0000000..146da4f --- /dev/null +++ b/modules/25-strings/15-escape-characters/ru/README.md @@ -0,0 +1,126 @@ + +Мы хотим показать диалог Матери Драконов со своим ребёнком: + +``` +- Are you hungry? +- Aaaarrrgh! +``` + +Если вывести на экран строку с таким текстом: + +```javascript +console.log('- Are you hungry?- Aaaarrrgh!'); +``` + +то получится так: + +``` +- Are you hungry?- Aaaarrrgh! +``` + +Не то, что мы хотели. Строки расположены друг за другом, а не одна ниже другой. Нам нужно как-то сказать интерпретатору «нажать на энтер» — сделать перевод строки после вопросительного знака. Это можно сделать, используя символ перевода строки: `\n`. + +```javascript +console.log('- Are you hungry?\n- Aaaarrrgh!'); +``` + +результат: + +``` +- Are you hungry? +- Aaaarrrgh! +``` + +`\n` — это специальный символ. В литературе его часто обозначают как *LF* (Line Feed). Возможно вы сейчас подумали, что это опечатка, ведь здесь мы видим два символа `\` и `n`, но это не так. С точки зрения компьютера — это один невидимый символ перевода строки. Доказательство: + +```javascript +// Мы это не изучали, но вы должны знать правду +// Ниже код, который возвращает длину строки +'a'.length; // 1 +'\n'.length; // 1 !!! +'\n\n'.length; // 2 !!! +``` + +Почему так сделано? `\n` — всего лишь способ записать символ перевода строки, но сам перевод строки по своему смыслу – это один символ, правда, невидимый. Именно поэтому и возникла такая задача. Нужно было как-то представить его на клавиатуре. А поскольку количество знаков на клавиатуре ограничено и отдано под самые важные, то все специальные символы реализуются в виде таких обозначений. + +Символ перевода строки не является чем-то специфичным для программирования. Все, кто хоть раз печатал на компьютере, использовал перевод строки, нажимая на Enter. Во многих редакторах есть опция, позволяющая включить отображение невидимых символов — с ее помощью можно понять, где они находятся (хотя это всего лишь схематичное отображение, у этих символов нет графического представления, они невидимые): + +
+- Привет!¶
+- О, привет!¶
+- Как дела?
+
+ +Устройство, которое выводит соответствующий текст, учитывает этот символ. Например, принтер при встрече с LF протаскивает бумагу вверх на одну строку, а текстовый редактор переносит весь последующий текст ниже, также на одну строку. + +`\n` — это пример **экранирующей последовательности** (escape sequence). Их ещё называют управляющими конструкциями. Хотя таких символов не один десяток, в программировании часто встречаются всего несколько. Кроме перевода строки, к таким символам относятся табуляция (разрыв, получаемый при нажатии на кнопку Tab) и возврат каретки (только в Windows). Нам, программистам, часто нужно использовать перевод строки `\n` для правильного форматирования текста. + +```javascript +console.log('Gregor Clegane\nDunsen\nPolliver\nChiswyck'); +``` + +На экран выведется: + +``` +Gregor Clegane +Dunsen +Polliver +Chiswyck +``` + +Обратите внимание на следующие моменты: + +1. Не имеет значения, что стоит перед или после `\n`: символ или пустая строка. Перевод будет обнаружен и выполнен в любом случае. + +2. Помните, что строка может содержать один символ или вообще ноль символов. А еще строка может содержать только `\n`. Проанализируйте следующий пример: + + ```javascript + console.log('\n'); + console.log('Dunsen'); + ``` + + Здесь мы сначала выводим строку «перевод строки», а потом делаем вывод обыкновенной строки. Программа выведет на экран: + +
+    
+ Dunsen +
+ + Почему перед строкой *Dunsen* появилось две пустые строки, а не одна? Дело в том, что `console.log()` при выводе значения автоматически добавляет в конец символ перевода строки. Таким образом, один перевод строки мы указали явно, передав этот символ экранирующей последовательности аргументом в функцию, а второй перевод строки добавлен самой функцией автоматически. + + Ещё пример кода: + + ```javascript + console.log('Polliver'); + console.log('Gregor Clegane'); + console.log(); + console.log('Chiswyck'); + console.log('\n'); + console.log('Dunsen'); + ``` + + Вывод будет таким: + +
+    Polliver
+    Gregor Clegane
+ Chiswyck
+ + Dunsen +
+ + Сейчас у вас достаточно знаний, чтобы самостоятельно разобраться и понять, почему вывод сформировался именно таким образом. + +3. Если нам понадобится вывести `\n` именно как текст (два отдельных печатных символа), то можно воспользоваться уже известным нам способом экранирования, добавив еще один `\` в начале. То есть последовательность `\\n` отобразится как символы `\` и `n`, идущие друг за другом. + +```javascript +console.log('Joffrey loves using \\n'); +``` + +на экран выйдет: + +
+Joffrey loves using \n
+
+ +Небольшое, но важное замечание про Windows. В Windows для перевода строк по умолчанию используется `\r\n`. Такая комбинация хорошо работает только в Windows, но создаёт проблемы при переносе в другие системы (например, когда в команде разработчиков есть пользователи как Windows, так и Linux). Дело в том, что последовательность `\r\n` имеет разную трактовку в зависимости от выбранной кодировки (рассматривается позже). По этой причине, в среде разработчиков принято всегда использовать `\n` без `\r`, так как LF всегда трактуется одинаково и отлично работает в любой системе. Не забудьте настроить ваш редактор на использование `\n`. diff --git a/modules/25-strings/15-escape-characters/ru/data.yml b/modules/25-strings/15-escape-characters/ru/data.yml new file mode 100644 index 0000000..ec3c5fd --- /dev/null +++ b/modules/25-strings/15-escape-characters/ru/data.yml @@ -0,0 +1,13 @@ +name: Экранирующие последовательности +definitions: + - name: Экранирующая последовательность + description: > + специальная комбинация символов в тексте. Например, `\n` — это перевод + строки. +tips: + - > + Обязательно поэкспериментируйте с выводом разных строк на сайте + [https://replit.com/languages/nodejs](https://replit.com/languages/nodejs) + - > + [История перевода + строки](https://ru.wikipedia.org/wiki/Перевод_строки#История) diff --git a/modules/25-strings/20-string-concatenation/ru/EXERCISE.md b/modules/25-strings/20-string-concatenation/ru/EXERCISE.md new file mode 100644 index 0000000..0b97df9 --- /dev/null +++ b/modules/25-strings/20-string-concatenation/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Выведите на экран + +``` +Winter came for the House of Frey. +``` + +используя конкатенацию слов. diff --git a/modules/25-strings/20-string-concatenation/ru/README.md b/modules/25-strings/20-string-concatenation/ru/README.md new file mode 100644 index 0000000..cb0721b --- /dev/null +++ b/modules/25-strings/20-string-concatenation/ru/README.md @@ -0,0 +1,48 @@ + +В веб-разработке программы постоянно оперируют строками. Всё, что мы видим на сайтах, так или иначе представлено в виде текста. Этот текст чаще всего динамический, то есть полученный из разных частей, которые соединяются вместе. Операция соединения строк в программировании называется **конкатенацией**. + +```javascript +// Оператор такой же, как и при сложении чисел +// но здесь он имеет другой смысл (семантику) +console.log('Dragon' + 'stone'); +// => Dragonstone +``` + +Склеивание строк всегда происходит в том же порядке, в котором записаны операнды. Левый операнд становится левой частью строки, а правый — правой. + +Вот еще несколько примеров: + +```javascript +console.log('Kings' + 'wood'); // => Kingswood + +// Обратный порядок слов +console.log('road' + 'Kings'); // => roadKings + +// Конкатенировать можно абсолютно любые строки +console.log("King's" + 'Landing'); // => King'sLanding +``` + +Как видите, строки можно склеивать, даже если они записаны с разными кавычками. + +В последнем примере название города получилось с ошибкой: *King's Landing* нужно писать через пробел. Но в наших начальных строках не было пробелов, а пробелы в самом коде слева и справа от символа `+` не имеют значения, потому что они не являются частью строк. + +Выхода из этой ситуации два: + +```javascript +// Оба способа равнозначны + +// Ставим пробел в левой части +console.log("King's " + 'Landing'); // => King's Landing +// Ставим пробел в правой части +console.log("King's" + ' Landing'); // => King's Landing +``` + +Пробел — такой же символ, как и другие. Чем больше пробелов, тем шире отступы: + +```javascript +console.log("King's " + ' Landing'); // => King's Landing + +console.log("King's " + ' Landing'); // => King's Landing +``` + +https://replit.com/@hexlet/js-basics-strings diff --git a/modules/25-strings/20-string-concatenation/ru/data.yml b/modules/25-strings/20-string-concatenation/ru/data.yml new file mode 100644 index 0000000..9a53953 --- /dev/null +++ b/modules/25-strings/20-string-concatenation/ru/data.yml @@ -0,0 +1,10 @@ +name: Конкатенация +tips: + - > + Если в редакторе есть запись `// BEGIN` и `// END`, то код нужно писать + между этими строчками. +definitions: + - name: Конкатенация + description: > + операция соединения двух строк. Например, `console.log("King's " + ' + Landing');` diff --git a/modules/25-strings/30-encoding/ru/EXERCISE.md b/modules/25-strings/30-encoding/ru/EXERCISE.md new file mode 100644 index 0000000..b6e7f9c --- /dev/null +++ b/modules/25-strings/30-encoding/ru/EXERCISE.md @@ -0,0 +1,16 @@ + +В JavaScript можно «запросить» и вывести на экран любой символ из кодировки ASCII. Например: + +```javascript +console.log(String.fromCharCode(63)); +``` + +На экран выведется символ с номером 63 — вопросительный знак `?`. Таким способом можно выводить любой символ. + +https://replit.com/@hexlet/js-basics-strings-encoding + +Найдите в интернете таблицу кодов ASCII. Можно использовать запросы типа "ascii codes table" или «коды ascii». Обычно в таких таблицах коды указаны сразу в нескольких системах счисления: десятичной, двоичной, восьмеричной и шестнадцатеричной. Нас интересует десятичный код (*dec* или *decimal*). + +Используя пример выше и найденную таблицу, выведите на экран символы `~`, `^` и `%` (каждый на своей собственной строке). + +(Конечно, можно «обмануть» тесты и просто сделать что-то типа `console.log('~')`, но так будет совсем неинтересно :) diff --git a/modules/25-strings/30-encoding/ru/README.md b/modules/25-strings/30-encoding/ru/README.md new file mode 100644 index 0000000..fa65857 --- /dev/null +++ b/modules/25-strings/30-encoding/ru/README.md @@ -0,0 +1,37 @@ + +На самом глубоком уровне компьютер оперирует исключительно цифрами `0` и `1`. Это так называемый [двоичный код](https://ru.wikipedia.org/wiki/Двоичный_код), а единички и нули называются битами, от "binary digit" — «двоичная цифра». + +Обычные, привычные нам числа в десятичной системе счисления, закодированы с помощью двоичных чисел: + +- 0 ← 0 +- 1 ← 1 +- 2 ← 10 +- 3 ← 11 +- 4 ← 100 +- 5 ← 101 + +Но как быть с текстом? Компьютер на самом деле не знает ничего о буквах, знаках пунктуации и прочих текстовых символах. Все эти символы также закодированы числами. + +Можно взять английский алфавит и дать каждой букве число, начиная с единицы по порядку: + +- a ← 1 +- b ← 2 +- c ← 3 +- d ← 4 +- ... +- z ← 26 + +Далее можно научить компьютер понимать эту таблицу и переводить текст в числа и наоборот — числа в текст: + +- `hello` → `8` `5` `12` `12` `15` +- `7` `15` `15` `4` → `good` + +Подобные таблицы, в которых сопоставляются буквы и числа, называются кодировками. Кроме букв алфавита, в таблицы кодировок входят знаки препинания и другие полезные символы. Вы наверняка сталкивались с кодировками, например, [ASCII](https://ru.wikipedia.org/wiki/ASCII) или [UTF-8](https://ru.wikipedia.org/wiki/UTF-8). + +Разные кодировки содержат различное количество символов. Изначально небольших таблиц вроде ASCII было достаточно для большинства задач. Но в ней есть только латинские буквы, несколько простых символов вроде `%` и `?` и специальные управляющие символы типа перевода строки. + +С распространением компьютеров, разным странам понадобились свои, более широкие таблицы. В том числе для кириллических букв, иероглифов, арабской вязи, дополнительных математических и типографских символов, а впоследствии — даже для эмодзи-смайликов. + +Сегодня в большинстве случаев используется один из вариантов [юникода](https://ru.wikipedia.org/wiki/Юникод) — *utf-8*. Он включает в себя знаки почти всех письменных языков мира. Благодаря этому, письмо, сформированное человеком в Китае на китайском, без проблем можно открыть и увидеть в первозданном виде на компьютере в Финляндии (поймет он его или нет, это уже другой вопрос). + +С кодированием текста и кодировками программисты встречаются в своей жизни регулярно. Поддержка юникода у разных языков программирования выполнена на разном уровне. Кроме того, кодировки нужно явно указывать при работе и с базами данных, и с файлами. diff --git a/modules/25-strings/30-encoding/ru/data.yml b/modules/25-strings/30-encoding/ru/data.yml new file mode 100644 index 0000000..a0ce3ed --- /dev/null +++ b/modules/25-strings/30-encoding/ru/data.yml @@ -0,0 +1,9 @@ +name: Кодировка +tips: + - | + [Что такое кодировки?](https://guides.hexlet.io/ru/encoding/) +definitions: + - name: Кодировка + description: >- + набор символов, закодированных с помощью чисел для представления текста в + электронном виде. diff --git a/modules/30-variables/10-definition/ru/EXERCISE.md b/modules/30-variables/10-definition/ru/EXERCISE.md new file mode 100644 index 0000000..a112dab --- /dev/null +++ b/modules/30-variables/10-definition/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Создайте переменную с именем `motto` и содержимым `What Is Dead May Never Die!`. Распечатайте содержимое переменной. diff --git a/modules/30-variables/10-definition/ru/README.md b/modules/30-variables/10-definition/ru/README.md new file mode 100644 index 0000000..32fa509 --- /dev/null +++ b/modules/30-variables/10-definition/ru/README.md @@ -0,0 +1,49 @@ + +Представьте себе задачу: нам нужно напечатать на экран фразу *Father!* два раза или даже пять раз. Эту задачу можно решить в лоб: + +```javascript +console.log('Father!'); +console.log('Father!'); +``` + +В простейшем случае так и стоит поступить, но если фраза *Father!* начнет использоваться чаще, да еще и в разных частях программы, то придется ее везде повторять. Проблемы с таким подходом начнутся тогда, когда понадобится изменить нашу фразу, а такое происходит довольно часто. Нам придется найти все места, где использовалась фраза *Father!*, и выполнить необходимую замену. А можно поступить по-другому. Вместо копирования нашего выражения достаточно создать переменную с этой фразой. + +```javascript +// greeting - переводится как приветствие +let greeting = 'Father!'; +console.log(greeting); // => Father! +console.log(greeting); // => Father! +``` + +Переменная указывает на данные, которые были в неё записаны. Благодаря этому, данные можно использовать многократно без необходимости их постоянно дублировать. Сама переменная создается и наполняется данными (инициализируется) с помощью инструкции `let greeting = 'Father!'`. + +Для имени переменной используется любой набор допустимых символов, к которым относятся буквы английского алфавита, цифры, а также знаки *_* и *$*. При этом цифру нельзя ставить в начале. Имена переменных регистрозависимы, то есть имя `hello` и имя `heLLo` - это два разных имени, а значит и две переменные. Регистр в JavaScript имеет важное значение, никогда не забывайте про него. + +Переменную не обязательно инициализировать данными во время объявления. Иногда бывает нужно ее создать, а наполняться она будет потом: + +```javascript +let greeting; + +// Использование +console.log(greeting); // undefined + +// Изменение переменной в следующем уроке +``` + +Объявленная, но не инициализированная переменная, содержит внутри себя значение `undefined`. Это специальное значение, используемое тогда, когда ничего не определено. + +Количество создаваемых переменных ничем не ограничено, большие программы содержат десятки и сотни тысяч имен переменных: + +```javascript +let greeting1 = 'Father!'; +console.log(greeting1); +console.log(greeting1); + +let greeting2 = 'Mother!'; +console.log(greeting2); +console.log(greeting2); +``` + +https://replit.com/@hexlet/js-basics-variables-definition + +Для удобства анализа программы, переменные принято создавать как можно ближе к тому месту, где они используются. diff --git a/modules/30-variables/10-definition/ru/data.yml b/modules/30-variables/10-definition/ru/data.yml new file mode 100644 index 0000000..d4f5eac --- /dev/null +++ b/modules/30-variables/10-definition/ru/data.yml @@ -0,0 +1,9 @@ +name: Что такое переменная +tips: + - > + [let](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/let) +definitions: + - name: Переменная + description: >- + способ сохранить информацию и дать ей имя для последующего использования в + коде. diff --git a/modules/30-variables/11-change/ru/EXERCISE.md b/modules/30-variables/11-change/ru/EXERCISE.md new file mode 100644 index 0000000..4371511 --- /dev/null +++ b/modules/30-variables/11-change/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +В упражнении определена переменная, внутри которой находится строка. Переопределите значение этой переменной и присвойте ей ту же строку, но в перевернутом виде, т.е. расположите символы первоначальной строки в обратном порядке. diff --git a/modules/30-variables/11-change/ru/README.md b/modules/30-variables/11-change/ru/README.md new file mode 100644 index 0000000..cf430d2 --- /dev/null +++ b/modules/30-variables/11-change/ru/README.md @@ -0,0 +1,16 @@ + +Само слово "переменная" говорит о том, что ее можно менять. И действительно, с течением времени внутри программы значения переменных могут изменяться. + +```javascript +let greeting = 'Father!'; +console.log(greeting); +console.log(greeting); + +greeting = 'Mother!'; +console.log(greeting); +console.log(greeting); +``` + +https://replit.com/@hexlet/js-basics-variables-change + +Имя осталось тем же, но внутри другие данные. Обратите внимание на ключевое различие между объявлением переменной и ее изменением. Ключевое слово `let` ставится только при создании переменной, но при изменении оно уже не используется. diff --git a/modules/30-variables/11-change/ru/data.yml b/modules/30-variables/11-change/ru/data.yml new file mode 100644 index 0000000..3284d02 --- /dev/null +++ b/modules/30-variables/11-change/ru/data.yml @@ -0,0 +1,6 @@ +name: Изменение переменной +definitions: + - name: Переменная + description: >- + способ сохранить информацию и дать ей имя для последующего использования в + коде. diff --git a/modules/30-variables/13-variables-naming/ru/EXERCISE.md b/modules/30-variables/13-variables-naming/ru/EXERCISE.md new file mode 100644 index 0000000..9aaae9c --- /dev/null +++ b/modules/30-variables/13-variables-naming/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Создайте переменную, описывающую дословно "количество моих братьев", и присвойте ей значение *2*. Распечатайте содержимое переменной. После успешной проверки сравните своё имя с именем, которое используется в учительском решении. diff --git a/modules/30-variables/13-variables-naming/ru/README.md b/modules/30-variables/13-variables-naming/ru/README.md new file mode 100644 index 0000000..c230f17 --- /dev/null +++ b/modules/30-variables/13-variables-naming/ru/README.md @@ -0,0 +1,36 @@ + +Представим себе, что программа из прошлого урока выглядит так: + +```javascript +let x = 'Father!'; +console.log(x); +console.log(x); +``` + +Она по прежнему работает, но в ней изменилось имя переменной на `x`. Компьютеру без разницы, как мы называем переменные, это бездушная машина, но вот программистам — нет. Мы гораздо чаще читаем код, чем пишем. Причём не свой, а написанный другими людьми. От качества и понятности имён переменных зависит половина успеха в анализе кода. + +Лучше посидеть и придумать название, которое описывает суть, смысл переменной, чем назвать её как попало, а в будущем переделывать. Постарайтесь давать им такие имена, чтобы они были максимально понятны без контекста, без изучения окружающего кода. + +Существует общепринятое правило: не используйте транслит для имён, только английский язык. Если вы испытываете сложности с английским, то пользуйтесь переводчиком. Со временем, копаясь в чужом коде, вы сформируете правильные понятия для именования. + +Среди разработчиков есть шутка: «самое сложное в программировании — названия переменных и инвалидация кеша». Придумывать названия и правда сложно. Как бы вы назвали переменную, в которой хранится *количество неоплаченных заказов от клиентов, имеющих задолженность в предыдущем квартале?* + +
+Ответ + +Правильного и однозначного ответа на этот вопрос нет. Например, можно использовать название `unpaidOrdersFromDebtorsInPreviousQuarterCount`. + +Это имя хорошо описывает содержание переменной и позволяет легко идентифицировать ее смысл в коде. При этом оно слишком длинное и сложное, поэтому лучше использовать более краткое имя — например, `unpaidOrdersFromDebtorsCount` или `debtorsUnpaidOrdersCount`. В общем, выбор имени для переменной зависит от контекста использования. +
+ +В JavaScript в именах констант и переменных каждое слово пишется с заглавной буквы, кроме первого. Например: + +```javascript +const firstName = 'John'; +console.log(firstName); // => John + +const playerNumber = 24; +console.log(playerNumber); // => 24 +``` + +Самопроверка. Придумайте название для переменной, в которой будет храниться *«количество братьев и сестёр короля»*. Запишите его в блокноте или отправьте себе на почту. Не указывайте там ничего, кроме названия переменной. А через несколько уроков мы вернёмся к этой теме ;-) diff --git a/modules/30-variables/13-variables-naming/ru/data.yml b/modules/30-variables/13-variables-naming/ru/data.yml new file mode 100644 index 0000000..2bf9b42 --- /dev/null +++ b/modules/30-variables/13-variables-naming/ru/data.yml @@ -0,0 +1,13 @@ +name: Выбор имени переменной +tips: + - > + [Именование в + программировании](https://ru.hexlet.io/blog/posts/naming-in-programming) + - > + [Ошибки в именовании + переменных](https://ru.hexlet.io/blog/posts/naming-errors-1) +definitions: + - name: Переменная + description: >- + способ сохранить информацию и дать ей имя для последующего использования в + коде. diff --git a/modules/30-variables/14-errors/ru/EXERCISE.md b/modules/30-variables/14-errors/ru/EXERCISE.md new file mode 100644 index 0000000..6c3aaa2 --- /dev/null +++ b/modules/30-variables/14-errors/ru/EXERCISE.md @@ -0,0 +1,10 @@ + +Найдите в программе необъявленную переменную и объявите ее, присвоив ей значение 'Dragon'; + +После выполнения программы результат на экране должен выглядеть так: + +
+Targaryen
+and
+Dragon
+
diff --git a/modules/30-variables/14-errors/ru/README.md b/modules/30-variables/14-errors/ru/README.md new file mode 100644 index 0000000..51b64e0 --- /dev/null +++ b/modules/30-variables/14-errors/ru/README.md @@ -0,0 +1,21 @@ + +Порядок следования инструкций в коде с переменными играет огромное значение. Переменная должна быть определена до того, как будет использована. Ниже пример ошибки, которую очень часто допускают новички: + +```javascript +// Uncaught ReferenceError: greeting is not defined +console.log(greeting); +let greeting = 'Father!'; +``` + +Запуск программы с примера выше завершается ошибкой *ReferenceError: greeting is not defined*. *ReferenceError* - это ошибка обращения, она означает, что в коде используется имя (говорят идентификатор), которое не определено. Причём в самой ошибке об этом говорят прямо: *greeting is not defined*, что переводится как *greeting не определен*. Кроме неправильного порядка определения, в JavaScript встречаются банальные опечатки — как при использовании переменной, так и при её объявлении. + +Количество подобных ошибок уменьшается за счет использования правильно настроенного редактора. Такой редактор подсвечивает имена, которые используются без объявления и предупреждает о возможных проблемах. + +Еще одна распространенная ошибка — попытаться объявить уже объявленную переменную: + +```javascript +let greeting = 'Father!'; +let greeting = 'Father!'; +``` + +Так делать нельзя. Придётся создать новую переменную. diff --git a/modules/30-variables/14-errors/ru/data.yml b/modules/30-variables/14-errors/ru/data.yml new file mode 100644 index 0000000..62f3e5c --- /dev/null +++ b/modules/30-variables/14-errors/ru/data.yml @@ -0,0 +1,9 @@ +name: Ошибки при работе с переменными +tips: + - > + [ReferenceError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError) +definitions: + - name: Переменная + description: >- + способ сохранить информацию и дать ей имя для последующего использования в + коде. diff --git a/modules/30-variables/15-variables-expressions/ru/EXERCISE.md b/modules/30-variables/15-variables-expressions/ru/EXERCISE.md new file mode 100644 index 0000000..ace4412 --- /dev/null +++ b/modules/30-variables/15-variables-expressions/ru/EXERCISE.md @@ -0,0 +1,13 @@ + +Напишите программу, которая берет исходное количество евро, записанное в переменную `eurosCount`, переводит евро в доллары и выводит на экран. Затем полученное значение переводит в юани и выводит на новой строчке. + +Пример вывода для 100 евро: + +
+125
+7500
+
+ +Считаем, что: +- 1 евро = 1.25 долларов +- 1 доллар = 6.91 юаней diff --git a/modules/30-variables/15-variables-expressions/ru/README.md b/modules/30-variables/15-variables-expressions/ru/README.md new file mode 100644 index 0000000..4828755 --- /dev/null +++ b/modules/30-variables/15-variables-expressions/ru/README.md @@ -0,0 +1,70 @@ + +Переменные полезны не только для хранения и переиспользования информации, но и для упрощения сложных вычислений. Давайте рассмотрим пример: нужно перевести евро в юани через доллары. Подобные конвертации через промежуточную валюту часто делают банки при покупках за рубежом. + +Для начала переведем 50 евро в доллары. Допустим, что один евро — 1.25 долларов: + +```javascript +let dollarsCount = 50 * 1.25; +console.log(dollarsCount); // => 62.5 +``` + +В предыдущем уроке мы записывали в переменную конкретное значение. А здесь `let dollarsCount = 50 * 1.25;` справа от знака равно находится **выражение**. Интерпретатор вычислит результат — `62.5` — и запишет его в переменную. С точки зрения интерпретатора не важно, что перед ним: `62.5` или `50 * 1.25`, для него оба варианта — выражения, которые надо вычислить. И они вычисляются в одно и тоже значение — `62.5`. + +Любая строка — выражение. Конкатенация строк — тоже выражение. Когда интерпретатор видит выражение, он обрабатывает его и генерирует результат — **значение выражения**. Вот несколько примеров выражений, а в комментариях справа от каждого выражения — итоговое значение: + +```javascript +62.5 // 62.5 +50 * 1.25 // 62.5 +120 / 10 * 2 // 24 + +'hello' // hello +'Good' + 'will' // Goodwill +``` + +Правила построения кода (грамматика языка) таковы, что в тех местах, где ожидается выражение, можно поставить любое вычисление (не только математическое, но и, например, строковое — как конкатенация), и программа останется работоспособной. По этой причине невозможно описать и показать все случаи использования всех операций. + +Программы состоят из множества комбинаций выражений, и понимание этой концепции — один из ключевых шагов на вашем пути. + +Основываясь на сказанном выше, подумайте, сработает ли такой код? + +```javascript +let who = "dragon's" + 'mother'; +console.log(who); +``` + +Запустите его на [repl.it](https://repl.it/languages/javascript) и поэкспериментируйте. + +
+Ответ + +Да, сработает. Будет выведена строка `dragon'smother`. + +
+ +Вернемся к нашей валютной программе. Запишем стоимость доллара в юанях как отдельную переменную. Вычислим цену 50 евро в долларах, умножив их на `1.25`. Допустим, что 1 доллар — 6.91 юаней: + +```javascript +let yuansPerDollar = 6.91; +let dollarsCount = 50 * 1.25; // 62.5 +let yuansCount = dollarsCount * yuansPerDollar; // 431.875 + +console.log(yuansCount); +``` + +А теперь давайте добавим к выводу текст с помощью конкатенации: + +```javascript +let yuansPerDollar = 6.91; +let dollarsCount = 50 * 1.25; // 62.5 +let yuansCount = dollarsCount * yuansPerDollar; // 431.875 + +console.log('The price is ' + yuansCount + ' yuans'); +``` + +
+The price is 431.875 yuans
+
+ +Любая переменная может быть частью любого выражения. В момент вычисления, вместо имени переменной подставляется её значение. + +Интерпретатор вычисляет значение `dollarsCount` до того, как эта переменная начнет использоваться в других выражениях. Когда подходит момент использования переменной, Javascript «знает» значение, потому что уже вычислил его. diff --git a/modules/30-variables/15-variables-expressions/ru/data.yml b/modules/30-variables/15-variables-expressions/ru/data.yml new file mode 100644 index 0000000..3d1fc4b --- /dev/null +++ b/modules/30-variables/15-variables-expressions/ru/data.yml @@ -0,0 +1,9 @@ +name: Выражения в определениях +tips: + - | + [Выражение](https://ru.wikipedia.org/wiki/Выражение_(информатика)) +definitions: + - name: Переменная + description: >- + способ сохранить информацию и дать ей имя для последующего использования в + коде. diff --git a/modules/30-variables/18-variable-concatenation/ru/EXERCISE.md b/modules/30-variables/18-variable-concatenation/ru/EXERCISE.md new file mode 100644 index 0000000..9cb066e --- /dev/null +++ b/modules/30-variables/18-variable-concatenation/ru/EXERCISE.md @@ -0,0 +1,18 @@ + +Сайты постоянно посылают письма своим пользователям. Типичная задача — сделать автоматическую отправку персонального письма, где в заголовке будет имя пользователя. Если где-то в базе сайта хранится имя человека в виде строки, то задача генерации заголовка сводится к конкатенации: например, нужно склеить строку `Здравствуйте` со строкой, где записано имя. + +Напишите программу, которая будет генерировать заголовок и тело письма, используя уже готовые переменные, и выводить получившиеся строки на экран. + +Для заголовка используйте переменные `firstName` и `greeting`, запятую и восклицательный знак. Выведите это на экран в правильном порядке. + +Для тела письма используйте переменные `info` и `intro`, при этом второе предложение должно быть на новой строке. + +Результат на экране будет выглядеть так: + +
+Hello, Joffrey!
+Here is important information about your account security.
+We couldn't verify your mother's maiden name.
+
+ +Выполните задание, используя только два `console.log()`. diff --git a/modules/30-variables/18-variable-concatenation/ru/README.md b/modules/30-variables/18-variable-concatenation/ru/README.md new file mode 100644 index 0000000..b850866 --- /dev/null +++ b/modules/30-variables/18-variable-concatenation/ru/README.md @@ -0,0 +1,28 @@ + +Для закрепления предыдущей темы, попробуем использовать переменные с конкатенацией. Синтаксически ничего не меняется: мы умеем конкатенировать (склеивать) две строки: + +```javascript +let what = 'Kings' + 'road'; +console.log(what); // => Kingsroad +``` + +… а значит сумеем конкатенировать строку и одну переменную, в которой записана строка: + +```javascript +let first = 'Kings'; +let what = first + 'road'; + +console.log(what); // => Kingsroad +``` + +… и даже конкатенировать две переменные, в которых записаны строки: + +```javascript +let first = 'Kings'; +let last = 'road'; + +let what = first + last; +console.log(what); // => Kingsroad +``` + +https://replit.com/@hexlet/variables-expression diff --git a/modules/30-variables/18-variable-concatenation/ru/data.yml b/modules/30-variables/18-variable-concatenation/ru/data.yml new file mode 100644 index 0000000..a8708d1 --- /dev/null +++ b/modules/30-variables/18-variable-concatenation/ru/data.yml @@ -0,0 +1,13 @@ +name: Переменные и конкатенация +tips: + - > + Подумайте, с какой строкой и в каком порядке нужно склеивать переменные, + чтобы получить такой двухстрочный вывод тела письма. + - > + Помните, что можно создать строку, которая содержит только управляющую + последовательность `\n`. +definitions: + - name: Конкатенация + description: > + операция соединения двух строк. Например, `console.log("King's " + ' + Landing');` diff --git a/modules/30-variables/19-naming-style/ru/EXERCISE.md b/modules/30-variables/19-naming-style/ru/EXERCISE.md new file mode 100644 index 0000000..1ba3540 --- /dev/null +++ b/modules/30-variables/19-naming-style/ru/EXERCISE.md @@ -0,0 +1,4 @@ + +Создайте две переменные с именами «первое число» и «второе число» на английском языке, используя lowerCamelCase. Запишите в первую переменную число `11`, во вторую — `-100`. Выведите на экран произведение чисел, записанных в получившихся переменных. + +Код будет работать с любыми названиями, а наша система всегда проверяет только результат на экране, поэтому выполнение этого задания — под вашу ответственность. diff --git a/modules/30-variables/19-naming-style/ru/README.md b/modules/30-variables/19-naming-style/ru/README.md new file mode 100644 index 0000000..1ef53b2 --- /dev/null +++ b/modules/30-variables/19-naming-style/ru/README.md @@ -0,0 +1,11 @@ + +`greeting` — пример простого имени, но не все имена так просты. Довольно часто они составные, то есть включают в себя несколько слов. Например, «имя пользователя». В разных языках применяются разные стили кодирования, и имя переменной будет отличаться. + +В именовании переменных можно выделить четыре основных подхода, которые иногда комбинируют друг с другом. Все эти подходы проявляют себя, когда имя переменной состоит из нескольких слов: + +* kebab-case — составные части переменной разделяются дефисом. Например: `my-super-var`. +* snake_case — для разделения используется подчеркивание. Например: `my_super_var`. +* CamelCase — каждое слово в переменной пишется с заглавной буквы. Например: `MySuperVar`. +* lowerCamelCase — каждое слово в переменной пишется с заглавной буквы, кроме первого. Например: `mySuperVar`. + +В Javascript используется CamelCase и его вариация lowerCamelCase, при котором первая буква первого слова — строчная. Именно lowerCamelCase применяется для переменных. Это значит, что имена соединяются друг с другом, при этом все имена кроме первого становятся с заглавной буквы: `userName`. С тремя словами это выглядит так: `mySuperVariable`. diff --git a/modules/30-variables/19-naming-style/ru/data.yml b/modules/30-variables/19-naming-style/ru/data.yml new file mode 100644 index 0000000..89f0e6c --- /dev/null +++ b/modules/30-variables/19-naming-style/ru/data.yml @@ -0,0 +1,7 @@ +name: Стили именования +tips: + - | + [CamelCase](https://ru.wikipedia.org/wiki/CamelCase) +definitions: + - name: Стандарт кодирования + description: Набор синтаксических и стилистических правил написания кода. diff --git a/modules/30-variables/20-magic-numbers/ru/EXERCISE.md b/modules/30-variables/20-magic-numbers/ru/EXERCISE.md new file mode 100644 index 0000000..e7f6237 --- /dev/null +++ b/modules/30-variables/20-magic-numbers/ru/EXERCISE.md @@ -0,0 +1,23 @@ + +Вы столкнулись с таким кодом, который выводит на экран общее количество комнат во владении нынешнего короля: + +```javascript +let king = 'King Balon the 6th'; +console.log(king + ' has ' + (6 * 17) + ' rooms.'); +``` + +Как видите, это магические числа: непонятно, что такое 6 и что такое 17. Можно догадаться, если знать историю королевской семьи: каждый новый король получает в наследство все замки от предков и строит новый замок — точную копию родительского. + +Эта странная династия просто плодит одинаковые замки… + +Избавьтесь от магических чисел, создав новые переменные, и выведите текст на экран. + +Получится так: + +
+King Balon the 6th has 102 rooms.
+
+ +Названия переменных должны передавать смысл чисел, но должны при этом оставаться достаточно короткими и ёмкими для комфортного чтения. + +Помните: код будет работать с любыми названиями, а наша система всегда проверяет только результат на экране, поэтому выполнение этого задания — под вашу ответственность. diff --git a/modules/30-variables/20-magic-numbers/ru/README.md b/modules/30-variables/20-magic-numbers/ru/README.md new file mode 100644 index 0000000..60521fa --- /dev/null +++ b/modules/30-variables/20-magic-numbers/ru/README.md @@ -0,0 +1,31 @@ + +Вспомним один из прошлых уроков: + +```javascript +let dollarsCount = 50 * 1.25; // 62.5 +let rublesCount = dollarsCount * 60; // 3750 + +console.log(rublesCount); +``` + +С точки зрения профессиональной разработки, такой код «пахнет». Так описывают код, который сложен для понимания. И причина здесь вот в чем: уже сейчас, глядя на число `60` и `1.25`, вы скорее всего задаетесь вопросом: «что это за числа?». А представьте, что будет через месяц! А как его поймет новый программист, не видевший код ранее? В нашем примере контекст восстанавливается благодаря грамотному именованию, но в реальной жизни код значительно сложнее, и догадаться до смысла чисел зачастую невозможно. + +Этот «запах» вызывают Magic Numbers (магические числа). Числа, происхождение которых невозможно понять без глубокого знания происходящего внутри данного участка кода. + +Выход из ситуации прост: достаточно создать переменные с правильными именами, как все встанет на свои места. + +```javascript +let dollarsPerEuro = 1.25; +let rublesPerDollar = 60; + +let dollarsCount = 50 * dollarsPerEuro; // 62.5 +let rublesCount = dollarsCount * rublesPerDollar; // 3750 + +console.log(rublesCount); +``` + +Обратите внимание на следующие детали: + +* Именование lowerCamelCase. +* Две новые переменные отделены от последующих вычислений пустой строчкой. Эти переменные имеют смысл и без вычислений, поэтому такое отделение уместно, оно повышает читаемость. +* Получился хорошо именованный и структурированный код, но он длиннее прошлой версии. Так часто бывает, и это нормально. Код должен быть читабельным. diff --git a/modules/30-variables/20-magic-numbers/ru/data.yml b/modules/30-variables/20-magic-numbers/ru/data.yml new file mode 100644 index 0000000..37265ec --- /dev/null +++ b/modules/30-variables/20-magic-numbers/ru/data.yml @@ -0,0 +1,5 @@ +name: Магические числа +tips: + - > + [Магические + числа](https://ru.wikipedia.org/wiki/Магическое_число_(программирование)) diff --git a/modules/30-variables/23-constants/ru/EXERCISE.md b/modules/30-variables/23-constants/ru/EXERCISE.md new file mode 100644 index 0000000..3371830 --- /dev/null +++ b/modules/30-variables/23-constants/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Создайте константу `army`, присвойте ей значение `the white walkers` и распечатайте её значение на экран. diff --git a/modules/30-variables/23-constants/ru/README.md b/modules/30-variables/23-constants/ru/README.md new file mode 100644 index 0000000..442d833 --- /dev/null +++ b/modules/30-variables/23-constants/ru/README.md @@ -0,0 +1,42 @@ + +Во всем модуле подавляющее большинство примеров кода использовало переменные в качестве имен (псевдонимы) конкретных значений, а не как переменные, которые меняют свое значение со временем. + +```javascript +let dollarsInEuro = 1.25; +let rublesInDollar = 60; + +let dollarsCount = 50 * dollarsInEuro; // 62.5 +let rublesCount = dollarsCount * rublesInDollar; // 3750 + +console.log(rublesCount); +``` + +В программировании принято называть такие имена константами, и многие языки поддерживают константы как конструкцию. JavaScript, как раз, относится к таким языкам, и его стандарты кодирования [говорят прямо](https://eslint.org/docs/rules/prefer-const) — если значение не меняется, то мы имеем дело с константой. Перепишем пример выше на использование констант: + +```javascript +const dollarsInEuro = 1.25; +const rublesInDollar = 60; + +const euros = 1000; +const dollars = euros * dollarsInEuro; // 1250 +const rubles = dollars * rublesInDollar; // 75000 + +console.log(rubles); +``` + +https://replit.com/@hexlet/js-basics-variables + +Единственное изменение заключается в том, что ключевое слово `let` заменилось на `const`, но это только синтаксис. Теперь, если попытаться изменить любую константу, то мы получим сообщение об ошибке. В остальном они используются точно так же, как и переменные. + +```javascript +const pi = 3.14; +pi = 5; // TypeError: Assignment to constant variable. +``` + +Зачем такие сложности? Почему бы не оставить только переменные? Даже если бы мы оставили только переменные, то это не отменяет того факта, что они часто использовались бы как константы, более того, код на JavaScript можно и идиоматично писать без использования переменных вообще. Посмотрите на пример из [реального кода Хекслета](https://github.com/Hexlet/hexlet-exercise-kit/blob/main/import-documentation/index.js). На текущем этапе вы его вряд ли поймете, но попробуйте посчитать количество констант и переменных внутри него, вы увидите, что здесь ровно одна переменная, и целая куча констант. + +Константы значительно проще для анализа, когда мы видим константу в коде, то нам сразу понятно, что ее значение всегда остается прежним. При использовании констант отсутствует понятие времени. С переменными все не так, мы не можем быть уверены в их значении, приходится анализировать весь код, чтобы понять, как они могли измениться. + +Переменные жизненно необходимы только в одном случае (во всех остальных гарантировано можно обойтись без них) - при работе с циклами, до которых мы ещё дойдем. + +В дальнейшем мы будем предпочитать константы и использовать переменные только тогда, когда без них никак. diff --git a/modules/30-variables/23-constants/ru/data.yml b/modules/30-variables/23-constants/ru/data.yml new file mode 100644 index 0000000..3e7b77e --- /dev/null +++ b/modules/30-variables/23-constants/ru/data.yml @@ -0,0 +1,6 @@ +name: Константы +tips: + - > + [const](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) + - > + [TypeError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError) diff --git a/modules/30-variables/25-interpolation/ru/EXERCISE.md b/modules/30-variables/25-interpolation/ru/EXERCISE.md new file mode 100644 index 0000000..2acc54b --- /dev/null +++ b/modules/30-variables/25-interpolation/ru/EXERCISE.md @@ -0,0 +1,6 @@ + +Выведите на экран строку `Do you want to eat, ?`, где вместо `` должна использоваться константа `stark`. Вывод должен получиться таким: + +
+Do you want to eat, Arya?
+
diff --git a/modules/30-variables/25-interpolation/ru/README.md b/modules/30-variables/25-interpolation/ru/README.md new file mode 100644 index 0000000..5f31fd9 --- /dev/null +++ b/modules/30-variables/25-interpolation/ru/README.md @@ -0,0 +1,34 @@ + +В уроке про конкатенацию перед нами стояла задача создать заголовок письма из двух констант и знаков препинания. Вы, скорее всего, решили задачу так: + +```javascript +const firstName = 'Joffrey'; +const greeting = 'Hello'; + +console.log(greeting + ', ' + firstName + '!'); +// => Hello, Joffrey! +``` + +Это довольно простой случай, но даже здесь нужно приложить усилия, чтобы увидеть, какая в итоге получится строка. Нужно следить за несколькими кавычками и пробелами, и без вглядывания не понять, где что начинается и кончается. + +Есть другой, более удобный и изящный способ решения той же задачи — **интерполяция**. Вот, как это выглядит: + +```javascript +const firstName = 'Joffrey'; +const greeting = 'Hello'; + +// Обратите внимание на ограничители строки, это бектики +// Интерполяция не работает с одинарными и двойными кавычками +console.log(`${greeting}, ${firstName}!`); +// => Hello, Joffrey! +``` + +https://replit.com/@hexlet/js-basics-interpolation + +Мы просто создали одну строку и «вставили» в неё в нужные места константы с помощью знака доллара и фигурных скобок `${ }`. Получился как будто бланк, куда внесены нужные значения. И нам не нужно больше заботиться об отдельных строках для знаков препинания и пробелов — все эти символы просто записаны в этой строке-шаблоне. + +В одной строке можно делать сколько угодно подобных блоков. + +Интерполяция работает только со строками в [бэктиках](https://ru.wikipedia.org/wiki/Машинописный_обратный_апостроф). Это символ `. + +Почти во всех языках интерполяция предпочтительнее конкатенации для объединения строк. Строка при этом получается склеенная, и внутри неё хорошо просматриваются пробелы и другие символы. Во-первых, интерполяция позволяет не путать строки с числами (из-за знака +), а во-вторых, так гораздо проще (после некоторой практики) понимать строку целиком. diff --git a/modules/30-variables/25-interpolation/ru/data.yml b/modules/30-variables/25-interpolation/ru/data.yml new file mode 100644 index 0000000..20b3444 --- /dev/null +++ b/modules/30-variables/25-interpolation/ru/data.yml @@ -0,0 +1,10 @@ +name: Интерполяция +tips: + - > + [Шаблонные + строки](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/template_strings) +definitions: + - name: Интерполяция + description: >- + способ соединения строк через вставку значений переменных в строку-шаблон + с помощью фигурных скобок. Например, `` `Hi, ${name}!` ``. diff --git a/modules/30-variables/30-symbols/ru/EXERCISE.md b/modules/30-variables/30-symbols/ru/EXERCISE.md new file mode 100644 index 0000000..d79f9e0 --- /dev/null +++ b/modules/30-variables/30-symbols/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Выведите на экран последний символ строки, находящейся в константе `name` diff --git a/modules/30-variables/30-symbols/ru/README.md b/modules/30-variables/30-symbols/ru/README.md new file mode 100644 index 0000000..6bc82cc --- /dev/null +++ b/modules/30-variables/30-symbols/ru/README.md @@ -0,0 +1,50 @@ + +Иногда нужно получить один символ из строки. Например, если сайт знает имя и фамилию пользователя, и в какой-то момент требуется вывести эту информацию в формате *A. Ivanov*, то нужно взять первый символ из имени. + +```javascript +const firstName = 'Tirion'; + +console.log(firstName[0]); // => T +``` + +Квадратные скобки с цифрой — это специальный синтаксис извлечения символа из строки. Цифра называется **индексом** — позицией символа внутри строки. Индексы начинаются с 0 почти во всех языках программирования — поэтому, чтобы получить первый символ, нужно указать индекс `0`. Индекс последнего элемента равен длине строки минус единица: + +```javascript +// Длина строки 6, поэтому последний индекс — это 5 +const firstName = 'Tirion'; + +console.log(firstName[5]); // => n +``` + +Вопрос на самопроверку. Что выведет этот код? + +``` +const magic = '\nyou'; +console.log(magic[1]); // => ? +``` + +
+Ответ + +Данный код выведет символ `y` + +
+ +Индексом может быть не только конкретное число, но и значение переменной. Вот пример, который приведёт к тому же результату — выводу на экран символа *T*, но индекс внутри квадратных скобок записан не числом, а константой: + +```javascript +const firstName = 'Tirion'; +const index = 0; + +console.log(firstName[index]); // => T +``` + +Технически можно указать индекс и за пределами слова. Для нашего примера — это числа от 6 и выше. JavaScript не считает такое поведение ошибкой. Обращение по несуществующему индексу вернет значение `undefined`. + +```javascript +const firstName = 'Tirion'; + +console.log(firstName[10]); // => undefined +``` + +https://replit.com/@hexlet/js-basics-symbols diff --git a/modules/30-variables/30-symbols/ru/data.yml b/modules/30-variables/30-symbols/ru/data.yml new file mode 100644 index 0000000..f40da7e --- /dev/null +++ b/modules/30-variables/30-symbols/ru/data.yml @@ -0,0 +1,7 @@ +name: Извлечение символов из строки +tips: + - > + [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined) +definitions: + - name: Индекс + description: позиция символа внутри строки. diff --git a/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md b/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md new file mode 100644 index 0000000..f795f61 --- /dev/null +++ b/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md @@ -0,0 +1 @@ +Выведите на экран число `-0.304`. diff --git a/modules/33-data-types/10-primitive-data-types/ru/README.md b/modules/33-data-types/10-primitive-data-types/ru/README.md new file mode 100644 index 0000000..3098b11 --- /dev/null +++ b/modules/33-data-types/10-primitive-data-types/ru/README.md @@ -0,0 +1,33 @@ + +Что произойдет, если мы попробуем умножить число на строку? JavaScript вернет `NaN` (не число) — то самое значение. Оно возникает там, где вместе используются несовместимые значения. В данном случае число и строка: + +```javascript +3 * 'Dracarys'; // NaN +``` + +Внутри высокоуровневых языков программирования данные разделяются по типам. Любая строка относится к типу String, а числа — к типу Number и BigInt (очень большие числа). Зачем нужны типы? Для защиты программы от трудноотловимых ошибок. Типы определяют две вещи: + +* Возможные (допустимые) значения. Например, числа в JavaScript делятся на два типа: Number и BigInt. Первые — это все числа ниже определенного порога (его можно посмотреть), вторые — выше. Такое разделение связано с техническими особенностями работы аппаратуры. +* Набор операций, которые можно выполнять над этим типом. Например, операция умножения имеет смысл для типа «целые числа». Но не имеет смысла для типа «строки»: умножать слово «мама» на слово «блокнот» — бессмыслица. + +JavaScript ведет себя двояко, когда встречается с нарушениями. В некоторых ситуациях, он ругается на недопустимость операции и завершается с ошибкой. В других — программа продолжает работать. В этом случае недопустимая операция возвращает что-то похожее на `NaN`, как в примере выше. + +Каким образом JavaScript понимает, что за тип данных перед ним? Достаточно просто. Любое значение где-то инициализируется и, в зависимости от способа инициализации, становится понятно, что перед нами. Например, числа — это просто числа без дополнительных символов, кроме точки для рациональных чисел. А вот строки всегда ограничены специальными символами (в JavaScript три разных варианта). Например, такое значение `'234'` – строка, несмотря на то, что внутри нее записаны цифры. + +JavaScript позволяет узнать тип данных с помощью оператора `typeof`: + +```javascript +typeof 3; // number +typeof 'Game'; // string +``` + +https://replit.com/@hexlet/js-basics-data-types-primitive-data-types + +Типы данных Number, BigInt и String — это *примитивные* типы. Но есть и другие. В JavaScript встроен составной тип Object (а на его базе массивы, даты и другие). С его помощью можно объединять данные разных типов в одно значение, например, мы можем создать пользователя добавив к нему имя и возраст. + +```javascript +// Этот синтаксис изучается на Хекслете +const user = { name: 'Toto', age: 33 }; +``` + +По-английски строки в программировании называются "strings", а строчки текстовых файлов — "lines". Например, в коде выше есть две строчки (lines), но только одна строка (strings). В русском иногда может быть путаница, поэтому во всех уроках мы будем говорить **строка** для обозначения типа данных «строка», и **строчка** для обозначения строчек (lines) в файлах. diff --git a/modules/33-data-types/10-primitive-data-types/ru/data.yml b/modules/33-data-types/10-primitive-data-types/ru/data.yml new file mode 100644 index 0000000..4486bf9 --- /dev/null +++ b/modules/33-data-types/10-primitive-data-types/ru/data.yml @@ -0,0 +1,18 @@ +name: Типы данных +tips: + - > + [Литерал](https://ru.wikipedia.org/wiki/%D0%9B%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D0%BB_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)) + - | + [Статья о дробных числах](https://habrahabr.ru/post/112953/) +definitions: + - name: Тип данных + description: >- + множество данных в коде (разновидность информации). Тип определяет, что + можно делать с элементами конкретного множества. Например, целые числа, + рациональные числа, строки — это разные типы данных. + - name: Примитивные типы данных + description: простые типы, встроенные в сам язык программирования. + - name: Строка (string) + description: > + тип данных, описывающий набор символов (иными словами — текст); например, + `'text'` или `"text"`. diff --git a/modules/33-data-types/45-undefined/ru/EXERCISE.md b/modules/33-data-types/45-undefined/ru/EXERCISE.md new file mode 100644 index 0000000..3201661 --- /dev/null +++ b/modules/33-data-types/45-undefined/ru/EXERCISE.md @@ -0,0 +1 @@ +Выведите на экран значение `undefined`, не указывая его явно (через присваивание или передав напрямую в `console.log()`). Если не догадаетесь, как это сделать, подсмотрите решение учителя. diff --git a/modules/33-data-types/45-undefined/ru/README.md b/modules/33-data-types/45-undefined/ru/README.md new file mode 100644 index 0000000..4bbee23 --- /dev/null +++ b/modules/33-data-types/45-undefined/ru/README.md @@ -0,0 +1,35 @@ + +Объявление переменных возможно и без указания конкретного значения. Что будет выведено на экран если её распечатать? + +```javascript +let name; +console.log(name); // ? +``` + +На экране появится `undefined`, специальное значение особого типа, которое означает отсутствие значения. Undefined активно используется самим JavaScript в самых разных ситуациях, например, при обращении к несуществующему символу строки: + +```javascript +const name = 'Arya'; +console.log(name[8]); +``` + +https://replit.com/@hexlet/js-basics-data-types-undefined + +Смысл (семантика) значения `undefined` именно в том, что значения нет. Однако, ничто не мешает написать такой код: + +```javascript +let key = undefined; +``` + +И хотя интерпретатор позволяет такое сделать, это нарушение семантики значения `undefined`, ведь в этом коде выполняется присваивание, а значит — подставляется значение. + +JavaScript — один из немногих языков, в которых в явном виде присутствует понятие `undefined`. В остальных языках его роль выполняет значение `null`, которое, кстати, тоже есть в JavaScript. + +*Вопрос на самопроверку. Почему нельзя объявить константу без указания значения?* + +
+Ответ + +Константу невозможно изменить или переопределить. Ее значение необходимо указывать строго при определении. + +
diff --git a/modules/33-data-types/45-undefined/ru/data.yml b/modules/33-data-types/45-undefined/ru/data.yml new file mode 100644 index 0000000..2a8d3e1 --- /dev/null +++ b/modules/33-data-types/45-undefined/ru/data.yml @@ -0,0 +1,9 @@ +name: undefined +tips: + - > + [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined) +definitions: + - name: undefined + description: > + аналог отсутствия значения; указывает, что переменной не присвоено + значение или она вообще не объявлена. diff --git a/modules/33-data-types/47-data-types-immutability/ru/EXERCISE.md b/modules/33-data-types/47-data-types-immutability/ru/EXERCISE.md new file mode 100644 index 0000000..545cab8 --- /dev/null +++ b/modules/33-data-types/47-data-types-immutability/ru/EXERCISE.md @@ -0,0 +1,9 @@ +Вам даны три константы с фамилиями разных людей. Составьте и выведите на экран в одну строку слово из символов в таком порядке: + +1. Третий символ из первой строки +2. Второй символ из второй строки +3. Четвертый символ из третьей строки +4. Пятый символ из второй строки +5. Третий символ из второй строки + +Попробуйте использовать интерполяцию: внутри фигурных скобок можно помещать не только целые переменные, но и отдельные символы с помощью квадратных скобок. diff --git a/modules/33-data-types/47-data-types-immutability/ru/README.md b/modules/33-data-types/47-data-types-immutability/ru/README.md new file mode 100644 index 0000000..d6e1a79 --- /dev/null +++ b/modules/33-data-types/47-data-types-immutability/ru/README.md @@ -0,0 +1,20 @@ + +Что произойдет, если попытаться изменить символ в строке? + +```javascript +let firstName = 'Alexander'; +// Код выполнится без ошибок +firstName[0] = 'B'; +console.log(firstName); // => Alexander +``` + +Как это ни странно, но значение переменной `firstName` останется прежним, хотя код выполнится без ошибок. Так происходит из-за неизменяемости примитивных типов в JavaScript — язык не дает никакой физической возможности поменять строку. Неизменяемость примитивных типов важна по многим причинам, ключевая — производительность. Но что делать, если нам действительно нужно её изменить? Для этого и существуют переменные: + +```javascript +let firstName = 'Alexander'; +// Код выполнится без ошибок +firstName = 'Blexander' +console.log(firstName); // => Blexander +``` + +Есть большая разница между изменением значения переменной и изменением самого значения. Примитивные типы в JavaScript поменять нельзя (а вот составные можно, подробнее о них уже на самом Хекслете), а заменить значение переменной — без проблем. diff --git a/modules/33-data-types/47-data-types-immutability/ru/data.yml b/modules/33-data-types/47-data-types-immutability/ru/data.yml new file mode 100644 index 0000000..4447660 --- /dev/null +++ b/modules/33-data-types/47-data-types-immutability/ru/data.yml @@ -0,0 +1,8 @@ +name: | + Неизменяемость примитивных типов +tips: [] +definitions: + - name: Неизменяемость + description: > + состояние, при котором объект, переменная не могут быть изменены после + создания diff --git a/modules/33-data-types/50-data-types-weak-typing/ru/EXERCISE.md b/modules/33-data-types/50-data-types-weak-typing/ru/EXERCISE.md new file mode 100644 index 0000000..0c62f55 --- /dev/null +++ b/modules/33-data-types/50-data-types-weak-typing/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Выведите на экран результат выражения: `7 - (-8 - -2)`. Попробуйте сделать число 7 не числом, а строкой. Поэкспериментируйте с другими числами тоже. diff --git a/modules/33-data-types/50-data-types-weak-typing/ru/README.md b/modules/33-data-types/50-data-types-weak-typing/ru/README.md new file mode 100644 index 0000000..4fab117 --- /dev/null +++ b/modules/33-data-types/50-data-types-weak-typing/ru/README.md @@ -0,0 +1,29 @@ + +Нам известно про два разных типа данных: числа и строки. Мы, например, можем складывать числа, потому что операция сложения — это операция для типа «числа». + +А что, если применить эту операцию не к двум числам, а к числу и строке? + +```javascript +console.log(1 + '7'); // => 17 +``` + +Несмотря на то, что `'7'` — это строка, а не число, интерпретатор JavaScript выдал ответ `17`, как если бы мы складывали две строки. Когда JavaScript видит несоответствие типов, он сам пытается преобразовать информацию. В данном случае он преобразовал число `1` в строку `'1'`, а потом спокойно сделал конкатенацию `'1'` и `'7'`. + +Не все языки так делают. JavaScript — это язык со **слабой типизацией**. Он знает о существовании разных типов (числа, строки и др.), но относится к их использованию не очень строго, пытаясь преобразовывать информацию, когда это кажется разумным. Иногда JavaScript даже доходит до крайностей. Большинство выражений, не работающих в других языках, прекрасно работают в JavaScript. Попробуйте выполнить любую арифметическую операцию (кроме сложения), подставив туда строки или любые другие типы данных (кроме ситуации, когда оба операнда - это числа или строки, содержащие только число) — вы увидите, что они всегда будут работать и возвращать `NaN`, что довольно логично. + +```javascript +const result = 'one' * 'two'; +console.log(result); // => NaN +``` + +https://replit.com/@hexlet/js-basics-immutability-of-primitive-types + +В языках со **строгой типизацией** сложить число со строкой не получится. + +JavaScript был создан для интернета, а в интернете вся информация — это строки. Даже когда вы вводите на сайте номер телефона или год рождения, на сервер эта информация поступает не как числа, а как строки. Поэтому авторы языка решили, что автоматически преобразовывать типы — правильно и удобно. + +Такое автоматическое неявное преобразование типов с одной стороны и правда удобно. Но на практике это свойство языка создает множество ошибок и проблем, которые трудно найти. Код может иногда работать, а иногда не работать — в зависимости от того, «повезло» ли в конкретном случае с автоматическим преобразованием. Программист это заметит не сразу. + +В дальнейших заданиях вы будете встречаться с таким поведением не раз. Часто будет возникать вопрос «почему мой код работает не так, как я ожидаю?». + +Слабая типизация красной нитью проходит сквозь всю разработку на Javascript. diff --git a/modules/33-data-types/50-data-types-weak-typing/ru/data.yml b/modules/33-data-types/50-data-types-weak-typing/ru/data.yml new file mode 100644 index 0000000..f744fff --- /dev/null +++ b/modules/33-data-types/50-data-types-weak-typing/ru/data.yml @@ -0,0 +1,10 @@ +name: Слабая типизация +tips: + - | + [Типизация](https://ru.wikipedia.org/wiki/Сильная_и_слабая_типизация) +definitions: + - name: Слабая типизация + description: > + это типизация, при которой язык программирования выполняет множество + неявных преобразований типов автоматически, даже если может произойти + потеря точности или преобразование неоднозначно. diff --git a/modules/35-calling-functions/100-call/ru/EXERCISE.md b/modules/35-calling-functions/100-call/ru/EXERCISE.md new file mode 100644 index 0000000..5d2cb83 --- /dev/null +++ b/modules/35-calling-functions/100-call/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +В коде программы определены две константы, содержащие имена компаний. Посчитайте их общую длину в символах и выведите ее на экран. diff --git a/modules/35-calling-functions/100-call/ru/README.md b/modules/35-calling-functions/100-call/ru/README.md new file mode 100644 index 0000000..5b1db3e --- /dev/null +++ b/modules/35-calling-functions/100-call/ru/README.md @@ -0,0 +1,64 @@ + +Сложение, конкатенация, нахождение остатка от деления и остальные рассмотренные операции – все это довольно базовые возможности языков программирования. Математика не ограничена арифметикой, кроме нее есть и множество других разделов со своими операциями, например, геометрия. То же самое касается и строк: их можно переворачивать, менять регистр букв, удалять лишние символы — и это только самое простое. И, наконец, на более высоком уровне есть прикладная логика конкретного приложения. Программы списывают деньги, считают налоги, формируют отчеты. Количество подобных операций бесконечно и индивидуально для каждой программы. И все они должны быть как-то выражены в коде. + +Для выражения любой произвольной операции в программировании существует понятие *функция*. Функции бывают как встроенные, так и добавленные программистом. С одной встроенной функцией мы уже знакомы, это `console.log()`. + +Функции — одна из ключевых конструкций в программировании, без них невозможно сделать практически ничего. Знакомство с ними мы начинаем как можно раньше, так как весь дальнейший материал оперирует функциями по максимуму. Сначала мы научимся пользоваться уже созданными функциями, а уже потом научимся создавать свои собственные. + +Начнем с простых функций для работы над строками. Ниже пример вызова функции `length()`, которая считает количество символов в строке: + +```javascript +// length это функция +import { length } from 'hexlet-basics/string'; + +// Вызов функции length с параметром 'Hello!' +const result = length('Hello!'); +console.log(result); // => 6 +``` + +Лирическое отступление. Первая строчка в этом коде - импорт функции из другого модуля. Импорты и модули изучаются на Хекслете, здесь же они будут присутствовать в задании «как есть», так как без них невозможно использовать функции, определенные в других файлах. Не заморачивайтесь, если вам не понятен смысл этого действия, подробнее о нем можно узнать из курса [введение в программирование](https://ru.hexlet.io/courses/introduction_to_programming). + +Параметры (или аргументы) — это информация, которую функция получает при вызове. Именно на основе этой информации функция, как правило, вычисляет что-то и выдает результат. + +Мы создали константу `result` и указали интерпретатору записать в неё результат, **возвращаемый** функцией `length()` при её вызове. В этом смысле функции подобны операциям - они всегда возвращают результат своей работы. + +```javascript +// Вызов length возвращает результат (длину строки) +// который записывается в константу с именем result +const result = length('Hello!'); +``` + +Запись `length('Hello!')` означает, что вызывается функция с именем *length*, в которую был передан параметр `'Hello!'`. Функция `length()` считает длину именно той строки, которая ей была передана. + +Вызов функции всегда обозначается скобками `()`, идущими сразу за именем функции. В скобках может быть любое количество параметров, а иногда — вообще ни одного. Количество зависит от используемой функции. Возьмем для примера функцию `pow()`, которая возводит указанное число в нужную степень. Она принимает на вход два параметра и возводит число, переданное первым параметром, в степень, переданную вторым параметром. + +```javascript +import { pow } from 'hexlet-basics/math'; + +// Вызов pow(2, 3) возвращает значение 2 в 3 степени +const result = pow(2, 3); // 2 * 2 * 2 +console.log(result); // => 8 +``` + +По большому счету, операторы и функции — это одно и то же. Ключевая разница только в том, как они записываются. Если представить (гипотетически) сложение как функцию, то она будет выглядеть так: + +```javascript +// Обычное сложение +3 + 5; // 8 +// Сложение представленное как функция +// Выглядит странновато, но передает смысл функций ++(3, 5); +``` + +## Резюме + +Функции вызываются и возвращают результат, который затем может быть использован в дальнейших вычислениях или, например, выведен на экран. + +Вопрос на самопроверку. Как узнать, что возвращает вызов функции `console.log()`? Проверьте. + +
+Ответ + +Вызов функции `console.log()` возвращает `undefined`. + +
diff --git a/modules/35-calling-functions/100-call/ru/data.yml b/modules/35-calling-functions/100-call/ru/data.yml new file mode 100644 index 0000000..7beab61 --- /dev/null +++ b/modules/35-calling-functions/100-call/ru/data.yml @@ -0,0 +1,14 @@ +name: Функции и их вызов +tips: + - > + [Вызов + функции](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#calling_functions) +definitions: + - name: Функция + description: >- + операция, способная принимать данные и возвращать результат; функция + вызывается так: `foo()`. + - name: Аргумент + description: >- + информация, которую функция получает при вызове. Например, `foo(42)` — + передача аргумента `42` функции `foo()` diff --git a/modules/35-calling-functions/110-math/ru/EXERCISE.md b/modules/35-calling-functions/110-math/ru/EXERCISE.md new file mode 100644 index 0000000..3c3a55a --- /dev/null +++ b/modules/35-calling-functions/110-math/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Выведите на экран абсолютное значение числа, находящегося в константе `soldiersCount`, используя функцию [Math.abs()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/abs). Эта функция возвращает абсолютное значение переданного числа. Абсолютное значения числа — это само это число без знака перед ним. + +```javascript +Math.abs(-3); // 3 +Math.abs(3); // 3 +Math.abs(0); // 0 +``` diff --git a/modules/35-calling-functions/110-math/ru/README.md b/modules/35-calling-functions/110-math/ru/README.md new file mode 100644 index 0000000..b118c7a --- /dev/null +++ b/modules/35-calling-functions/110-math/ru/README.md @@ -0,0 +1,14 @@ + +Объяснение функций в JavaScript немного осложняется структурой языка. Изначально он появился в браузерах и имел сильно ограниченные возможности по сравнению с языками общего назначения. Со временем все изменилось — JavaScript стал мощным языком, захватившим клиентскую разработку и активно использующимся на сервере. Однако наследие осталось, так как нужно поддерживать обратную совместимость. Поэтому в некоторых местах есть несостыковки, которые нельзя объяснить системой: на них можно только махнуть рукой и сказать: «Так исторически сложилось». + +К подобным «местам» относятся математические функции. В предыдущем задании мы использовали самописную функцию `pow()` (мы, как создатели курса, добавили ее в практику), а теперь давайте рассмотрим её версию, встроенную в сам язык. + +```javascript +Math.pow(2, 3); // 8 +``` + +https://replit.com/@hexlet/js-basics-calling-functions-math + +Что такое `Math`? Технически — это объект, доступный из любого места программы, но перед тем, как говорить об объектах, нужно проделать очень большой путь. Сейчас достаточно запомнить, что функции для математических операций вызываются через `Math.`. Наличие этой приставки никак не влияет на понятие функции, которое мы рассмотрели ранее и будем рассматривать позже. + +Полный список функций Math доступен в [документации](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math). О том, как её правильно читать, мы поговорим далее. diff --git a/modules/35-calling-functions/110-math/ru/data.yml b/modules/35-calling-functions/110-math/ru/data.yml new file mode 100644 index 0000000..e6feaf9 --- /dev/null +++ b/modules/35-calling-functions/110-math/ru/data.yml @@ -0,0 +1,14 @@ +name: Математические функции JavaScript +tips: + - > + [Документация + Math](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math) +definitions: + - name: Функция + description: >- + операция, способная принимать данные и возвращать результат; функция + вызывается так: `foo()`. + - name: Аргумент + description: >- + информация, которую функция получает при вызове. Например, `foo(42)` — + передача аргумента `42` функции `foo()` diff --git a/modules/35-calling-functions/120-function-signature/ru/EXERCISE.md b/modules/35-calling-functions/120-function-signature/ru/EXERCISE.md new file mode 100644 index 0000000..f9faa14 --- /dev/null +++ b/modules/35-calling-functions/120-function-signature/ru/EXERCISE.md @@ -0,0 +1,6 @@ + +Теперь ваша очередь посмотреть на сигнатуру функции в документации и разобраться, как её использовать. Можете читать документацию на русском языке, но программист должен уметь читать документацию на английском. Используйте словари или переводчики при необходимости. Лучше сразу привыкать и подтягивать навыки чтения на английском, иначе будут сложности в будущем. + +В `Math` есть функция `ceil()`. Изучите её [документацию](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil). + +Напишите программу, которая использует функцию `Math.ceil()` с константой `number` и выводит результат на экран. diff --git a/modules/35-calling-functions/120-function-signature/ru/README.md b/modules/35-calling-functions/120-function-signature/ru/README.md new file mode 100644 index 0000000..b7cd1d2 --- /dev/null +++ b/modules/35-calling-functions/120-function-signature/ru/README.md @@ -0,0 +1,25 @@ + +Функция `Math.pow()`, возводящая число в какую-нибудь степень, принимает два параметра: **какое число возводить** и **в какую степень возводить**. Если вызывать `pow()` без параметров, то вернется `NaN`. Функция честно пытается выполнить возведение в степень, но если значение не передано, то интерпретатор автоматически передает ей `undefined`. JavaScript заставляет программистов быть более аккуратным, чем остальные языки. В большинстве языков, если передать в функцию меньше параметров, чем она ожидает, то возникнет ошибка, — но только не в JavaScript. `NaN` вернется и при передаче любых не числовых значений: + +```javascript +const result = Math.pow(2, 'boom'); +console.log(result); // => NaN +``` + +https://replit.com/@hexlet/js-basics-calling-functions-function-signature + +Другая функция может иметь другое число параметров и другие типы параметров. Например, может существовать функция, которая принимает три параметра: число, строку и ещё одно число. + +Откуда мы знаем, сколько каких параметров нужно функции `Math.pow()` и какого типа будет «возврат»? Мы заглянули в **сигнатуру** этой функции. Сигнатура определяет входные параметры и их типы, а также выходной параметр и его тип. Про функцию `Math.pow()` можно почитать в [документации](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/pow). В разделе «Синтаксис» есть такой текст: + +``` +Math.pow(base, exponent) + +Параметры + base + Основание степени. + exponent + Показатель степени, в которую возводится основание base. +``` + +Это сигнатура функции и короткое пояснение на русском языке. Документация позволяет понять, сколько аргументов у функции и какого они типа, возвращает ли что-то функция и если да, то какого типа возвращаемое значение. diff --git a/modules/35-calling-functions/120-function-signature/ru/data.yml b/modules/35-calling-functions/120-function-signature/ru/data.yml new file mode 100644 index 0000000..d8d8973 --- /dev/null +++ b/modules/35-calling-functions/120-function-signature/ru/data.yml @@ -0,0 +1,10 @@ +name: Сигнатура функции +tips: + - > + [Сигнатура + функции](https://developer.mozilla.org/en-US/docs/Glossary/Signature/Function) +definitions: + - name: Сигнатура функции + description: >- + формальное описание типов параметров и типа возвращаемого значения + функции. diff --git a/modules/35-calling-functions/135-calling-functions-default-arguments/ru/EXERCISE.md b/modules/35-calling-functions/135-calling-functions-default-arguments/ru/EXERCISE.md new file mode 100644 index 0000000..82955c2 --- /dev/null +++ b/modules/35-calling-functions/135-calling-functions-default-arguments/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Округлите число, записанное в константу `number`, до двух знаков после запятой и выведите результат на экран. diff --git a/modules/35-calling-functions/135-calling-functions-default-arguments/ru/README.md b/modules/35-calling-functions/135-calling-functions-default-arguments/ru/README.md new file mode 100644 index 0000000..ca03740 --- /dev/null +++ b/modules/35-calling-functions/135-calling-functions-default-arguments/ru/README.md @@ -0,0 +1,23 @@ + +Рассмотрим функцию `round()`, которая округляет целое число: + +```javascript +const result = round(10.25, 0); // 10 +``` + +Мы передали в неё два параметра: число, которое нужно округлить, и точность округления. `0` означает, что округление будет до целого значения, то есть дробная часть просто отбрасывается. + +Чаще всего нужно округлять именно до целого числа (а не до десятых, например), поэтому создатели функции `round()` сделали второй параметр **необязательным** и задали ему внутри функции **значение по умолчанию `0`**. Значит, можно не указывать второй параметр, а результат будет тем же: + +```javascript +const result = round(10.25); // 10 +``` + +Если нужна другая точность, то можно передать параметр: + +```javascript +// округление до одного знака после запятой +const result = round(10.25, 1); // 10.3 +``` + +Если функция в JavaScript принимает необязательные параметры, то они всегда стоят после обязательных. Их количество может быть любым (это зависит от самой функции), но они всегда идут рядом и в конце списка аргументов. diff --git a/modules/35-calling-functions/135-calling-functions-default-arguments/ru/data.yml b/modules/35-calling-functions/135-calling-functions-default-arguments/ru/data.yml new file mode 100644 index 0000000..c615f6d --- /dev/null +++ b/modules/35-calling-functions/135-calling-functions-default-arguments/ru/data.yml @@ -0,0 +1,8 @@ +name: Параметры по умолчанию +tips: + - > + [Параметры по + умолчанию](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Default_parameters) +definitions: + - name: Параметр по умолчанию + description: необязательный параметр функции diff --git a/modules/35-calling-functions/150-calling-functions-expression/ru/EXERCISE.md b/modules/35-calling-functions/150-calling-functions-expression/ru/EXERCISE.md new file mode 100644 index 0000000..3b39470 --- /dev/null +++ b/modules/35-calling-functions/150-calling-functions-expression/ru/EXERCISE.md @@ -0,0 +1,9 @@ + +Выведите на экран первую и последнюю буквы предложения, записанного в константу `text`, в следующем формате: + +
+First: N
+Last: t
+
+ +Постарайтесь создать только одну константу, в которую сразу запишется нужный текст перед печатью на экран. В этом уроке мы отрабатываем умение собирать составное выражение. diff --git a/modules/35-calling-functions/150-calling-functions-expression/ru/README.md b/modules/35-calling-functions/150-calling-functions-expression/ru/README.md new file mode 100644 index 0000000..9ab6e4f --- /dev/null +++ b/modules/35-calling-functions/150-calling-functions-expression/ru/README.md @@ -0,0 +1,55 @@ + +В программировании выражение – нечто, возвращающее результат, который можно использовать. Мы уже знаем достаточно много о выражениях и о принципах их построения. Математические операции (сложение, вычитание), строковые операции (конкатенация) – все это выражения: + +```javascript +1 + 5 * 3; +'Hex' + 'Let'; +// Переменные могут быть частью выражения +rate * 5; +``` + +Особенность выражений в том, что они возвращают результат, который можно, например, присвоить константе или вывести на экран. Например: + +```javascript +// Тут выражение это 1 + 5 +const sum = 1 + 5; +console.log(1 + 5); +``` + +Но не все в программировании является выражением. Определение переменной – это инструкция, она не может быть частью выражения. То есть такой код выдаст ошибку: + +```javascript +// Бессмысленный код, который не сработает +10 + const sum = 1 + 5; +``` + +Почему об этом важно знать? Как вы увидите дальше, выражения можно комбинировать, получая все более сложное поведение в самых неожиданных местах и самым неожиданным образом. Вы будете лучше понимать, как можно соединять части кода, чтобы получить нужный результат. + +Поговорим о функциях. Вызов функции - это выражение или нет? Мы знаем, что функции возвращают результат, то есть да, они выражения. Из этого автоматически следует много интересного. Например, мы можем использовать вызов функции прямо в математических операциях. Вот как можно получить индекс последнего символа в слове: + +```javascript +import { length } from 'hexlet-basics/string'; + +const name = 'JavaScript'; +// Индексы начинаются с нуля +// Вызов метода и вычитание вместе! +const lastIndex = length(name) - 1; +console.log(lastIndex); // 9 +``` + +В этом коде нет нового синтаксиса. Мы всего лишь соединили уже известные части, опираясь на их природу. Можно пойти еще дальше: + +```javascript +console.log(length(name) - 1); // 9 +``` + +Все это справедливо для любых функций, например строковых: + +```javascript +import { length } from 'hexlet-basics/string'; + +const name = 'JavaScript'; +// Используется интерполяция +console.log(`Последний символ: ${name[length(name) - 1]}`); +// 'Последний символ: t' +``` diff --git a/modules/35-calling-functions/150-calling-functions-expression/ru/data.yml b/modules/35-calling-functions/150-calling-functions-expression/ru/data.yml new file mode 100644 index 0000000..bad9134 --- /dev/null +++ b/modules/35-calling-functions/150-calling-functions-expression/ru/data.yml @@ -0,0 +1,6 @@ +name: Вызов функции — выражение +definitions: + - name: Выражение + description: > + последовательность действий над данными, приводящая к каком-то результату, + который можно использовать. diff --git a/modules/35-calling-functions/180-variadic-parameters/ru/EXERCISE.md b/modules/35-calling-functions/180-variadic-parameters/ru/EXERCISE.md new file mode 100644 index 0000000..269f1ff --- /dev/null +++ b/modules/35-calling-functions/180-variadic-parameters/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Посчитайте программно (а не в голове) минимальное число среди 3, 10, 22, -3, 0 — и выведите его на экран. Воспользуйтесь функцией `Math.min()`, которая работает аналогично `Math.max()`. diff --git a/modules/35-calling-functions/180-variadic-parameters/ru/README.md b/modules/35-calling-functions/180-variadic-parameters/ru/README.md new file mode 100644 index 0000000..b1ed3e5 --- /dev/null +++ b/modules/35-calling-functions/180-variadic-parameters/ru/README.md @@ -0,0 +1,18 @@ + +Интересная особенность некоторых функций — принимать переменное число параметров. Речь не идет о значениях по умолчанию. Посмотрите на этот пример: + +```javascript +Math.max(1, 10, 3); // 10 +``` + +Функция `Math.max()` находит максимальное значение среди переданных параметров. Как вы думаете, сколько параметров она ожидает на вход? Если открыть документацию этой функции, то мы увидим странную конструкцию: + + ``` + Math.max([value1[, value2[, ...]]]) + ``` + + Такая запись говорит о том, что эта функция принимает на вход любое число параметров (и даже может быть вызвана без них). Необязательность передаваемых параметров описывается скобками *[ ]*, точно так же описываются и опциональные параметры, у которых есть значения по умолчанию. Возможность передачи любого числа параметров зашита в этой части *[, ...]*. + + ```javascript + Math.max(1, -3, 2, 3, 2); // 3 + ``` diff --git a/modules/35-calling-functions/180-variadic-parameters/ru/data.yml b/modules/35-calling-functions/180-variadic-parameters/ru/data.yml new file mode 100644 index 0000000..b7487ae --- /dev/null +++ b/modules/35-calling-functions/180-variadic-parameters/ru/data.yml @@ -0,0 +1,8 @@ +name: Функции с переменным числом параметров +tips: + - > + [Пример функции с переменным числом + параметров](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max) +definitions: + - name: Аргумент по умолчанию + description: необязательный аргумент функции. diff --git a/modules/35-calling-functions/270-deterministic/ru/EXERCISE.md b/modules/35-calling-functions/270-deterministic/ru/EXERCISE.md new file mode 100644 index 0000000..2492674 --- /dev/null +++ b/modules/35-calling-functions/270-deterministic/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Функция `Math.random()` возвращает случайное число от 0 до 1 с большим количеством знаков после запятой. Но в реальных задачах бывает нужно получать случайные целые числа, например, в диапазоне от 0 до 10. Реализуйте код, который печатает на экран именно такие числа. Для этой задачи вам понадобятся функции [Math.random()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/random) и [Math.round()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/round) + +Попробуйте решить это задание в одну строчку + +## Алгоритм + +Так как `Math.random()` возвращает числа в диапазоне от 0 до 1, то чтобы получить числа от 0 до 10, нам нужно выполнить умножение на 10. Затем получившиеся число округляется и так мы получаем то, что нужно. diff --git a/modules/35-calling-functions/270-deterministic/ru/README.md b/modules/35-calling-functions/270-deterministic/ru/README.md new file mode 100644 index 0000000..07ab4af --- /dev/null +++ b/modules/35-calling-functions/270-deterministic/ru/README.md @@ -0,0 +1,22 @@ + +Независимо от того, какой язык программирования используется, функции внутри него обладают некоторыми фундаментальными свойствами. Зная эти свойства, легче прогнозировать поведение функций, способы их тестирования и место их использования. К таким свойствам относится детерминированность. Функция называется детерминированной тогда, когда для одних и тех же входных параметров она возвращает один и тот же результат. Например, функция, считающая количество символов, детерминированная: + +```javascript +import { length } from 'hexlet-basics/string'; + +length('hexlet'); // 6 +length('hexlet'); // 6 + +length('wow'); // 3 +length('wow'); // 3 +``` + +Сколько бы раз мы ни вызывали эту функцию, передавая туда значение `'hexlet'`, она всегда вернет `6`. В свою очередь функция, возвращающая случайное число, не является детерминированной, так как у одного и того же входа (даже если он пустой, то есть параметры не принимаются) мы получим всегда разный результат. Насколько он разный - не важно, даже если хотя бы один из миллиона вызовов вернет что-то другое, эта функция автоматически считается недетерминированной. + +```javascript +// Функция, возвращающая случайное число +Math.random(); // 0.09856613113197676 +Math.random(); // 0.8839904367241888 +``` + +Зачем это нужно знать? Детерминированность серьезно влияет на многие аспекты. Детерминированные функции удобны в работе, их легко оптимизировать, легко тестировать. Если есть возможность сделать функцию детерминированной, то лучше ее такой и сделать diff --git a/modules/35-calling-functions/270-deterministic/ru/data.yml b/modules/35-calling-functions/270-deterministic/ru/data.yml new file mode 100644 index 0000000..f863825 --- /dev/null +++ b/modules/35-calling-functions/270-deterministic/ru/data.yml @@ -0,0 +1,10 @@ +name: Детерминированность +tips: + - > + [Детерминированные + функции](https://ru.wikipedia.org/wiki/Чистота_функции#Детерминированность_функции) +definitions: + - name: Побочный эффект + description: >- + действие, которое изменяет внешнее окружение (среду выполнения). Например, + вывод на экран или отправка письма. diff --git a/modules/35-calling-functions/350-stdlib/ru/EXERCISE.md b/modules/35-calling-functions/350-stdlib/ru/EXERCISE.md new file mode 100644 index 0000000..390fc48 --- /dev/null +++ b/modules/35-calling-functions/350-stdlib/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Оператор `typeof` позволяет определить тип передаваемого операнда. Название типа возвращается в виде строки. Например, вызов `typeof 'go go go'` вернёт строку `'string'` (number — число). + +```javascript +console.log(typeof 3); // => 'number' +``` + +Выведите на экран тип значения константы `motto`. diff --git a/modules/35-calling-functions/350-stdlib/ru/README.md b/modules/35-calling-functions/350-stdlib/ru/README.md new file mode 100644 index 0000000..4546b78 --- /dev/null +++ b/modules/35-calling-functions/350-stdlib/ru/README.md @@ -0,0 +1,14 @@ + +JavaScript, как и любой другой язык, поставляется с набором полезных функций. Все вместе они составляют так называемую **стандартную библиотеку**. В неё обычно входят тысячи функций, которые невозможно выучить — этого и не нужно делать. Подразумевается, что любой программист знает, где искать документацию по ним и примерно представляет себе, чего он хочет достичь. А дальше — дело техники. Если отнять у программистов интернет, то большинство не сможет ничего запрограммировать. + +Для новичков эта информация часто выглядит так: «Сходи туда, не знаю куда, принеси то, не знаю что». То есть непонятно, как узнавать про эти функции, когда ты ничего не знаешь вообще. Как ни странно, не существует способа раз и навсегда познать всё, что нужно познать. Любой разработчик в процессе своего профессионального взросления знакомится со всё более интересными функциями, решающими его задачи более элегантно, и таким образом пополняет свой арсенал. + +Вот некоторые советы, как узнавать о новых функциях: + +* Всегда чётко отслеживайте, с чем вы сейчас работаете (какой тип данных). Почти всегда вы найдете необходимую функцию в соответствующем разделе документации — например, для работы со строками нужно изучать строковые функции. +* Периодически открывайте раздел со стандартными функциями по изучаемой тематике и просто пробегайтесь по ним, изучая сигнатуры и способы использования. +* Чаще читайте чужой код, особенно код библиотек, которые вы используете. Он весь доступен на GitHub. + +У JavaScript есть свои особенности по структуре стандартной библиотеки. Так как его код может исполняться в разных средах, таких как серверное окружение или браузер, то возможности стандартной библиотеки сильно зависят от варианта использования. Например, из браузера невозможно выполнять некоторые задачи, которые необходимо уметь выполнять на сервере. Документацию по серверной части необходимо смотреть на сайте https://nodejs.org. Серверные части стандартной библиотеки организованы в модули, у каждого модуля есть своя страница с описанием всех функций, находящихся внутри него. Например, модуль [fs](https://nodejs.org/api/fs.html) необходим для работы с файловой системой, через его функции происходит запись и чтение файлов. + +Если говорить про браузер, то там вообще мало что есть. По большей части это какие-то базовые функции, встроенные в сам язык — например те же [функции](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math) для работы с математикой. Остальные возможности добавляются через использование сторонних библиотек. diff --git a/modules/35-calling-functions/350-stdlib/ru/data.yml b/modules/35-calling-functions/350-stdlib/ru/data.yml new file mode 100644 index 0000000..3466e74 --- /dev/null +++ b/modules/35-calling-functions/350-stdlib/ru/data.yml @@ -0,0 +1,13 @@ +name: Стандартная библиотека +tips: + - > + [Описание строковых + функций](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) + - > + [Как искать техническую + информацию](https://guides.hexlet.io/ru/how-to-search/) +definitions: + - name: Стандартная библиотека + description: >- + набор полезных функций, входящий в комплект поставки языка + программирования. diff --git a/modules/38-properties/100-properties-syntax/ru/EXERCISE.md b/modules/38-properties/100-properties-syntax/ru/EXERCISE.md new file mode 100644 index 0000000..85dabdd --- /dev/null +++ b/modules/38-properties/100-properties-syntax/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Напечатайте на экран длину строки `text`. diff --git a/modules/38-properties/100-properties-syntax/ru/README.md b/modules/38-properties/100-properties-syntax/ru/README.md new file mode 100644 index 0000000..49cd3ab --- /dev/null +++ b/modules/38-properties/100-properties-syntax/ru/README.md @@ -0,0 +1,37 @@ + +Данные, которыми мы оперируем в своих программах, могут обладать важными свойствами — например, у строк есть длина. Как вы увидите далее, это свойство очень важно для реализации алгоритмов, связанных с преобразованием строки (как пример — переворот строки). Как узнать длину строки? Во многих языках длина строки вычисляется с помощью специальной функции и выглядит это примерно так: + +```javascript +import { length } from 'hexlet-basics/string'; + +const name = 'Robb'; +console.log(length(name)); // => 4 +``` + +В JavaScript свойства встроены прямо в язык. Они указываются через точку сразу после переменной (или константы): + +```javascript +const name = 'Robb'; +const len = name.length; +console.log(len); // => 4 +``` + +https://replit.com/@hexlet/js-basics-properties-properties-syntax + +Свойства связаны с данными, у которых они берутся. Для примитивных типов все свойства описаны в документации, как например, у [строк](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String). При этом у чисел вообще нет свойств. + +JavaScript позволяет обращаться к свойствам, которые не существуют (например, при опечатках). В таком случае их значением является `undefined`: + +```javascript +const name = 'Robb'; +console.log(name.whatIsThat); // => undefined +``` + +*Вопрос для самопроверки. Что распечатает код `console.log(name[name.length])` для `name`, определенного выше? Почему ответ такой?* + +
+Ответ + +Код распечатает `undefined`, потому что происходит обращение по индексу, который выходит за границу строки. В этом случае `name.length` — 4, а индекс последнего символа в строке — 3. + +
diff --git a/modules/38-properties/100-properties-syntax/ru/data.yml b/modules/38-properties/100-properties-syntax/ru/data.yml new file mode 100644 index 0000000..fdeecfe --- /dev/null +++ b/modules/38-properties/100-properties-syntax/ru/data.yml @@ -0,0 +1,7 @@ +name: Свойства +tips: + - > + Ознакомьтесь с документацией + [String.length](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/length). + Обратите внимание, что длина строки равна количеству символов в ней. Длина + пустой строки `''` равна 0. diff --git a/modules/38-properties/200-properties-methods/ru/EXERCISE.md b/modules/38-properties/200-properties-methods/ru/EXERCISE.md new file mode 100644 index 0000000..897869e --- /dev/null +++ b/modules/38-properties/200-properties-methods/ru/EXERCISE.md @@ -0,0 +1 @@ +Приведите строку `text` к нижнему регистру и напечатайте её на экран. diff --git a/modules/38-properties/200-properties-methods/ru/README.md b/modules/38-properties/200-properties-methods/ru/README.md new file mode 100644 index 0000000..be3f414 --- /dev/null +++ b/modules/38-properties/200-properties-methods/ru/README.md @@ -0,0 +1,39 @@ + +Кроме свойств, у данных существуют методы — функции, находящиеся внутри свойств. С практической точки зрения это значит, что метод работает и вызывается как функция, но делает это как свойство, через точку. + +```javascript +const name = 'Robb'; +const upperName = name.toUpperCase(); +console.log(upperName); // => ROBB +``` + +https://replit.com/@hexlet/js-basics-properties-methods + +Встроенные методы всегда оперируют теми данными, с которыми они связаны. Метод `.toUpperCase()` возвращает ту же строку, но преобразуя все символы в верхний регистр. Методов у данных обычно значительно больше, чем свойств, например, для строк их [несколько десятков](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String). В документации, на первый взгляд, они описаны немного странно: *String.prototype.toLowerCase()*. Это описание раскрывает некоторые внутренние детали реализации, которые сейчас не важны, да и мы не изучили всей необходимой базы для разговора о прототипах. + +Методы есть и у [чисел](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Number): + +```javascript +const temperature = 22.93; +// Округление до одного знака после запятой +const roundedTemperature = temperature.toFixed(1); +// Метод возвращает строку, которая содержит преобразованное число +console.log(roundedTemperature); // => 22.9 + +// Напрямую можно вызывать так +// Скобки нужны обязательно, иначе не заработает +(22.93).toFixed(1); // 22.9 +``` + +*Хозяйке на заметку. Технически всё несколько сложнее. Методы есть не у самих чисел, а у данных (объектов) типа Number. Числа, записанные в переменные или константы, автоматически преобразуются к данному типу во время обращения к ним, в это время происходит так называемый boxing.* + +Возникает закономерный вопрос: зачем нужны методы, почему не просто функции? С числами ситуация ещё сложнее. Часть операций реализована в виде методов самих чисел, например, `.toFixed()`, а ещё большая часть — в виде методов, доступных через `Math`. + +Есть две причины почему так сделано: + +1. Исторически так сложилось. JavaScript разрабатывался слишком быстро и поэтому не все было продумано хорошо +2. Далеко не все функции имеют отношение к конкретному значению. Возьмем для примера `Math.min()`. Эта функция находит минимальное число среди всех, которые ему были переданы. Эту функцию нелогично делать методом конкретного числа, например, так — `(1).min()`. Она не имеет никакой связи с конкретным числом + +С другой стороны, функции, работающие с конкретным числом, для единообразия должны быть реализованы как методы. К таким функциям относится получение модуля числа. То есть вместо такого вызова `Math.abs(-10)`, логично иметь такой: `(-10).abs()`. + +Что касается методов в целом, то не все так однозначно. Есть языки, в которых методов нет и там всё прекрасно, есть языки, где методы — это основной способ работы с функциями, но даже в этих языках всегда, наряду с методами, используются обычные функции. JavaScript — язык, в котором прижились оба подхода, в нём активно используются как обычные функции, так и методы. О плюсах и минусах подобных подходов подробно рассказывается в курсах [посвященных ООП](https://ru.hexlet.io/programs/js-oop). diff --git a/modules/38-properties/200-properties-methods/ru/data.yml b/modules/38-properties/200-properties-methods/ru/data.yml new file mode 100644 index 0000000..b897f9e --- /dev/null +++ b/modules/38-properties/200-properties-methods/ru/data.yml @@ -0,0 +1,5 @@ +name: Методы +tips: + - > + [Метод строки + toLowerCase()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase) diff --git a/modules/38-properties/300-properties-immutability/ru/EXERCISE.md b/modules/38-properties/300-properties-immutability/ru/EXERCISE.md new file mode 100644 index 0000000..c79e15f --- /dev/null +++ b/modules/38-properties/300-properties-immutability/ru/EXERCISE.md @@ -0,0 +1,3 @@ + +Данные, вводимые пользователями, часто содержат лишние пробельные символы в конце или начале строки. Обычно их вырезают с помощью метода `.trim()`, например, было: `' hello\n '`, стало: `'hello'`. +Обновите переменную `firstName` записав в неё то же самое значение, но обработанное методом `.trim()`. Распечатайте то, что получилось, на экран. diff --git a/modules/38-properties/300-properties-immutability/ru/README.md b/modules/38-properties/300-properties-immutability/ru/README.md new file mode 100644 index 0000000..a73d9e5 --- /dev/null +++ b/modules/38-properties/300-properties-immutability/ru/README.md @@ -0,0 +1,27 @@ + +Что напечатает на экран последний вызов? + +```javascript +const name = 'Tirion'; +console.log(name.toUpperCase()); // => TIRION +console.log(name); // => ? +``` + +Ответ на этот вопрос зависит от того, как вы поняли урок про неизменяемость примитивных типов данных. Вызов метода `.toUpperCase()` возвращает новое значение, в котором все буквы преобразованы в верхний регистр, но он не меняет (и не может этого сделать) исходную строку. Поэтому внутри константы (или переменной — это не важно) окажется старое значение: `'Tirion'`. Эта логика справедлива для методов всех примитивных типов. Более того, попытка изменить значение свойства этих данных ни к чему не приведет: + +```javascript +const name = 'Tirion'; +console.log(name.length); // => 6 +name.length = 100; +console.log(name.length); // => 6 +``` + +https://replit.com/@hexlet/js-properties-immutability + +Вместо изменения значения можно *заменить* значение. Для этого понадобятся переменные: + +```javascript +let name = 'Tirion'; +name = name.toUpperCase(); +console.log(name); // => TIRION +``` diff --git a/modules/38-properties/300-properties-immutability/ru/data.yml b/modules/38-properties/300-properties-immutability/ru/data.yml new file mode 100644 index 0000000..56398bd --- /dev/null +++ b/modules/38-properties/300-properties-immutability/ru/data.yml @@ -0,0 +1,5 @@ +name: Неизменяемость +tips: + - > + [Метод строки + trim()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) diff --git a/modules/38-properties/400-properties-expressions/ru/EXERCISE.md b/modules/38-properties/400-properties-expressions/ru/EXERCISE.md new file mode 100644 index 0000000..acc681a --- /dev/null +++ b/modules/38-properties/400-properties-expressions/ru/EXERCISE.md @@ -0,0 +1,9 @@ + +Выведите на экран первую и последнюю буквы предложения, записанного в константу `text`, в следующем формате: + +
+First: N
+Last: t
+
+ +Ваша задача извлечь эти символы из строки и вставить в `console.log()`, не используя промежуточные переменные. diff --git a/modules/38-properties/400-properties-expressions/ru/README.md b/modules/38-properties/400-properties-expressions/ru/README.md new file mode 100644 index 0000000..95a1b91 --- /dev/null +++ b/modules/38-properties/400-properties-expressions/ru/README.md @@ -0,0 +1,22 @@ + +Свойства и методы — такие же выражения, как переменные, константы или вызовы функции, а значит, их можно всячески комбинировать. + +Использование в операциях: + +```javascript +const name = 'Shaya'; +name.length + 5; // 10 +`hi, ${name.toUpperCase()}!`; // hi, SHAYA! +``` + +Использование в параметрах функций: + +```javascript +const name1 = 'Robb'; +const name2 = 'Shaya'; +console.log(name2.length); // => 5 +console.log(name2.toLowerCase()); // => shaya +console.log(Math.min(name1.length, name2.length)); // => 4 +``` + +https://replit.com/@hexlet/js-basics-properties-method diff --git a/modules/38-properties/400-properties-expressions/ru/data.yml b/modules/38-properties/400-properties-expressions/ru/data.yml new file mode 100644 index 0000000..9bada81 --- /dev/null +++ b/modules/38-properties/400-properties-expressions/ru/data.yml @@ -0,0 +1,9 @@ +name: Свойства и методы как выражения +tips: + - > + [немного о методе + .trim()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) +definitions: + - name: Метод + description: | + это функция или процедура, принадлежащая какому-то классу или объекту. diff --git a/modules/38-properties/500-properties-chain-of-methods/ru/EXERCISE.md b/modules/38-properties/500-properties-chain-of-methods/ru/EXERCISE.md new file mode 100644 index 0000000..09ebc58 --- /dev/null +++ b/modules/38-properties/500-properties-chain-of-methods/ru/EXERCISE.md @@ -0,0 +1,5 @@ + +С помощью метода `slice()` получите часть предложения, записанного в константу `text`, c `5` по `15` символы включительно. Полученную подстроку обработайте методом `.trim()` и выведите на экран длину итоговой подстроки. Выполните эти методы подряд в цепочке без создания промежуточных переменных. + +* [slice()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/slice) +* [trim()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) diff --git a/modules/38-properties/500-properties-chain-of-methods/ru/README.md b/modules/38-properties/500-properties-chain-of-methods/ru/README.md new file mode 100644 index 0000000..ef6c4e5 --- /dev/null +++ b/modules/38-properties/500-properties-chain-of-methods/ru/README.md @@ -0,0 +1,50 @@ + +У чисел есть метод, который преобразует их в строку: + +```javascript +const peopleCount = 5; +peopleCount.toString(); // 5 +``` + +Попробуйте ответить на вопрос, заработает ли следующий код — и если да, то что он напечатает на экран? + +```javascript +const name = 'Tirion'; +console.log(name.length.toString()); +``` + +Синтаксис нескольких подряд идущих точек мы видим впервые, но все операции, которые здесь встречаются, нам знакомы. Всё, что произошло в этом коде — это объединение уже известных возможностей языка. Такое в программировании происходит довольно часто. Даже не зная синтаксиса, можно пробовать комбинировать различные подходы, и есть неплохая вероятность, что они заработают. + +Самый простой способ понять как работает этот код — разбить цепочку на отдельные операции: + +```javascript +const name = 'Tirion'; +const len = name.length; +console.log(len.toString()); +``` + +Эти примеры абсолютно эквивалентны. Мы можем выполнять операции последовательно с промежуточным созданием констант, а можем строить непрерывную цепочку из свойств и методов. В цепочках вычисления всегда идут слева направо. + +Ещё один пример для закрепления: + +```javascript +const name = 'Tirion'; +console.log(name.toUpperCase().toLowerCase()); +``` + +Подобный код требует небольших умственных усилий. Важно понимать, что `.toLowerCase()` применяется к результату вызова метода, который находится левее. А метод `toUpperCase()` возвращает строку. Новички часто делают ошибки в цепочках с методами, забывая ставить вызов: + +```javascript +const name = 'Tirion'; +// Этот код отработает неверно! +console.log(name.toUpperCase.toLowerCase()); +``` + +Продолжая эту идею, возможно строить бесконечно длинные (хотя, в данном случае, бесполезные) цепочки: + +```javascript +// Чему равен результат такого вызова? +console.log(name.toUpperCase().toLowerCase().length.toString().length); +``` + +*С функциями подобный трюк не сработает, так как при обычном использовании они вкладываются друг в друга f(f(f())), что значительно ухудшает анализ. Но это не значит, что нельзя сделать красиво — можно и даже нужно. В других языках это реализуется через композицию функций или пайплайн-оператор, который, кстати говоря, постепенно начинает использоваться и в самом JavaScript: https://github.com/tc39/proposal-pipeline-operator.* diff --git a/modules/38-properties/500-properties-chain-of-methods/ru/data.yml b/modules/38-properties/500-properties-chain-of-methods/ru/data.yml new file mode 100644 index 0000000..7d0b9a5 --- /dev/null +++ b/modules/38-properties/500-properties-chain-of-methods/ru/data.yml @@ -0,0 +1,6 @@ +name: Цепочка вызовов +tips: [] +definitions: + - name: Метод + description: | + это функция или процедура, принадлежащая какому-то классу или объекту. diff --git a/modules/40-define-functions/100-define-functions-syntax/ru/EXERCISE.md b/modules/40-define-functions/100-define-functions-syntax/ru/EXERCISE.md new file mode 100644 index 0000000..b378df5 --- /dev/null +++ b/modules/40-define-functions/100-define-functions-syntax/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Реализуйте функцию с именем `printMotto()`, которая выведет на экран фразу *Winter is coming*. + +```javascript +printMotto(); // => Winter is coming +``` + +В задачах, в которых нужно реализовать функцию, эту функцию вызывать не нужно. Вызывать функцию будут автоматизированные тесты, которые проверяют её работоспособность. Пример с вызовом выше показан только для того, чтобы вы понимали, как ваша функция будет использоваться. diff --git a/modules/40-define-functions/100-define-functions-syntax/ru/README.md b/modules/40-define-functions/100-define-functions-syntax/ru/README.md new file mode 100644 index 0000000..bc9d792 --- /dev/null +++ b/modules/40-define-functions/100-define-functions-syntax/ru/README.md @@ -0,0 +1,65 @@ + +Определение собственных функций значительно упрощает написание и поддержку программ. Функции позволяют объединять сложные (составные) операции в одну. Например, отправка письма на сайте - это достаточно сложный процесс, включающий в себя взаимодействие с внешними системами (интернет). Благодаря возможности определять функции, вся сложность может быть скрыта за одной простой функцией: + +```javascript +// Гипотетический пример +// Место откуда берется функция +import { send } from 'mailer'; + +const email = 'support@hexlet.io'; +const title = 'Помогите'; +const body = 'Я написал историю успеха, как я могу получить скидку?'; + +// Один маленький вызов — и много логики внутри +send(email, title, body); +``` + +Внутри себя подобный вызов выполняет довольно много логики. Соединяется с почтовым сервером, формирует правильный запрос на основе заголовка и тела сообщения, а затем все это отправляет, не забыв закрыть соединение. + +Создадим нашу первую функцию. Ее задача - вывести на экран приветствие: + +
Hello, Hexlet!
+ +```javascript +// Определение функции +// Определение не вызывает и не выполняет функцию +// Мы лишь говорим, что теперь такая функция существует +const showGreeting = () => { + // Внутри тела отступ 2 пробела для удобства чтения + const text = 'Hello, Hexlet!'; + console.log(text); +} + +// Вызов функции +showGreeting(); // => Hello, Hexlet! +``` + +https://replit.com/@hexlet/js-basics-functions-define + +В отличие от обычных данных, функции выполняют действия, поэтому их имена практически всегда должны быть глаголами: «построить что-то», «нарисовать что-то», «открыть что-то». + +Всё, что описывается внутри фигурных скобок `{}`, называется телом функции. Внутри тела можно описывать любой код. Считайте, что это маленькая самостоятельная программа, набор произвольных инструкций. Тело выполняется ровно в тот момент, когда запускается функция. Причём каждый вызов функции запускает тело независимо от других вызовов. Кстати, тело может быть пустым: + +```javascript +// Минимальное определение функции +const noop = () => { + // Тут мог бы быть код, но его нет +} + +noop(); +``` + +Определение функции подозрительно похоже на создание константы. Действительно, в реальности, определение функции состоит из двух частей: собственно определения и присваивания константе: + +1. Определение: `() => { }` +2. Присваивание `const nameOfFunction = ...` + +Технически возможно создать функцию, которая просто определена, но ей невозможно воспользоваться, потому что нет имени: + +```javascript +() => { + // Работающий, но бесполезный код +}; +``` + +Понятие «создать функцию» имеет много синонимов: «реализовать», «определить» и даже «заимплементить» (от слова implement). Все они встречаются в повседневной практике на работе. diff --git a/modules/40-define-functions/100-define-functions-syntax/ru/data.yml b/modules/40-define-functions/100-define-functions-syntax/ru/data.yml new file mode 100644 index 0000000..22876b2 --- /dev/null +++ b/modules/40-define-functions/100-define-functions-syntax/ru/data.yml @@ -0,0 +1,5 @@ +name: Создание (определение) функций +tips: + - > + [Именование в + программировании](https://ru.hexlet.io/blog/posts/naming-in-programming) diff --git a/modules/40-define-functions/150-define-functions-return/ru/EXERCISE.md b/modules/40-define-functions/150-define-functions-return/ru/EXERCISE.md new file mode 100644 index 0000000..b9a0fac --- /dev/null +++ b/modules/40-define-functions/150-define-functions-return/ru/EXERCISE.md @@ -0,0 +1,7 @@ + +Реализуйте функцию `sayHurrayThreeTimes()`, которая возвращает строку 'hurray! hurray! hurray!'. + +```javascript +const hurray = sayHurrayThreeTimes(); +console.log(hurray); // => hurray! hurray! hurray! +``` diff --git a/modules/40-define-functions/150-define-functions-return/ru/README.md b/modules/40-define-functions/150-define-functions-return/ru/README.md new file mode 100644 index 0000000..3e27ee5 --- /dev/null +++ b/modules/40-define-functions/150-define-functions-return/ru/README.md @@ -0,0 +1,116 @@ + +Функции, которые мы определяли в предыдущих уроках, заканчивали свою работу тем, что печатали на экран какие-то данные: + +```javascript +const greeting = () => { + console.log('Hello, Hexlet!'); +}; +``` + +Пользы от таких функций не очень много, так как результатом их работы невозможно воспользоваться внутри программы. Рассмотрим это на примере. + +Возьмем задачу обработки электронной почты. Когда пользователь регистрируется на каком-то сайте, то он может ввести email любым способом: + +* Добавив случайно пробелы в начале или в конце `_support@hexlet.io__` +* Использовав буквы в разном регистре `SUPPORT@hexlet.io` + +Если мы сохраним его в таком виде в базу данных, то пользователь, скорее всего, не сможет войти на сайт, так как будет вбивать адрес без пробелов и используя другой регистр символов. Чтобы этого не произошло, email нужно подготовить к записи в базу, привести его к нижнему регистру и обрезать пробельные символы по краям строки. Вся задача решается в пару строчек: + +```javascript +const saveEmail = () => { + // В реальности email приходит из формы + const email = ' SuppORT@hexlet.IO'; + // обрезаем пробельные символы + const trimmedEmail = email.trim(); + const preparedEmail = trimmedEmail.toLowerCase(); + console.log(preparedEmail); + // здесь будет запись в базу данных +}; +``` + +Этот код стал возможен только благодаря возврату значения. Методы `trim()` и `toLowerCase()` ничего не печатают на экран (в консоль), они **возвращают** результат своей работы и поэтому мы можем записать его в константы. Если бы они вместо этого печатали на экран, мы бы не могли присвоить результат их работы константе. Как мы не можем сделать с определенной выше функцией `greeting()`: + +```javascript +const message = greeting(); +console.log(message); // => undefined +``` + +Изменим функцию `greeting()` таким образом, чтобы она начала возвращать данные, вместо их печати. Для этого нам понадобится выполнить возврат вместо печати на экран + +```javascript +const greeting = () => { + return 'Hello, Hexlet!'; +}; +``` + +`return` – особая инструкция, которая берёт выражение, записанное справа, и отдаёт его наружу, тому коду, который вызвал функцию. Как только JavaScript натыкается на `return`, выполнение функции на этом завершается. + +```javascript +// Теперь мы можем использовать результат работы функции +const message = greeting(); +console.log(message); // => Hello, Hexlet! +// И даже выполнить какие-то действия над результатом +console.log(message.toUpperCase()); // => HELLO, HEXLET! +``` + +Любой код после `return` не выполняется: + +```javascript +const greetingWithCodeAfterReturn = () => { + return 'Hello, Hexlet!'; + console.log('Я никогда не выполнюсь'); +}; +``` + +Даже если функция возвращает данные, это не ограничивает её в том, что она печатает. Кроме возврата данных мы можем и печатать: + +```javascript +const greetingWithReturnAndPrinting = () => { + console.log('Я появлюсь в консоли'); + return 'Hello, Hexlet!'; +}; + +// И напечатает текст на экран и вернет значение +const message = greetingWithReturnAndPrinting (); +``` + +Возвращать можно не только конкретное значение. Так как `return` работает с выражениями, то справа от него может появиться почти все что угодно. Здесь нужно руководствоваться принципами читаемости кода: + +```javascript +const greeting = () => { + const message = 'Hello, Hexlet!'; + return message; +}; +``` + +Здесь мы не возвращаем переменную, возвращается всегда значение, которое находится в этой переменной. Ниже пример с вычислениями: + +```javascript +const doubleFive = () => { + // или return 5 + 5 + const result = 5 + 5; + return result; +}; +``` + +Вопрос на самопроверку. Что вернет вызов, определенной ниже, функции `run()`? + +```javascript +// Определение +const run = () => { + return 5; + return 10; +}; + +// Что будет выведено на экран? +console.log(run()); +``` + +
+Ответ + +На экран будет выведено `5`. + +
+ +https://replit.com/@hexlet/js-basics-functions-return diff --git a/modules/40-define-functions/150-define-functions-return/ru/data.yml b/modules/40-define-functions/150-define-functions-return/ru/data.yml new file mode 100644 index 0000000..df4256a --- /dev/null +++ b/modules/40-define-functions/150-define-functions-return/ru/data.yml @@ -0,0 +1,5 @@ +name: Возврат значений +tips: + - > + [Подробнее о + return](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return) diff --git a/modules/40-define-functions/320-define-functions-parameters/ru/EXERCISE.md b/modules/40-define-functions/320-define-functions-parameters/ru/EXERCISE.md new file mode 100644 index 0000000..4d78c4c --- /dev/null +++ b/modules/40-define-functions/320-define-functions-parameters/ru/EXERCISE.md @@ -0,0 +1,30 @@ + +Допишите функцию `truncate()`, которая обрезает переданную строку до указанного количества символов, добавляет в конце многоточие и возвращает получившуюся строку. Подобная логика часто используется на сайтах, чтобы отобразить длинный текст в сокращенном виде. + +Функция принимает два параметра: + +1. Строка, которую нужно обрезать +2. Число символов, которые нужно оставить + +Пример того, как должна работать написанная вами функция: + +```javascript +// Передаём текст напрямую +// Обрезаем текст, оставляя 2 символа +truncate('hexlet', 2); // he... + +// Через переменную +const text = 'it works!'; +// Обрезаем текст, оставляя 4 символа +truncate(text, 4); // it w... +``` +Вам нужно самостоятельно реализовать функцию `truncate()`, в JavaScript такой функции не существует. Реализовать эту функцию можно различными способами, подскажем лишь один из них. Для решения этим способом вам понадобится взять подстроку из строки, переданной первым параметром в функцию. Используйте для этого метод [slice()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice). Подумайте, исходя из задания, с какого индекса и по какой вам надо извлечь подстроку? + + ```javascript + const word = 'welcome'; + // Передавать параметры в метод можно через переменные + const index = 3; + word.slice(0, index); // wel + ``` + +С точки зрения проверочной системы не имеет значения, каким из способов будет реализована функция `truncate()` внутри, главное – чтобы она выполняла поставленную задачу diff --git a/modules/40-define-functions/320-define-functions-parameters/ru/README.md b/modules/40-define-functions/320-define-functions-parameters/ru/README.md new file mode 100644 index 0000000..496a05d --- /dev/null +++ b/modules/40-define-functions/320-define-functions-parameters/ru/README.md @@ -0,0 +1,104 @@ + +Функции могут не только возвращать значения, но и принимать их в виде параметров (их ещё называют аргументами). С параметрами функций мы уже сталкивались много раз: + +```javascript +// Принимает на вход параметр любого типа +console.log('я параметр'); +// Принимает на вход два строковых параметра +// первый – что ищем, второй – на что меняем +'google'.replace('go', 'mo'); // moogle +// Принимает на вход два числовых параметра +// первый – начальный индекс (включая), второй – конечный индекс (не включая) +'hexlet'.slice(1, 3); // ex +``` + +В этом уроке мы научимся создавать функции, которые принимают на вход параметры. Представим, что перед нами стоит задача – реализовать функцию `getLastChar()`, возвращающую последний символ в строке, переданной ему на вход как параметр. Вот как будет выглядеть использование этой функции: + +```javascript +// Передача параметров напрямую без переменных +getLastChar('Hexlet'); // t +// Передача параметров через переменные +const name1 = 'Hexlet'; +getLastChar(name1); // t +const name2 = 'Goo'; +getLastChar(name2); // o +``` + +Из описания и примеров кода мы можем сделать следующие выводы: + +* Нам нужно определить функцию `getLastChar()` +* Функция должна принимать на вход один параметр строкового типа +* Функция должна возвращать значение строкового типа + +Определение функции: + +```javascript +const getLastChar = (text) => { + // Вычисляем индекс последнего символа как длина строки - 1 + return text[text.length - 1]; +}; +``` + +Разберем его. В скобках указывается имя переменой `text`, которая служит нам параметром. Имя параметра может быть любым. Главное, чтобы оно отражало смысл того значения, которое содержится внутри. Мы могли бы определить функцию и вот так: + +```javascript +const getLastChar = (str) => { + return str[str.length - 1]; +}; +``` + +Конкретное значение параметра будет зависеть от вызова этой функции. + +```javascript +// Внутри функции str будет равна 'hexlet' +getLastChar('hexlet'); // t + +// Внутри функции str будет равна 'code' +getLastChar('code'); // e + +// Внутри функции str будет равна 'Winter is coming' +// Имя переменной снаружи не связанно с именем переменной в определении функции +const text = 'Winter is coming'; +getLastChar(text); // g +``` + +Точно таким же образом можно указывать два, три и более параметров. Каждый параметр отделяется от другого запятой: + +```javascript +// функция по нахождению среднего числа +const average = (a, b) => { + return (a + b) / 2; +}; + +average(1, 5); // 3 +average(1, 2); // 1.5 +``` + +https://replit.com/@hexlet/js-basics-define-functions-parameters + +Тоже самое относится и к методам. Они могут требовать на вход любое количество параметров, которое им нужно для работы: + +```javascript +// первый параметр – что ищем +// второй параметр – на что меняем +'google'.replace('go', 'mo'); // moogle +```` + +Для создания таких функций и методов, нужно в определении указать нужное количество параметров через запятую, дав им понятные имена. Ниже пример определения функции `replace()`, которая заменяет в слове одну часть строки на другую: + +```javascript +const replace = (text, from, to) => { + // здесь тело функции, но мы его + // опускаем, чтобы не отвлекаться +}; + +replace('google', 'go', 'mo'); // moogle +``` + +Когда параметров два и более, то практически для всех функций становится важен порядок передачи этих параметров. Если его поменять, то функция отработает по-другому: + +```javascript +// ничего не заменилось, +// так как внутри google нет mo +replace('google', 'mo', 'go'); // google +``` diff --git a/modules/40-define-functions/320-define-functions-parameters/ru/data.yml b/modules/40-define-functions/320-define-functions-parameters/ru/data.yml new file mode 100644 index 0000000..1a3a7ed --- /dev/null +++ b/modules/40-define-functions/320-define-functions-parameters/ru/data.yml @@ -0,0 +1,5 @@ +name: Параметры функций +tips: + - > + [Параметры + функции](https://ru.wikipedia.org/wiki/Параметр_(программирование)) diff --git a/modules/40-define-functions/340-define-functions-default-parameters/ru/EXERCISE.md b/modules/40-define-functions/340-define-functions-default-parameters/ru/EXERCISE.md new file mode 100644 index 0000000..198a971 --- /dev/null +++ b/modules/40-define-functions/340-define-functions-default-parameters/ru/EXERCISE.md @@ -0,0 +1,17 @@ + +Реализуйте функцию `getHiddenCard()`, которая принимает на вход номер кредитки (состоящий из 16 цифр) в виде строки и возвращает его скрытую версию, которая может использоваться на сайте для отображения. Если исходная карта имела номер *2034399002125581*, то скрытая версия выглядит так *\*\*\*\*5581*. Другими словами, функция заменяет первые 12 символов, на звездочки. Количество звездочек регулируется вторым необязательным параметром. Значение по умолчанию — 4. + +```javascript +// Кредитка передается внутрь как строка +getHiddenCard('1234567812345678', 2); // **5678 +getHiddenCard('1234567812345678', 3); // ***5678 +getHiddenCard('1234567812345678'); // ****5678 +getHiddenCard('2034399002121100', 1); // *1100 +``` + +Для выполнения задания вам понадобится метод строки `repeat()`, который повторяет строку указанное количество раз + +```javascript +'+'.repeat(5); // +++++ +'o'.repeat(3); // ooo +``` diff --git a/modules/40-define-functions/340-define-functions-default-parameters/ru/README.md b/modules/40-define-functions/340-define-functions-default-parameters/ru/README.md new file mode 100644 index 0000000..b81d72f --- /dev/null +++ b/modules/40-define-functions/340-define-functions-default-parameters/ru/README.md @@ -0,0 +1,54 @@ + +В программировании большое количество функций и методов имеют параметры, которые редко меняются. В таких случаях этим параметрам задают значения по умолчанию, которые можно поменять по необходимости. Этим немного сокращается количество одинакового кода. Пример: + +```javascript +// Функция возведения в степень +// Второй параметр имеет значение по умолчанию 2 +const pow = (x, base = 2) => { + return x ** base; +}; +// 3 во второй степени (двойка задана по умолчанию) +pow(3); // 9 +// три в третьей степени +pow(3, 3); // 27 +``` + +https://replit.com/@hexlet/js-basics-define-functions-default-parameters + +Значение по умолчанию выглядит как обычное присваивание в определении. Оно срабатывает только в том случае, если аргумент не передан. К этому нужно привыкнуть. Значение по умолчанию может быть даже в том случае, когда параметр один: + +```javascript +const print = (text = 'nothing') => console.log(text); + +print(); // "nothing" +print("Hexlet"); // Hexlet +``` + +Параметров со значениями по умолчанию может быть сколько угодно: + +```javascript +const f = (a = 5, b = 10, c = 100) => { ... } +``` + +У значений по умолчанию есть одна особенность - они должны идти в самом конце списка параметров. Значения, передаваемые функции при вызове, всегда записываются в параметры слева направо, в том порядке, в котором они переданы. Получается, что если значения по умолчанию идут слева в списке параметров, перед обычными параметрами, то при вызове функции с какими-либо аргументами на место значений по умолчанию встанут значения аргументов. Например: + +```javascript +// Вызовем эту функцию со следующими аргументами: f(1, 2, 3) +const f = (a = 5, b = 10, c = 100, x) => { ... } +// параметры получат следующие значения: а = 1, b = 2, c = 3, x = undefined +// в x мы ничего не передали, и JS присвоил ему значение undefined + +// Именно поэтому параметры со значением по умолчанию должны идти справа от обычных, +// иначе они либо будут перезаписаны, либо обычный параметр может остаться без значения + +// Вызываем функцию, f(1, 2) +const f = (a = 5, x, b = 10, c = 100) => { ... } + +// a = 1, x = 2, остальные параметры получают значения по умолчанию + +// Здесь всё хорошо, никаких неожиданностей +const f = (x, a = 5, b = 10, c = 100) => { ... } + +// И здесь +const f = (x, y, a = 5, b = 10, c = 100) => { ... } +``` diff --git a/modules/40-define-functions/340-define-functions-default-parameters/ru/data.yml b/modules/40-define-functions/340-define-functions-default-parameters/ru/data.yml new file mode 100644 index 0000000..a3b3de4 --- /dev/null +++ b/modules/40-define-functions/340-define-functions-default-parameters/ru/data.yml @@ -0,0 +1,8 @@ +name: Необязательные параметры функций +tips: + - > + [Параметры по + умолчанию](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Default_parameters) +definitions: + - name: Параметр по умолчанию + description: необязательный параметр функции diff --git a/modules/40-define-functions/450-define-functions-short-syntax/ru/EXERCISE.md b/modules/40-define-functions/450-define-functions-short-syntax/ru/EXERCISE.md new file mode 100644 index 0000000..7e2551f --- /dev/null +++ b/modules/40-define-functions/450-define-functions-short-syntax/ru/EXERCISE.md @@ -0,0 +1,19 @@ + +Реализуйте функцию `capitalize()`, которая принимает непустую строку и приводит первую букву первого слова к верхнему регистру: + +```javascript +const name = 'arya'; +console.log(capitalize(name)); // => Arya +``` + +Чтобы получить подстроку (или символ) из строки, используйте метод [slice()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice): + +```javascript +'welcome'.slice(2, 5); // lco +``` + +Для приведения строки к верхнему регистру используйте метод [toUpperCase()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) + +```javascript +'welcome'.toUpperCase(); // WELCOME +``` diff --git a/modules/40-define-functions/450-define-functions-short-syntax/ru/README.md b/modules/40-define-functions/450-define-functions-short-syntax/ru/README.md new file mode 100644 index 0000000..5f7ef79 --- /dev/null +++ b/modules/40-define-functions/450-define-functions-short-syntax/ru/README.md @@ -0,0 +1,38 @@ + +По сравнению с некоторыми (в первую очередь функциональными) языками, определение функции в JavaScript выглядит довольно громоздко: + +```javascript +const square = (x) => { + return x ** 2; +}; +``` + +Здесь используется много дополнительных символов и слово `return`. С версии es6, в языке появился альтернативный, сокращенный синтаксис, который, в некоторых ситуациях, значительно упрощает восприятие и сокращает количество кода. + +```javascript +// Требуется немного времени на привыкание к этой форме +// но потом вы не сможете без неё жить +const double = (x) => x ** 2; +``` + +Отличия от полного определения два: пропали фигурные скобки и инструкция `return`. Сокращенная запись функции делает возврат автоматически. Подразумевается, что внутри такой функции ровно одно выражение, которое вычисляется, и её результат сразу возвращается наружу. + +Подчеркнём, что отличия исключительно синтаксические, с точки зрения использования различий нет. Пример с двумя аргументами: + +Полная версия + +```javascript +const sum = (a, b) => { + return a + b; +}; +``` + +Сокращенная версия + +```javascript +const sum = (a, b) => a + b; +``` + +https://replit.com/@hexlet/js-basics-define-functions-short-syntax + +Обратите внимание на отсутствие фигурных скобок. Разработчики, которые не привыкли использовать такой синтаксис, иногда пишут подобный код `const sum = (a, b) => { a + b };`, а потом долго не могут понять, почему он не работает. Ответ очень простой: если стоят фигурные скобки, то это не сокращенная форма, а значит, чтобы функция вернула значение, придётся поставить `return`. diff --git a/modules/40-define-functions/450-define-functions-short-syntax/ru/data.yml b/modules/40-define-functions/450-define-functions-short-syntax/ru/data.yml new file mode 100644 index 0000000..b2cc64f --- /dev/null +++ b/modules/40-define-functions/450-define-functions-short-syntax/ru/data.yml @@ -0,0 +1,4 @@ +name: Упрощенный синтаксис функций +tips: + - | + [Javascript ES6](https://www.w3schools.com/js/js_es6.asp) diff --git a/modules/45-logic/10-bool-type/ru/EXERCISE.md b/modules/45-logic/10-bool-type/ru/EXERCISE.md new file mode 100644 index 0000000..b686bb6 --- /dev/null +++ b/modules/45-logic/10-bool-type/ru/EXERCISE.md @@ -0,0 +1,9 @@ + +Напишите функцию `isPensioner()`, которая принимает один параметр — возраст человека, и проверяет, является ли он пенсионным. Пенсионером считается человек, достигший возраста 60 лет и больше. + +Примеры вызова: + +```javascript +isPensioner(75); // true +isPensioner(18); // false +``` diff --git a/modules/45-logic/10-bool-type/ru/README.md b/modules/45-logic/10-bool-type/ru/README.md new file mode 100644 index 0000000..6d639bc --- /dev/null +++ b/modules/45-logic/10-bool-type/ru/README.md @@ -0,0 +1,57 @@ + +Кроме арифметических операций со школы нам известны операции сравнения. Например, `5 > 4`. Это звучит как вопрос: «5 больше 4?». В данном случае ответ «да». В других случаях ответом может быть «нет», например, для `3 < 1`. + +Операции сравнения не имеют привязки к числам. Сравнивать можно практически всё что угодно, например, строки. Каждый раз, когда мы входим на какой-то сайт, внутри происходит сравнение введенных логина и пароля с теми, какие есть в базе. И только если они есть, нас пускают внутрь (авторизируют). + +Языки программирования адаптировали все математические операции сравнения практически в неизменном виде. Единственное серьезное отличие – операторы равенства и неравенства. В математике для этого используется обычное равно `=`, но в программировании такое встречается не часто. Во многих языках символ `=` используется для присваивания значений переменным, поэтому для сравнения взяли `==` или `===`. + +Список операций сравнения в JavaScript: + +* `<` меньше +* `<=` меньше или равно +* `>` больше +* `>=` больше или равно +* `===` равно +* `!==` не равно + +_Небольшая ремарка: для равенства и неравенства также существуют операторы `==` и `!=`, которые мы не будем использовать из-за потенциальной опасности. Мы поговорим об этом в будущих уроках._ + +Логическая операция типа `5 > 4` или `password === text` — это выражение, и его результат — специальное значение `true` («истина») или `false` («ложь»). Это новый для нас тип данных — boolean. Он содержит всего лишь два этих значения. + +```javascript +const result = 5 > 4; +console.log(result); // => true +console.log('one' !== 'one'); // => false +``` + +Наряду со строками (string), целыми и рациональными числами (number), логический тип (boolean) — это один из примитивных типов данных в JavaScript. + +--- + +Попробуем написать примитивную функцию, которая принимает на вход возраст ребенка и определяет, младенец ли он. Младенцами считаются дети до года: + +```javascript +const isInfant = (age) => age < 1; +``` + +Пользуемся тем фактом, что любая операция — это выражение, поэтому единственной строчкой функции пишем «вернуть то значение, которое получится в результате сравнения `age < 1`». + +В зависимости от пришедшего аргумента, сравнение будет либо истинным (`true`), либо ложным (`false`), и `return` вернёт этот результат. + +```javascript +const isInfant = (age) => age < 1; + +console.log(isInfant(3)); +``` + +
false
+ +https://replit.com/@hexlet/js-basics-logic-bool-type + +А теперь проверим ребенка, которому полгода: + +```javascript +console.log(isInfant(0.5)); +``` + +
true
diff --git a/modules/45-logic/10-bool-type/ru/data.yml b/modules/45-logic/10-bool-type/ru/data.yml new file mode 100644 index 0000000..0140ba5 --- /dev/null +++ b/modules/45-logic/10-bool-type/ru/data.yml @@ -0,0 +1,8 @@ +name: Логический тип +tips: + - > + [Boolean в + JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) +definitions: + - name: Логический тип (boolean) + description: 'тип данных с двумя возможными значениями: true (истина) и false (ложь).' diff --git a/modules/45-logic/15-predicates/ru/EXERCISE.md b/modules/45-logic/15-predicates/ru/EXERCISE.md new file mode 100644 index 0000000..7cc71d7 --- /dev/null +++ b/modules/45-logic/15-predicates/ru/EXERCISE.md @@ -0,0 +1,9 @@ + +Напишите функцию `isMister()`, которая принимает строку и проверяет, является ли она словом `'Mister'`. + +Примеры вызова: + +```javascript +isMister('Mister'); // true +isMister('Miss'); // false +``` diff --git a/modules/45-logic/15-predicates/ru/README.md b/modules/45-logic/15-predicates/ru/README.md new file mode 100644 index 0000000..2de8be5 --- /dev/null +++ b/modules/45-logic/15-predicates/ru/README.md @@ -0,0 +1,33 @@ + +Вспомним функцию `isInfant()` из прошлого урока: + +```javascript +const isInfant = (age) => age < 1; +console.log(isInfant(3)); +``` +
false
+ +https://replit.com/@hexlet/js-basics-logic-bool-type + +Подобные функции называют предикатами. Функции-предикаты (или функции-вопросы) отвечают на какой-то вопрос и всегда (без исключений!) возвращают либо `true`, либо `false`. + +Предикаты во всех языках принято именовать особым образом для простоты анализа. В JavaScript предикаты, как правило, начинаются с префикса `is`, `has` или `can`, но не ограничены этими словами. Примеры: + + * `isInfant()` — «младенец ли?» + * `hasChildren()` — «есть ли дети?» + * `isEmpty()` — «пустой ли?» + * `hasErrors()` — «есть ли ошибки?» + +Функция может считаться предикатом **только** если она возвращает boolean. + +--- + +Давайте напишем ещё одну функцию-предикат. Она принимает строку и проверяет, является ли она словом `'Castle'`: + +```javascript +const isCastle = (type) => type === 'Castle'; + +console.log(isCastle('Sea')); +``` + +
false
diff --git a/modules/45-logic/15-predicates/ru/data.yml b/modules/45-logic/15-predicates/ru/data.yml new file mode 100644 index 0000000..2980e9f --- /dev/null +++ b/modules/45-logic/15-predicates/ru/data.yml @@ -0,0 +1,8 @@ +name: Предикаты +tips: + - > + [Именование в + программировании](https://ru.hexlet.io/blog/posts/naming-in-programming) +definitions: + - name: Предикат + description: выражение, отвечающее на вопрос «да» или «нет» с помощью типа boolean. diff --git a/modules/45-logic/20-logic-combine-expressions/ru/EXERCISE.md b/modules/45-logic/20-logic-combine-expressions/ru/EXERCISE.md new file mode 100644 index 0000000..1cf0ce5 --- /dev/null +++ b/modules/45-logic/20-logic-combine-expressions/ru/EXERCISE.md @@ -0,0 +1,7 @@ + +Реализуйте функцию, которая проверяет формат указанного телефона. Если телефон начинается с *+*, значит это международный формат. + +```javascript +isInternationalPhone('89602223423'); // false +isInternationalPhone('+79602223423'); // true +``` diff --git a/modules/45-logic/20-logic-combine-expressions/ru/README.md b/modules/45-logic/20-logic-combine-expressions/ru/README.md new file mode 100644 index 0000000..54c8646 --- /dev/null +++ b/modules/45-logic/20-logic-combine-expressions/ru/README.md @@ -0,0 +1,67 @@ + +Логические операции — это выражения. Значит, логические операции можно комбинировать с другими выражениями. + +Например, мы хотим проверить чётность числа, то есть кратность двум. В программировании используют такой подход: + +* проверяют остаток от деления на 2: + * если остаток 0, то число было чётным + * если остаток не 0, то число было нечётным + +Остаток от деления — простая, но очень важная концепция в арифметике, алгебре, и даже в теории чисел и криптографии. Идея проста: нужно разделить число на несколько равных групп, и если в конце что-то останется — это и есть остаток от деления. + +Делим конфеты поровну между людьми: + +- 7 конфет, 2 человека: 2 x 3 + **остаток 1**. + Значит, 7 не кратно 2. +- 21 конфету, 3 человека: 3 x 7 + **остаток 0**. + Значит, 21 кратно 3. +- 19 конфет, 5 человек: 5 x 3 + **остаток 4**. + Значит, 19 не кратно 5. + +Оператор `%` вычисляет остаток от деления (не путайте с делением): + +```javascript +7 % 2; // 1 +21 % 3; // 0 +19 % 5; // 4 + +// Проверка четности + +10 % 2 // 10 чётное, так как остаток 0 +9 % 2 // 9 нечётное, так как остаток 1 +``` + +Напишем функцию проверки чётности: + +```javascript +const isEven = (number) => number % 2 === 0; + +isEven(10); // true +isEven(3); // false +``` + +В одном выражении мы скомбинировали логический оператор `===` (проверка равенства) и арифметический оператор `%`. + +Приоритет арифметических операций выше логических. Значит, сначала вычисляется арифметическое выражение `number % 2`, затем результат участвует в логическом сравнении. + +Словами это можно расшифровать так: *«вычислить остаток от деления числа `number` на 2 и сравнить, равен ли остаток нулю; затем вернуть результат проверки равенства»*. + +Другой пример: напишем функцию, которая принимает строку и проверяет, заглавная ли первая буква. + +Алгоритм: + +1. Получим и запишем в переменную первый символ из строки-параметра +2. Сравним, равен ли символ своей большой (заглавной) версии +3. Вернём результат + +```javascript +const isFirstLetterInUpperCase = (string) => { + const firstLetter = string[0]; + return firstLetter.toUpperCase() === firstLetter; +}; + +isFirstLetterInUpperCase('marmont'); // false +isFirstLetterInUpperCase('Robb'); // true +``` + +https://replit.com/@hexlet/js-basics-logica-operations diff --git a/modules/45-logic/20-logic-combine-expressions/ru/data.yml b/modules/45-logic/20-logic-combine-expressions/ru/data.yml new file mode 100644 index 0000000..e38a0ed --- /dev/null +++ b/modules/45-logic/20-logic-combine-expressions/ru/data.yml @@ -0,0 +1,9 @@ +name: Комбинирование логических операций +tips: + - | + [Выражение](https://ru.wikipedia.org/wiki/Выражение_(информатика)) +definitions: + - name: Выражение + description: > + последовательность действий над данными, приводящая к каком-то результату, + который можно использовать. diff --git a/modules/45-logic/25-logical-operators/ru/EXERCISE.md b/modules/45-logic/25-logical-operators/ru/EXERCISE.md new file mode 100644 index 0000000..4107661 --- /dev/null +++ b/modules/45-logic/25-logical-operators/ru/EXERCISE.md @@ -0,0 +1,19 @@ + +Реализуйте функцию `isLeapYear()`, которая определяет, является ли год високосным или нет. Год будет високосным, если он кратен (то есть делится без остатка) 400 или он одновременно кратен 4 и не кратен 100. Как видите, в определении уже заложена вся необходимая логика, осталось только переложить её на код: + +```javascript +isLeapYear(2018); // false +isLeapYear(2017); // false +isLeapYear(2016); // true +``` + +Кратность можно проверять так: + +```javascript +// % - возвращает остаток от деления левого операнда на правый +// Проверяем что number кратен 10 +number % 10 === 0 + +// Проверяем что number не кратен 10 +number % 10 !== 0 +``` diff --git a/modules/45-logic/25-logical-operators/ru/README.md b/modules/45-logic/25-logical-operators/ru/README.md new file mode 100644 index 0000000..1c370d6 --- /dev/null +++ b/modules/45-logic/25-logical-operators/ru/README.md @@ -0,0 +1,99 @@ + +Логические выражения могут объединяться друг с другом, создавая все более хитрые проверки. Хороший пример: проверка пароля. Как вы знаете, некоторые сайты при регистрации хотят пароль от 8 до 20 символов в длину. Честно говоря, это странное ограничение, но что поделать. В математике мы бы написали `8 < x < 20` (где `x` это длина конкретного пароля), но в JavaScript такой трюк не пройдет. Нам придётся сделать два отдельных логических выражения и соединить их специальным оператором «И»: + +``` +Пароль длиннее 8 символов **И** пароль короче 20 символов. +``` + +Вот функция, которая принимает пароль и говорит, соответствует ли он условиям, или не соответствует: + +```javascript +const isStrongPassword = (password) => { + const length = password.length; + return length > 8 && length < 20; +}; + +isStrongPassword('qwerty'); // false +isStrongPassword('qwerty1234'); // true +isStrongPassword('zxcvbnmasdfghjkqwertyui'); // false +``` + +`&&` - означает «И» (в математической логике это называют конъюнкцией). Всё выражение считается истинным только в том случае, когда истинен каждый операнд — каждое из составных выражений. Иными словами, `&&` означает «и то, и другое». + +Приоритет этого оператора ниже, чем приоритет операторов сравнения, поэтому выражение отрабатывает правильно без скобок. + +Кроме `&&`, часто используется оператор `||` — «ИЛИ» (дизъюнкция). Он означает «или то, или другое, или оба». Операторы можно комбинировать в любом количестве и любой последовательности, но когда одновременно встречаются `&&` и `||`, то приоритет лучше задавать скобками. Ниже пример расширенной функции определения корректности пароля: + +```javascript +const hasSpecialChars = (str) => /* проверяет содержание специальных символов в строке */; + +const hasCapitalChars = (str) => /* проверяет содержание заглавных букв в строке */ + +const isStrongPassword = (password) => { + const length = password.length; + // Скобки задают приоритет. Понятно что к чему относится. + return length > 8 && (hasSpecialChars(password) || hasCapitalChars(password)); +}; +``` + +Другой пример. Мы хотим купить квартиру, которая удовлетворяет условиям: площадь от 100 кв. метров и больше на любой улице **ИЛИ** площадь от 80 кв. метров и больше, но на центральной улице `Main Street`. + +Напишем функцию, проверяющую квартиру. Она принимает два аргумента: площадь (число) и название улицы (строку): + +```javascript +const isGoodApartment = (area, street) => { + // Через переменную, чтобы функция была не слишком длинной + const result = area >= 100 || (area >= 80 && street === 'Main Street'); + return result; +}; + +isGoodApartment(91, 'Queens Street'); // false +isGoodApartment(78, 'Queens Street'); // false +isGoodApartment(70, 'Main Street'); // false + +isGoodApartment(120, 'Queens Street'); // true +isGoodApartment(120, 'Main Street'); // true +isGoodApartment(80, 'Main Street'); // true +``` + +https://replit.com/@hexlet/js-basics-logical-operators + +Область математики, в которой изучаются логические операторы, называется булевой алгеброй. Ниже показаны «таблицы истинности» — по ним можно определить, каким будет результат применения оператора: + +## И `&&` + +| A | B | A && B | +|-------| ------|----------| +| TRUE | TRUE | **TRUE** | +| TRUE | FALSE | FALSE | +| FALSE | TRUE | FALSE | +| FALSE | FALSE | FALSE | + +Пара примеров: + +```javascript +// true && true; +3 > 2 && 'wow'.startsWith('w'); // true + +// true && false; +'start' === 'start' && 8 < 3; // false +``` + +## ИЛИ `||` + +| A | B | A || B | +|-------|-------|----------| +| TRUE | TRUE | **TRUE** | +| TRUE | FALSE | **TRUE** | +| FALSE | TRUE | **TRUE** | +| FALSE | FALSE | FALSE | + +Пара примеров: + +```javascript +// true || true; +3 > 2 || 'wow'.startsWith('w'); // true + +// false || false; +'start' === 'Start' || 3 < 3; // false +``` diff --git a/modules/45-logic/25-logical-operators/ru/data.yml b/modules/45-logic/25-logical-operators/ru/data.yml new file mode 100644 index 0000000..cb8576a --- /dev/null +++ b/modules/45-logic/25-logical-operators/ru/data.yml @@ -0,0 +1,13 @@ +name: Логические операторы +tips: + - | + [Булева алгебра](https://ru.wikipedia.org/wiki/Булева_алгебра) + - | + [Конъюнкция](https://ru.wikipedia.org/wiki/Конъюнкция) + - | + [Дизъюнкция](https://ru.wikipedia.org/wiki/Дизъюнкция) +definitions: + - name: Логические операторы + description: >- + операторы «И» (&&), «ИЛИ» (||), позволяющие создавать составные логические + условия. diff --git a/modules/45-logic/28-logical-negation/ru/EXERCISE.md b/modules/45-logic/28-logical-negation/ru/EXERCISE.md new file mode 100644 index 0000000..00102e8 --- /dev/null +++ b/modules/45-logic/28-logical-negation/ru/EXERCISE.md @@ -0,0 +1,30 @@ + +В этом уроке вам нужно будет реализовать две функции `isPalindrome()` и `isNotPalindrome()` + +1. Функция `isPalindrome()` определяет, является ли слово палиндромом или нет. Палиндром это слово, которое читается одинаково в обоих направлениях. + + ```javascript + isPalindrome('шалаш'); // true + isPalindrome('ага'); // true + isPalindrome('хекслет'); // false + + // Слова в функцию могут быть переданы в любом регистре + // Поэтому сначала нужно привести слово в нижний регистр word.toLowerCase() + isPalindrome('Ага'); // true + ``` + + Для определения палиндрома необходимо перевернуть строку и сравнить ее с исходной. Для этого воспользуйтесь функцией `reverse()` + + ```javascript + reverse('мама'); // амам + ``` + +2. Функция `isNotPalindrome()` проверяет что слово НЕ является палиндромом: + + ```javascript + isNotPalindrome('шалаш'); // false + isNotPalindrome('ага'); // false + isNotPalindrome('хекслет'); // true + ``` + + Для этого, вызовите функцию `isPalindrome()` внутри `isNotPalindrome()` и примените отрицание. diff --git a/modules/45-logic/28-logical-negation/ru/README.md b/modules/45-logic/28-logical-negation/ru/README.md new file mode 100644 index 0000000..69dc65f --- /dev/null +++ b/modules/45-logic/28-logical-negation/ru/README.md @@ -0,0 +1,25 @@ + +Наряду с конъюнкцией (И) и дизъюнкцией (ИЛИ), часто используется операция «отрицание». Отрицание меняет логическое значение на противоположное. В программировании ему соответствует унарный оператор `!`. + +Если есть функция, проверяющая чётность числа, то с помощью отрицания можно выполнить проверку нечётности: + +```javascript +const isEven = (number) => number % 2 === 0; + +isEven(10); // true +!isEven(10); // false +``` + +https://replit.com/@hexlet/js-basics-logical-negation + +То есть мы просто добавили `!` слева от вызова функции и получили обратное действие. + +Отрицание — мощный инструмент, который позволяет лаконично выражать задуманные правила в коде без необходимости писать новые функции. + +А что если написать так `!!isEven(10)`? Внезапно, но код сработает. В логике двойное отрицание подобно отсутствию отрицания вообще. + +```javascript +isEven(10); // true +!isEven(10); // false +!!isEven(10); // true +``` diff --git a/modules/45-logic/28-logical-negation/ru/data.yml b/modules/45-logic/28-logical-negation/ru/data.yml new file mode 100644 index 0000000..b892f6d --- /dev/null +++ b/modules/45-logic/28-logical-negation/ru/data.yml @@ -0,0 +1,9 @@ +name: Отрицание +tips: + - | + [Законы Де Моргана](https://ru.wikipedia.org/wiki/Законы_де_Моргана) +definitions: + - name: Отрицание + description: > + логическая операция, которая меняет логическое значение на + противоположное. diff --git a/modules/45-logic/70-logical-expressions/ru/EXERCISE.md b/modules/45-logic/70-logical-expressions/ru/EXERCISE.md new file mode 100644 index 0000000..3bdc0ce --- /dev/null +++ b/modules/45-logic/70-logical-expressions/ru/EXERCISE.md @@ -0,0 +1,18 @@ + +Реализуйте функцию `getLetter()`, которая извлекает из переданной строки указанный символ (по порядковому номеру, а не по его индексу) и возвращает его наружу. Если такого символа нет, то функция возвращает пустую строку. + +Примеры вызова: + +```javascript +const name = 'Hexlet'; + +// Обычное обращение возвращает undefined +name[10]; // undefined + +// 11 символ соответствует 10 индексу +getLetter(name, 11); // '' + +getLetter(name, 1); // 'H' +getLetter(name, 0); // '' +getLetter(name, 6); // 't' +``` diff --git a/modules/45-logic/70-logical-expressions/ru/README.md b/modules/45-logic/70-logical-expressions/ru/README.md new file mode 100644 index 0000000..a0b1a1f --- /dev/null +++ b/modules/45-logic/70-logical-expressions/ru/README.md @@ -0,0 +1,131 @@ + +Посмотрите на код ниже и попробуйте угадать, что будет напечатано на экран? + +```javascript +console.log(0 || 1); +``` + +Правильный ответ: + +
+  1
+
+ +Оператор **ИЛИ** работает так, что его выполнение (слева направо) прерывается и возвращается результат первого аргумента, который можно преобразовать в `true`. + +Ниже пример с оператором **И**: + +```javascript +console.log(0 && 1); +``` + +
+  0
+
+ +Оператор **И** работает так, что его выполнение (слева направо) прерывается и возвращается результат первого аргумента, который можно преобразовать в `false`. + +В JavaScript есть два простых правила, по которым происходят преобразования: + +* `0`, `''`, `undefined`, `NaN`, `null` приводятся к `false`. Эти значения называют [falsy](https://developer.mozilla.org/ru/docs/Glossary/Falsy). +* Всё остальное приводится к `true` + +Этим активно пользуются в разработке, например, для определения значения по умолчанию: + +```javascript +const value = name || ''; +// Примеры +234 || ''; // 234 +'hexlet' || ''; // 'hexlet' +undefined || ''; // '' +``` + +https://replit.com/@hexlet/js-basics-logical-expressions + +Если `name` примет одно из falsy-значений, константе `value` будет присвоена пустая строка. В этом случае в последующем коде мы сможем работать с `value` как со строкой. + +Но здесь есть потенциальный баг. Если `name` содержит falsy-значение, а присваивание константе value значений типа `0`, `undefined`, `NaN` или `null` допустимо, то код выше начнет работать неверно: + +```javascript +// Упс +false || ''; // '' +0 || ''; // '' +undefined || ''; // '' +``` + +В одном из уроков мы рассмотрели операторы сравнения `===` и `!==` и упомянули, что в JavaScript так же есть операторы `==` и `!=`, но их не стоит использовать. Отличия как раз заключаются в преобразовании типов: + +```javascript +console.log('' === false); // => false +console.log('' == false); // => true +``` + +Пустая строка и `false` — это разные значения, поэтому оператор `===` говорит «ложь! они не равны!». + +Но оператор `==` преобразует типы, и с его точки зрения пустая строка и `false` равны. + +Это преобразование неявное, поэтому по возможности избегайте операторов `==` и `!=`. + +--- + +Вспомните операцию отрицания: + +```javascript +const answer = true; +console.log(!answer); // => false +``` + +Отрицание работает внутри выражений: + +```javascript +!false || ''; // true +``` + +Если выражение обернуть в скобки и поставить перед ними `!`, то будет отрицание всего выражения: + +```javascript +// Выражение обернуто в скобки +console.log(!('' === false)); // => true +console.log(!('' == false)); // => false +``` + +При двойном отрицании `!!` итоговое значение равно начальному: + +```javascript +const answer = true; +console.log(!!answer); // => true +``` + +Но здесь дополнительно может происходить преобразование типа. Поэтому результатом двойного отрицания всегда будет значение типа *boolean*. Этим приемом иногда пользуются, чтобы поменять тип данных. + +## Ошибка выбора + +Представьте себе задачу, в которой нам нужно проверить, что значение равно либо одному, либо другому. Например переменная `value` должна содержать одно из двух значений: `first` или `second`. Начинающие разработчики иногда записывают это выражение так: + +```javascript +value === ('first' || 'second') +``` + +В голове мы это себе примерно так и представляем, но языки работают по-другому, поэтому такой код приведет к неверному результату. Как его правильно прочитать? Мы должны вспомнить приоритет выполнения операций. Первым делом вычисляется все что указано в скобках, то есть `'first' || 'second'`. Если выполнить этот код в repl, то вывод будет таким: + +```bash +node +'Welcome to Node.js v17.4.0. +> 'first' || 'second' +'first' +> +``` + +Теперь мы можем заменить исходное выражение, на частично вычисленное: + +```javascript +value === 'first' +``` + +Совсем не то, что мы ожидали. А теперь вернемся к началу, и напишем проверку правильно: + +```javascript +// Скобки ставить не обязательно, +// потому что приоритет === выше чем приоритет || +value === 'first' || value === 'second' +``` diff --git a/modules/45-logic/70-logical-expressions/ru/data.yml b/modules/45-logic/70-logical-expressions/ru/data.yml new file mode 100644 index 0000000..358f2ec --- /dev/null +++ b/modules/45-logic/70-logical-expressions/ru/data.yml @@ -0,0 +1,7 @@ +name: Результат логических выражений +tips: + - | + [Boolean](https://ru.wikipedia.org/wiki/Логический_тип) + - > + [Извлечение символов из + строки](https://ru.code-basics.com/languages/javascript/lessons/symbols) diff --git a/modules/48-conditionals/30-if/ru/EXERCISE.md b/modules/48-conditionals/30-if/ru/EXERCISE.md new file mode 100644 index 0000000..cc8037e --- /dev/null +++ b/modules/48-conditionals/30-if/ru/EXERCISE.md @@ -0,0 +1,7 @@ + +Реализуйте функцию `guessNumber()`, которая принимает число и проверяет, равно ли число заданному (пусть это будет 42). Если равно, то функция должна вернуть строку `'You win!'`, в противном случае нужно вернуть строку `'Try again!'`. + +```javascript +guessNumber(42) // You win! +guessNumber(61) // Try again! +``` diff --git a/modules/48-conditionals/30-if/ru/README.md b/modules/48-conditionals/30-if/ru/README.md new file mode 100644 index 0000000..bac771e --- /dev/null +++ b/modules/48-conditionals/30-if/ru/README.md @@ -0,0 +1,43 @@ + +Условные конструкции позволяют изменить поведение программы в зависимости от проверяемых условий. Благодаря им у нас появляется возможность писать сложные программы, ведущие себя по разному, в зависимости от ситуации. + +Напишем, для примера, функцию, которая определяет тип переданного предложения. Для начала она будет отличать обычные предложения от вопросительных. + +```javascript +const getTypeOfSentence = (sentence) => { + const lastChar = sentence[sentence.length - 1]; + if (lastChar === '?') { + return 'question'; + } + + return 'general'; +}; + +getTypeOfSentence('Hodor'); // general +getTypeOfSentence('Hodor?'); // question +``` + +https://replit.com/@hexlet/js-basics-if + +`if` - конструкция языка, управляющая порядком выполнения инструкций. В скобках ей передается выражение-предикат, а затем описывается блок кода в фигурных скобках. Этот блок кода будет выполнен, только если предикат — истина. + +Если предикат — ложь, то блок кода в фигурных скобках пропускается, и функция продолжает свое выполнение дальше. В нашем случае следующая строчка кода — `return 'general';` — заставит функцию вернуть строку и завершиться. + +Как видите, `return` может находиться где угодно в функции. В том числе внутри блока кода с условием. + +Если в фигурных скобках после `if` содержится только одна строчка кода, то фигурные скобки можно не писать и сделать так: + +```javascript +const getTypeOfSentence = (sentence) => { + const lastChar = sentence[sentence.length - 1]; + if (lastChar === '?') + return 'question'; + + return 'general'; +}; + +console.log(getTypeOfSentence('Hodor')); // => general +console.log(getTypeOfSentence('Hodor?')); // => question +``` + +Советуем не делать так и **всегда писать фигурные скобки**. В таком случае явно видно, где начинается и заканчивается тело условия. Код становится более чётким и понятным. diff --git a/modules/48-conditionals/30-if/ru/data.yml b/modules/48-conditionals/30-if/ru/data.yml new file mode 100644 index 0000000..fd9d0e2 --- /dev/null +++ b/modules/48-conditionals/30-if/ru/data.yml @@ -0,0 +1,8 @@ +name: Условная конструкция (if) +tips: + - > + [if](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) +definitions: + - name: Условные конструкции + description: | + изменяют поведение программы в зависимости от проверяемых условий diff --git a/modules/48-conditionals/40-if-else/ru/EXERCISE.md b/modules/48-conditionals/40-if-else/ru/EXERCISE.md new file mode 100644 index 0000000..b534df0 --- /dev/null +++ b/modules/48-conditionals/40-if-else/ru/EXERCISE.md @@ -0,0 +1,13 @@ + +Реализуйте функцию `normalizeUrl()`, которая выполняет так называемую нормализацию данных. Она принимает адрес сайта и возвращает его с *https://* в начале. + +Функция принимает адреса в виде *АДРЕС* или *https://АДРЕС*, но всегда возвращает адрес в виде *https://АДРЕС* + +Можно использовать метод [startsWith()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith), чтобы проверить, начинается ли строка с префикса *https://*. А потом на основе этого добавлять или не добавлять *https://*. + +Примеры вызова: + +```javascript +normalizeUrl("google.com"); // "https://google.com" +normalizeUrl("https://ai.fi"); // "https://ai.fi" +``` diff --git a/modules/48-conditionals/40-if-else/ru/README.md b/modules/48-conditionals/40-if-else/ru/README.md new file mode 100644 index 0000000..effa5f8 --- /dev/null +++ b/modules/48-conditionals/40-if-else/ru/README.md @@ -0,0 +1,54 @@ + +Напишем функцию `getTypeOfSentence()`, которая анализирует текст и возвращает описание его тона: для обычных предложений – *General sentence*, для вопросительных – *Question sentence*. + +```javascript + getTypeOfSentence('Hodor'); // General sentence + getTypeOfSentence('Hodor?'); // Question sentence +``` + +Реализация функции: + +```javascript +const getTypeOfSentence = (sentence) => { + // Объявляем переменную, в которую запишем тип предложения + let sentenceType; + // Предикат, проверяющий окончание текста + // Если он оканчивается на символ '?', то вернётся true, + // иначе false + if (sentence.endsWith('?')) { + // Если условие выше сработало, + // то это вопросительное предложение. + // Присваиваем sentenceType соответствующее значение. + sentenceType = 'Question'; + } else { + // Во всех остальных случаях предложение — обычное + sentenceType = 'General'; + } + + // С помощью интерполяции формируем строку + return `${sentenceType} sentence`; +}; +``` + +https://replit.com/@hexlet/js-basics-if-else + +Мы добавили ключевое слово `else` и новый блок с фигурными скобками. Этот блок выполнится, только если условие в `if` — ложь. + +Существует два способа оформления конструкции *if-else*. С помощью отрицания можно изменить порядок блоков: + +```javascript +const getTypeOfSentence = (sentence) => { + let sentenceType; + // Добавилось отрицание + // Содержимое else переехало в if и наоборот + if (!sentence.endsWith('?')) { + sentenceType = 'General'; + } else { + sentenceType = 'Question'; + } + + return `${sentenceType} sentence`; +}; +``` + +Какой способ предпочтительнее? Человеческому мозгу проще мыслить прямолинейно, а не через отрицание. Старайтесь выбирать проверку, которая не содержит отрицаний, и подстраивайте содержимое блоков под неё. diff --git a/modules/48-conditionals/40-if-else/ru/data.yml b/modules/48-conditionals/40-if-else/ru/data.yml new file mode 100644 index 0000000..5a3244e --- /dev/null +++ b/modules/48-conditionals/40-if-else/ru/data.yml @@ -0,0 +1,9 @@ +name: else +tips: + - > + [if...else](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) +definitions: + - name: else + description: >- + способ задать блок кода, который будет выполнен, если условие с `if` не + удовлетворено diff --git a/modules/48-conditionals/50-else-if/ru/EXERCISE.md b/modules/48-conditionals/50-else-if/ru/EXERCISE.md new file mode 100644 index 0000000..be41fae --- /dev/null +++ b/modules/48-conditionals/50-else-if/ru/EXERCISE.md @@ -0,0 +1,19 @@ + +На электронной карте Вестероса, которую реализовал Сэм, союзники Старков отображены зеленым кружком, враги — красным, а нейтральные семьи — серым. + +Напишите для Сэма функцию `whoIsThisHouseToStarks()`, которая принимает на вход фамилию семьи и возвращает одно из трёх значений: `'friend'`, `'enemy'`, `'neutral'`. + +Правила определения: + +* Друзья (`'friend'`): 'Karstark', 'Tally' +* Враги (`'enemy'`): 'Lannister', 'Frey' +* Любые другие семьи считаются нейтральными + +Примеры вызова: + +```javascript +whoIsThisHouseToStarks('Karstark'); // friend +whoIsThisHouseToStarks('Frey'); // enemy +whoIsThisHouseToStarks('Joar'); // neutral +whoIsThisHouseToStarks('Ivanov'); // neutral +``` diff --git a/modules/48-conditionals/50-else-if/ru/README.md b/modules/48-conditionals/50-else-if/ru/README.md new file mode 100644 index 0000000..093ce65 --- /dev/null +++ b/modules/48-conditionals/50-else-if/ru/README.md @@ -0,0 +1,63 @@ + +Функция `getTypeOfSentence()` из предыдущего урока различает только вопросительные и обычные предложения. Давайте попробуем добавить поддержку восклицательных предложений: + +```javascript +const getTypeOfSentence = (sentence) => { + const lastChar = sentence[sentence.length - 1]; + let sentenceType; + + if (lastChar === '!') { + sentenceType = 'exclamation'; + } else { + sentenceType = 'normal'; + } + + if (lastChar === '?') { + sentenceType = 'question'; + } + + return `Sentence is ${sentenceType}`; +}; + +getTypeOfSentence('Who?'); // Sentence is question +getTypeOfSentence('No'); // Sentence is normal +getTypeOfSentence('No!'); // Sentence is exclamation +``` + +https://replit.com/@hexlet/js-basics-conditionals + +Мы добавили ещё одну проверку ("exclamation" переводится «восклицание»). Технически функция работает, но с точки зрения семантики есть проблемы. + +- Проверка на наличие вопросительного знака происходит в любом случае, даже если уже был обнаружен восклицательный знак. +- Ветка `else` описана именно для первого условия, но не для второго. + +Правильнее будет воспользоваться ещё одной возможностью условной конструкции: + +```javascript +const getTypeOfSentence = (sentence) => { + const lastChar = sentence[sentence.length - 1]; + let sentenceType; + + if (lastChar === '?') { + sentenceType = 'question'; + } else if (lastChar === '!') { + sentenceType = 'exclamation'; + } else { + sentenceType = 'normal'; + } + + return `Sentence is ${sentenceType}`; +}; + +getTypeOfSentence('Who?'); // Sentence is question +getTypeOfSentence('No'); // Sentence is normal +getTypeOfSentence('No!'); // Sentence is exclamation +``` + +Теперь все условия выстроены в единую конструкцию. `else if` — это «если не выполнено предыдущее условие, но выполнено текущее». Получается такая схема: + +- если последний символ это `?`, то `'question'` +- иначе, если последний символ это `!`, то `'exclamation'` +- иначе `'normal'` + +Выполнится только один из блоков кода, относящихся ко всей конструкции `if`. diff --git a/modules/48-conditionals/50-else-if/ru/data.yml b/modules/48-conditionals/50-else-if/ru/data.yml new file mode 100644 index 0000000..2d46cb3 --- /dev/null +++ b/modules/48-conditionals/50-else-if/ru/data.yml @@ -0,0 +1,8 @@ +name: Конструкция else if +tips: + - > + [else + if](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else#using_else_if) +definitions: + - name: else if + description: способ задать несколько альтернативных условий. diff --git a/modules/48-conditionals/60-ternary-operator/ru/EXERCISE.md b/modules/48-conditionals/60-ternary-operator/ru/EXERCISE.md new file mode 100644 index 0000000..41f1a95 --- /dev/null +++ b/modules/48-conditionals/60-ternary-operator/ru/EXERCISE.md @@ -0,0 +1,27 @@ + +Реализуйте функцию `convertText()`, которая принимает на вход строку и, если первая буква не заглавная, возвращает перевернутый вариант исходной строки. Если первая буква заглавная, то строка возвращается без изменений. Если на вход передана пустая строка, функция должна вернуть пустую строку. + +Примеры вызова: + +```javascript +convertText('Hello'); // Hello +convertText('hello'); // olleh + +// Не забудьте учесть пустую строку +convertText(''); // '' +``` + +Перевернуть строчку можно используя функцию `reverse()`. В качестве аргумента в неё нужно передать строку, которую мы хотим перевернуть: + +```javascript +const result = reverse('Hello!'); +console.log(result); // => !olleH +``` + +Есть разные подходы к решению этой задачи. Возможно, вам пригодится метод [toUpperCase()](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) и возможность получения символа из строки (например, `str[0]`). + +Попробуйте написать два варианта функции: с обычным if-else, и с тернарным оператором. + +## Подсказки + +* Подумайте какую проверку нужно написать первым делом: проверку заглавности буквы или является ли пустой строка. Что первичнее? diff --git a/modules/48-conditionals/60-ternary-operator/ru/README.md b/modules/48-conditionals/60-ternary-operator/ru/README.md new file mode 100644 index 0000000..b9e518a --- /dev/null +++ b/modules/48-conditionals/60-ternary-operator/ru/README.md @@ -0,0 +1,72 @@ + +Посмотрите на определение функции, которая возвращает модуль переданного числа: + +```javascript +const abs = (number) => { + if (number >= 0) { + return number; + } + + return -number; +}; + +abs(10); // 10 +abs(-10); // 10 +``` + +Можно ли записать её лаконичнее? Что-то вроде `return <ответ в зависимости от условия>`? Для этого справа от return должно быть выражение, но `if` — это инструкция, а не выражение. + +В JavaScript существует конструкция, которая по своему действию аналогична конструкции *if-else*, но при этом является выражением. Она называется **тернарный оператор**. + +Тернарный оператор — единственный в своем роде оператор, требующий три операнда: + +```javascript +const abs = (number) => { + return number >= 0 ? number : -number; +}; +``` + +Общий паттерн выглядит так: ` ? : `. + +Сокращенный вариант функции `abs()`, выглядит так: + +```javascript +const abs = (number) => (number >= 0 ? number : -number); +``` + +Обратите внимание на скобки вокруг тернарника. Они не обязательны, но линтер [настоятельно рекомендует](https://eslint.org/docs/rules/no-confusing-arrow) их ставить, во избежание неоднозначностей. + +Давайте перепишем начальный вариант `getTypeOfSentence()` аналогично: + +Было: + +```javascript +const getTypeOfSentence = (sentence) => { + const lastChar = sentence.slice(-1); + + if (lastChar === '?') { + return 'question'; + } + + return 'normal'; +}; +``` + +Стало: + +```javascript +const getTypeOfSentence = (sentence) => { + const lastChar = sentence.slice(-1); + + return (lastChar === '?') ? 'question' : 'normal'; +}; + +getTypeOfSentence('Hodor'); // normal +getTypeOfSentence('Hodor?'); // question +``` + +https://replit.com/@hexlet/js-basics-ternary-operator + +--- + +Если вы помните, в чём сила выражений, то вероятно уже догадались, что тернарный оператор можно вкладывать в тернарный оператор. **Не делайте этого :)** Такой код тяжело и читать, и отлаживать, это очень плохая практика. diff --git a/modules/48-conditionals/60-ternary-operator/ru/data.yml b/modules/48-conditionals/60-ternary-operator/ru/data.yml new file mode 100644 index 0000000..ac8ad0c --- /dev/null +++ b/modules/48-conditionals/60-ternary-operator/ru/data.yml @@ -0,0 +1,10 @@ +name: Тернарный оператор +tips: + - > + [Подробнее о тернарном + операторе](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) +definitions: + - name: Тернарный оператор + description: > + Способ превратить простую условную инструкцию в выражение, например, + `number >= 0 ? number : -number`. diff --git a/modules/48-conditionals/65-switch/ru/EXERCISE.md b/modules/48-conditionals/65-switch/ru/EXERCISE.md new file mode 100644 index 0000000..771a5c0 --- /dev/null +++ b/modules/48-conditionals/65-switch/ru/EXERCISE.md @@ -0,0 +1,15 @@ + +Реализуйте функцию `getNumberExplanation()`, которая принимает на вход число и возвращает объяснение этого числа. Если для числа нет объяснения, то возвращается `just a number`. Объяснения есть только для следующих чисел: + + * 666 - devil number + * 42 - answer for everything + * 7 - prime number + +Примеры вызова функции: + +```javascript +getNumberExplanation(8); // just a number +getNumberExplanation(666); // devil number +getNumberExplanation(42); // answer for everything +getNumberExplanation(7); // prime number +``` diff --git a/modules/48-conditionals/65-switch/ru/README.md b/modules/48-conditionals/65-switch/ru/README.md new file mode 100644 index 0000000..3dcaaa8 --- /dev/null +++ b/modules/48-conditionals/65-switch/ru/README.md @@ -0,0 +1,98 @@ + +Многие языки в дополнение к условной конструкции *if* включают в себя **switch**. Это специализированная версия *if*, созданная для некоторых особых ситуаций. Например, её имеет смысл использовать там, где есть цепочка *if else* с проверками на равенство. Например: + +```javascript +if (status === 'processing') { + // Делаем раз +} else if (status === 'paid') { + // Делаем два +} else if (status === 'new') { + // Делаем три +} else { + // Делаем четыре +} +``` + +Эта составная проверка обладает одной отличительной чертой: каждая ветка здесь — это проверка значения переменной `status`. Switch позволяет записать этот код короче и выразительнее: + +```javascript +switch (status) { + case 'processing': // status === processing + // Делаем раз + break; + case 'paid': // status === paid + // Делаем два + break; + case 'new': // status === new + // Делаем три + break; + default: // else + // Делаем четыре +} +``` + +Свитч — довольно сложная конструкция с точки зрения количества элементов, из которых она состоит: + +* Внешнее описание, в которое входит ключевое слово `switch`. Переменная, по значениям которой *switch* будет выбирать поведение. И фигурные скобки для вариантов выбора. +* Конструкции `case` и `default`, внутри которых описывается поведение для разных значений рассматриваемой переменной. Каждый `case` соответствует `if` в примере выше. `default` - это особая ситуация, соответствующая ветке `else` в условных конструкциях. Как `else`, указывать `default` не обязательно (но линтер всегда его [просит](https://eslint.org/docs/rules/default-case)). +* `break` нужен для предотвращения «проваливания». Если его не указать, то после выполнения нужного `case` выполнение перейдет к следующему `case`, и так либо до ближайшего `break`, либо до конца *switch*. + +Фигурные скобки в *switch* не определяют блок кода, как это было в других местах. Внутри допустим только тот синтаксис, который показан выше. То есть там можно использовать `case` или `default`. А вот внутри каждого `case` (и `default`) ситуация другая. Здесь можно выполнять любой произвольный код: + +```javascript +switch (count) { + case 1: + // Делаем что-то полезное + break; + case 2: + // Делаем что-то полезное + break; + default: + // Что-то делаем +} +``` + +Иногда, результат, полученный внутри `case`, — это конец выполнения функции, содержащей *switch*. В таком случае его нужно как-то вернуть наружу. Для решения этой задачи есть два способа. + +Первый. Создать переменную перед *switch*, заполнить её в *case* и затем, в конце, вернуть значение этой переменной наружу. + +```javascript +(count) => { + // Объявляем переменную + let result; + + // Заполняем + switch (count) { + case 1: + result = 'one'; + break; + case 2: + result = 'two'; + break; + default: + result = null; + } + + // Возвращаем + return result; +}; +``` + +Второй способ проще и короче. Вместо создания переменной, *case* позволяет внутри себя делать обычный возврат из функции. А так как после `return` никакой код не выполняется, то мы можем избавиться от `break`: + +```javascript +(count) => { + switch (count) { + case 1: + return 'one'; + case 2: + return 'two'; + default: + return null; + } +}; +``` + +https://replit.com/@hexlet/js-basics-switch + +Switch хоть и встречается в коде, но технически всегда можно обойтись без него. Ключевая польза при его использовании в том, что он лучше выражает намерение программиста, когда нужно проверять конкретные значения переменной. Хотя кода и стало физически чуть больше, читать его легче, в отличие от блоков *else if*. diff --git a/modules/48-conditionals/65-switch/ru/data.yml b/modules/48-conditionals/65-switch/ru/data.yml new file mode 100644 index 0000000..e87987e --- /dev/null +++ b/modules/48-conditionals/65-switch/ru/data.yml @@ -0,0 +1,5 @@ +name: Конструкция Switch +tips: + - > + [switch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/switch) +definitions: [] diff --git a/modules/50-loops/10-while/ru/EXERCISE.md b/modules/50-loops/10-while/ru/EXERCISE.md new file mode 100644 index 0000000..3c99696 --- /dev/null +++ b/modules/50-loops/10-while/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Модифицируйте функцию `printNumbers()` так, чтобы она выводила числа в обратном порядке. Для этого нужно идти от верхней границы к нижней. То есть счётчик должен быть инициализирован максимальным значением, а в теле цикла его нужно уменьшать до нижней границы. + +```javascript +printNumbers(4); +``` + +
4
3
2
1
finished!
diff --git a/modules/50-loops/10-while/ru/README.md b/modules/50-loops/10-while/ru/README.md new file mode 100644 index 0000000..3b3467a --- /dev/null +++ b/modules/50-loops/10-while/ru/README.md @@ -0,0 +1,105 @@ + +Программы, которые мы пишем, становятся всё сложнее и объемнее. Они все ещё очень далеки от реальных программ, где количество строк кода измеряется десятками и сотнями тысяч (а иногда и миллионами), но текущая сложность уже способна заставить напрячься людей без опыта. Начиная с этого урока, мы переходим к одной из самых сложных базовых тем в программировании – циклам. + +Любые прикладные программы служат очень прагматичным целям. Они помогают управлять сотрудниками, финансами, развлекают в конце концов. Несмотря на различия, все эти программы выполняют заложенные в них алгоритмы, которые очень похожи между собой. Что это такое? Алгоритм — это последовательность действий (инструкций), которая приводит нас к некоему ожидаемому результату. В принципе, это описание подходит под любую программу, но под алгоритмами обычно понимается что-то более специфичное. + +Представьте себе, что у нас есть книга и мы хотим найти внутри неё какую-то конкретную фразу. Саму фразу мы помним, но не знаем, на какой она странице. Как найти нужную страницу? Самый простой (и долгий) способ — последовательно просматривать страницы до тех пор, пока мы не найдем нужную. В худшем случае придется просмотреть все страницы, но результат мы всё равно получим. Именно этот процесс и называется алгоритмом. Он включает в себя логические проверки (нашли ли фразу) и перебор страниц. Количество страниц, которое придется посмотреть, заранее неизвестно, но сам процесс просмотра повторяется из раза в раз совершенно одинаковым образом. Для выполнения повторяющихся действий как раз и нужны циклы. Каждый повтор, в таком случае, называется итерацией. + +Допустим мы хотим написать функцию, которая выводит на экран все числа от 1 до указанного (через аргументы): + +```javascript +printNumbers(3); +// => 1 +// => 2 +// => 3 +``` + +Эту функцию невозможно реализовать уже изученными средствами, так как количество выводов на экран заранее неизвестно. А с циклами это не составит никаких проблем: + +```javascript +const printNumbers = (lastNumber) => { + // i сокращение от index (порядковый номер) + // используется по общему соглашению во множестве языков + // как счетчик цикла + let i = 1; + + while (i <= lastNumber) { + console.log(i); + i = i + 1; + } + console.log('finished!'); +}; + +printNumbers(3); +``` + +
+1
+2
+3
+finished!
+
+ +https://replit.com/@hexlet/js-basics-while + +В коде функции использован цикл `while`. Он состоит из трёх элементов: + +* Ключевое слово `while`. Несмотря на схожесть с вызовом функций, это не вызов функции. +* Предикат. Условие, которое указывается в скобках после `while`. Это условие вычисляется и проверяется перед выполнением тела цикла на каждой итерации. +* Тело цикла. Блок кода в фигурных скобках. Этот блок аналогичен блоку кода в функциях. Всё, что определено внутри этого блока (константы или переменные), видно только внутри этого блока. + +Конструкция читается так: «пока истинно условие (предикат) `i <= lastNumber` делать то, что указано в теле цикла». Разберём работу этого кода для вызова `printNumbers(3)`: + +```javascript +// Инициализируется i +let i = 1; + +// Предикат возвращает true, поэтому выполняется тело цикла +while (1 <= 3) +// console.log(1); +// i = 1 + 1; + +// Закончилось тело цикла, поэтому происходит возврат в начало +while (2 <= 3) +// console.log(2); +// i = 2 + 1; + +// Закончилось тело цикла, поэтому происходит возврат в начало +while (3 <= 3) +// console.log(3); +// i = 3 + 1; + +// Предикат возвращает false, поэтому выполнение переходит за цикл +while (4 <= 3) + +// console.log('finished!'); +// На этом этапе i равен 4, но он нам уже не нужен +// функция завершается +``` + +Самое главное в цикле — завершение его работы (выход из цикла). Процесс, который порождает цикл, должен в конце концов остановиться. Ответственность за остановку полностью лежит на программисте. Обычно задача сводится к введению переменной, называемой «счётчиком цикла». Сначала счётчик инициализируется, то есть ему задаётся начальное значение. В нашем примере это инструкция `let i = 1`, выполняемая до входа в цикл. Затем в условии цикла проверяется, достиг ли счётчик своего предельного значения. И, наконец, счётчик меняет свое значение `i = i + 1`. + +На этом моменте новички делают больше всего ошибок. Например, случайно забытое увеличение счётчика или неправильная проверка в предикате способны привести к зацикливанию. Это ситуация, при которой цикл работает бесконечно и программа никогда не останавливается. В таком случае приходится её завершать принудительно (кто знает, может быть когда зависают реальные программы, в этот момент внутри них выполняется бесконечный цикл). + +```javascript +const printNumbers = (lastNumber) => { + let i = 1; + + // Этот цикл никогда не остановится + // и будет печатать всегда одно значение + while (i <= lastNumber) { + console.log(i); + } + console.log('finished!'); +}; +``` + +В некоторых случаях бесконечные циклы полезны. Здесь мы такие случаи не рассматриваем, но полезно видеть как выглядит этот код: + +```javascript +while (true) { + // Что-то делаем +} +``` + +Подводя итог. Когда всё же нужны циклы, а когда можно обойтись без них? Физически невозможно обойтись без циклов тогда, когда алгоритм решения задачи требует повторения каких-то действий, как в примере с книгой, и количество этих операций заранее неизвестно. diff --git a/modules/50-loops/10-while/ru/data.yml b/modules/50-loops/10-while/ru/data.yml new file mode 100644 index 0000000..6465a68 --- /dev/null +++ b/modules/50-loops/10-while/ru/data.yml @@ -0,0 +1,8 @@ +name: Цикл While +tips: + - > + [Цикл + while](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/while) +definitions: + - name: Цикл While + description: инструкция для повторения кода, пока удовлетворяется какое-то условие. diff --git a/modules/50-loops/20-aggregation-numbers/ru/EXERCISE.md b/modules/50-loops/20-aggregation-numbers/ru/EXERCISE.md new file mode 100644 index 0000000..059b2de --- /dev/null +++ b/modules/50-loops/20-aggregation-numbers/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Реализуйте функцию `multiplyNumbersFromRange()`, которая перемножает числа в указанном диапазоне включая границы диапазона. Пример вызова: + +```javascript +multiplyNumbersFromRange(1, 5); // 1 * 2 * 3 * 4 * 5 = 120 +multiplyNumbersFromRange(2, 3); // 2 * 3 = 6 +multiplyNumbersFromRange(6, 6); // 6 +``` diff --git a/modules/50-loops/20-aggregation-numbers/ru/README.md b/modules/50-loops/20-aggregation-numbers/ru/README.md new file mode 100644 index 0000000..0b62e97 --- /dev/null +++ b/modules/50-loops/20-aggregation-numbers/ru/README.md @@ -0,0 +1,82 @@ + +Отдельный класс задач, который не может обойтись без циклов, называется агрегированием данных. К таким задачам относятся поиск максимального, минимального, суммы, среднего арифметического и т.п. Их главная особенность в том, что результат зависит от всего набора данных. Для расчета суммы нужно сложить **все** числа, для вычисления максимального нужно сравнить **все** числа. + +С такими задачами хорошо знакомы все, кто занимаются c числами, например бухгалтеры или маркетологи. Обычно их выполняют в таблицах наподобие Microsoft Excel или Google Tables. + +Разберем самый простой пример – поиск суммы набора чисел. Реализуем функцию, которая складывает числа в указанном диапазоне, включая границы. Диапазоном в данном случае называется ряд чисел от какого-то начала до определенного конца. Например, диапазон [1, 10] включает в себя все целые числа от 1 до 10. + +```javascript +sumNumbersFromRange(5, 7); // 5 + 6 + 7 = 18 +sumNumbersFromRange(1, 2); // 1 + 2 = 3 + +// [1, 1] диапазон с одинаковым началом и концом – тоже диапазон +// он в себя включает ровно одно число – саму границу диапазона +sumNumbersFromRange(1, 1); // 1 +sumNumbersFromRange(100, 100); // 100 +``` + +Для реализации этого кода нам понадобится цикл, так как сложение чисел – это итеративный процесс (он повторяется для каждого числа), а количество итераций зависит от размера диапазона. Перед тем, как смотреть код, попробуйте ответьте на вопросы ниже: + +* Каким значением инициализировать счетчик? +* Как он будет изменяться? +* Когда цикл должен остановиться? + +Попробуйте сначала подумать над этими вопросами, а затем посмотрите код ниже: + +```javascript +const sumNumbersFromRange = (start, finish) => { + // Технически можно менять start + // Но входные аргументы нужно оставлять в исходном значении + // Это сделает код проще для анализа + let i = start; + let sum = 0; // Инициализация суммы + + while (i <= finish) { // Двигаемся до конца диапазона + sum = sum + i; // Считаем сумму для каждого числа + i = i + 1; // Переходим к следующему числу в диапазоне + } + + // Возвращаем получившийся результат + return sum; +}; +``` + +https://replit.com/@hexlet/js-basics-aggregation-numbers + +Общая структура цикла здесь стандартна. Есть счетчик, который инициализируется начальным значением диапазона, есть сам цикл с условием остановки при достижении конца диапазона, и, наконец, изменение счетчика в конце тела цикла. Количество итераций в таком цикле равно `finish - start + 1`. То есть для диапазона от 5 до 7 – это 7 - 5 + 1, то есть 3 итерации. + +Главные отличия от обычной обработки связаны с логикой вычислений результата. В задачах на агрегацию всегда есть какая-то переменная, которая хранит внутри себя результат работы цикла. В коде выше это `sum`. На каждой итерации цикла происходит её изменение, прибавление следующего числа в диапазоне: `sum = sum + i`. Весь процесс выглядит так: + +```javascript +// Для вызова sumNumbersFromRange(2, 5); +let sum = 0; +sum = sum + 2; // 2 +sum = sum + 3; // 5 +sum = sum + 4; // 9 +sum = sum + 5; // 14 +// 14 – результат сложения чисел в диапазоне [2, 5] +``` + +У переменной `sum` есть начальное значение, равное 0. Зачем вообще задавать значение? Любая повторяющаяся операция начинается с какого-то значения. Нельзя просто так объявить переменную и начать с ней работать внутри цикла. Это приведет к неверному результату: + +```javascript +// начальное значение не задано +// js автоматически делает его равным undefined +let sum; + +// первая итерация цикла +sum = sum + 2; // ? +``` + +В результате такого вызова внутри `sum` окажется `NaN`, то есть не-число. Оно возникает из-за попытки сложить `2` и `undefined`. Значит какое-то значение всё же нужно. Почему в коде выше выбран 0? Очень легко проверить, что все остальные варианты приведут к неверному результату. Если начальное значение будет равно 1, то результат получится на 1 больше, чем нужно. + +В математике существует понятие **нейтральный элемент операции** (у каждой операции свой элемент). Это понятие имеет очень простой смысл. Операция с этим элементом не изменяет то значение, над которым проводится операция. В сложении любое число плюс ноль дает само число. При вычитании – тоже самое. Даже у конкатенации есть нейтральный элемент – это пустая строка: `'' + 'one'` будет 'one'. + +Вопрос на самопроверку. Какой нейтральный элемент у операции умножения? Для ответа на этот вопрос, найдите число, которое не меняет любые другие числа при умножения на него. + +
+Ответ + +Нейтральный элемент умножения — 1. + +
diff --git a/modules/50-loops/20-aggregation-numbers/ru/data.yml b/modules/50-loops/20-aggregation-numbers/ru/data.yml new file mode 100644 index 0000000..eafd735 --- /dev/null +++ b/modules/50-loops/20-aggregation-numbers/ru/data.yml @@ -0,0 +1,7 @@ +name: Агрегация данных (Числа) +tips: + - | + [Итерация](https://ru.wikipedia.org/wiki/Итерация_(программирование)) +definitions: + - name: Агрегация + description: Накопление результата во время итераций и работа с ним после цикла. diff --git a/modules/50-loops/23-aggregation-strings/ru/EXERCISE.md b/modules/50-loops/23-aggregation-strings/ru/EXERCISE.md new file mode 100644 index 0000000..ac461d2 --- /dev/null +++ b/modules/50-loops/23-aggregation-strings/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Реализуйте функцию `joinNumbersFromRange()`, которая объединяет все числа из диапазона в строку: + +```javascript +joinNumbersFromRange(1, 1); // 1 +joinNumbersFromRange(2, 3); // 23 +joinNumbersFromRange(5, 10); // 5678910 +``` diff --git a/modules/50-loops/23-aggregation-strings/ru/README.md b/modules/50-loops/23-aggregation-strings/ru/README.md new file mode 100644 index 0000000..eae01db --- /dev/null +++ b/modules/50-loops/23-aggregation-strings/ru/README.md @@ -0,0 +1,38 @@ + +Агрегация применяется не только к числам, но и к строкам. Это такие задачи, в которых строка формируется динамически, то есть заранее неизвестно, какого она размера и что будет содержать. + +Представьте себе функцию, которая умеет «умножать» строку, то есть она повторяет её указанное количество раз: + +```javascript +repeat('hexlet', 3); // hexlethexlethexlet +``` + +Принцип работы этой функции довольно простой: в цикле происходит «наращивание» строки указанное количество раз: + +```javascript +const repeat = (text, times) => { + // Нейтральный элемент для строк – пустая строка + let result = ''; + let i = 1; + + while (i <= times) { + // Каждый раз добавляем строку к результату + result = `${result}${text}`; + i = i + 1; + } + + return result; +}; +``` + +https://replit.com/@hexlet/js-basics-aggreagation + +Распишем выполнение этого кода по шагам: + +```javascript +// Для вызова repeat('hexlet', 3); +let result = ''; +result = `${result}hexlet`; // hexlet +result = `${result}hexlet`; // hexlethexlet +result = `${result}hexlet`; // hexlethexlethexlet +``` diff --git a/modules/50-loops/23-aggregation-strings/ru/data.yml b/modules/50-loops/23-aggregation-strings/ru/data.yml new file mode 100644 index 0000000..aca9f42 --- /dev/null +++ b/modules/50-loops/23-aggregation-strings/ru/data.yml @@ -0,0 +1,7 @@ +name: Агрегация данных (Строки) +tips: + - | + [Итерация](https://ru.wikipedia.org/wiki/Итерация_(программирование)) +definitions: + - name: Агрегация + description: Накопление результата во время итераций и работа с ним после цикла. diff --git a/modules/50-loops/25-iteration-over-string/ru/EXERCISE.md b/modules/50-loops/25-iteration-over-string/ru/EXERCISE.md new file mode 100644 index 0000000..5582514 --- /dev/null +++ b/modules/50-loops/25-iteration-over-string/ru/EXERCISE.md @@ -0,0 +1,14 @@ + +Реализуйте функцию `printReversedWordBySymbol()`, которая печатает переданное слово посимвольно, как в примере из теории, но делает это в обратном порядке. + +```javascript +const word = 'Hexlet'; + +printReversedWordBySymbol(word); +// => t +// => e +// => l +// => x +// => e +// => H +``` diff --git a/modules/50-loops/25-iteration-over-string/ru/README.md b/modules/50-loops/25-iteration-over-string/ru/README.md new file mode 100644 index 0000000..08e11ca --- /dev/null +++ b/modules/50-loops/25-iteration-over-string/ru/README.md @@ -0,0 +1,26 @@ + +Циклы подходят не только для обработки чисел, но и при работе со строками. В первую очередь благодаря возможности получить конкретный символ по его индексу. Ниже пример кода, который распечатывает каждую букву слова на отдельной строке: + +```javascript +const printNameBySymbol = (name) => { + let i = 0; + // Такая проверка будет выполняться до конца строки + // включая последний символ. Его индекс `length - 1`. + while (i < name.length) { + // Обращаемся к символу по индексу + console.log(name[i]); + i = i + 1; + } +}; + +const name = 'Arya'; +printNameBySymbol(name); +// => A +// => r +// => y +// => a +``` + +https://replit.com/@hexlet/js-basic-iteration-over-string + +Самое главное в этом коде, поставить правильное условие в `while`. Это можно сделать сразу двумя способами: `i < name.length` или `i <= name.length - 1`. Оба способа приводят к одному результату. diff --git a/modules/50-loops/25-iteration-over-string/ru/data.yml b/modules/50-loops/25-iteration-over-string/ru/data.yml new file mode 100644 index 0000000..70738d5 --- /dev/null +++ b/modules/50-loops/25-iteration-over-string/ru/data.yml @@ -0,0 +1,4 @@ +name: Обход строк +tips: + - | + [Итерация](https://ru.wikipedia.org/wiki/Итерация_(программирование)) diff --git a/modules/50-loops/26-conditions-inside-loops/ru/EXERCISE.md b/modules/50-loops/26-conditions-inside-loops/ru/EXERCISE.md new file mode 100644 index 0000000..ba72747 --- /dev/null +++ b/modules/50-loops/26-conditions-inside-loops/ru/EXERCISE.md @@ -0,0 +1,7 @@ + +Функция из теории учитывает регистр букв. То есть `A` и `a` с её точки зрения разные символы. Реализуйте вариант этой же функции, так чтобы регистр букв был не важен: + +```javascript +countChars('HexlEt', 'e'); // 2 +countChars('HexlEt', 'E'); // 2 +``` diff --git a/modules/50-loops/26-conditions-inside-loops/ru/README.md b/modules/50-loops/26-conditions-inside-loops/ru/README.md new file mode 100644 index 0000000..b7d3d3a --- /dev/null +++ b/modules/50-loops/26-conditions-inside-loops/ru/README.md @@ -0,0 +1,40 @@ + +Тело цикла, как и тело функции — это место выполнения инструкций. Значит, мы можем использовать внутри него всё изученное ранее, например — условные конструкции. + +Представьте себе функцию, которая считает, сколько раз входит буква в предложение. Пример её работы: + +```javascript +countChars('Fear cuts deeper than swords.', 'e'); // 4 +// Если вы ничего не нашли, то результат — 0 совпадений +countChars('Sansa', 'y'); // 0 +``` + +Перед тем как посмотреть её содержимое, попробуйте ответить на вопросы: + +* Является ли эта операция агрегацией? +* Какой будет проверка на вхождение символа? + +```javascript +const countChars = (str, char) => { + let i = 0; + let count = 0; + while (i < str.length) { + if (str[i] === char) { + // Считаем только подходящие символы + count = count + 1; + } + // Счетчик увеличивается в любом случае + i = i + 1; + } + + return count; +}; +``` + +https://replit.com/@hexlet/js-basics-condition-inside-loops + +Эта задача является агрегирующей. Несмотря на то, что она считает не все символы, для подсчета самой суммы все равно приходится анализировать каждый символ. + +Ключевое отличие этого цикла от рассмотренных в наличии условия внутри тела. Переменная `count` увеличивается только в том случае, когда текущий рассматриваемый символ совпадает с ожидаемым. + +В остальном — это типичная агрегатная функция, которая возвращает количество нужных символов вызываемому коду. diff --git a/modules/50-loops/26-conditions-inside-loops/ru/data.yml b/modules/50-loops/26-conditions-inside-loops/ru/data.yml new file mode 100644 index 0000000..9b3314f --- /dev/null +++ b/modules/50-loops/26-conditions-inside-loops/ru/data.yml @@ -0,0 +1,4 @@ +name: Условия внутри тела цикла +tips: + - > + [if...else](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) diff --git a/modules/50-loops/28-build-strings/ru/EXERCISE.md b/modules/50-loops/28-build-strings/ru/EXERCISE.md new file mode 100644 index 0000000..999554e --- /dev/null +++ b/modules/50-loops/28-build-strings/ru/EXERCISE.md @@ -0,0 +1,2 @@ + +Реализуйте функцию `even()`, которая возвращает новую строку, состоящую из чётных символов исходной строки. diff --git a/modules/50-loops/28-build-strings/ru/README.md b/modules/50-loops/28-build-strings/ru/README.md new file mode 100644 index 0000000..fcaa9f4 --- /dev/null +++ b/modules/50-loops/28-build-strings/ru/README.md @@ -0,0 +1,36 @@ + +Ещё одно использование циклов – формирование строк. Подобная задача нередко встречается в веб-программировании. Она сводится к обычной агрегации с применением интерполяции или конкатенации. + +Есть одна задача, крайне популярная среди людей, проводящих собеседования, это переворот строки. Её можно решить множеством разных способов, но именно посимвольный перебор считается самым базовым. Пример работы этой функции: + +```javascript +reverse('Hexlet'); // telxeH +``` + +Общая идея переворота состоит в следующем: нужно брать символы по очереди с начала строки и соединять их в обратном порядке. Звучит довольно просто. Давайте проверим: + +```javascript +const reverse = (str) => { + let i = 0; + // Нейтральный элемент для строк это пустая строка + let result = ''; + while (i < str.length) { + // Соединяем в обратном порядке + result = `${str[i]}${result}`; + // То же самое через конкатенацию + // result = str[i] + result; + i = i + 1; + } + + return result; +}; + +const name = 'Bran'; +reverse(name); // 'narB' +// Проверка нейтрального элемента +reverse(''); // '' +``` + +https://replit.com/@hexlet/js-basics-iteration-over-strings + +Единственный возможно сложный момент в этом коде – прочувствовать, как собирается сама строка. Так как каждый следующий символ прикрепляется к результирующей строке слева, то, в конечном итоге, строка оказывается перевернута. diff --git a/modules/50-loops/28-build-strings/ru/data.yml b/modules/50-loops/28-build-strings/ru/data.yml new file mode 100644 index 0000000..be85550 --- /dev/null +++ b/modules/50-loops/28-build-strings/ru/data.yml @@ -0,0 +1,4 @@ +name: Формирование строк в циклах +tips: + - | + [Итерация](https://ru.wikipedia.org/wiki/Итерация_(программирование)) diff --git a/modules/50-loops/30-syntax-sugar/ru/EXERCISE.md b/modules/50-loops/30-syntax-sugar/ru/EXERCISE.md new file mode 100644 index 0000000..de407d9 --- /dev/null +++ b/modules/50-loops/30-syntax-sugar/ru/EXERCISE.md @@ -0,0 +1,8 @@ + +Реализуйте функцию `filterString()`, принимающую на вход строку и символ, и возвращающую новую строку, в которой удален переданный символ во всех его позициях. Регистр символов важен. + +```javascript +const str = 'If I look back I am lost'; +filterString(str, 'I'); // 'f look back am lost' +filterString('zz Zorro', 'z'); // ' Zorro' +``` diff --git a/modules/50-loops/30-syntax-sugar/ru/README.md b/modules/50-loops/30-syntax-sugar/ru/README.md new file mode 100644 index 0000000..4017e6e --- /dev/null +++ b/modules/50-loops/30-syntax-sugar/ru/README.md @@ -0,0 +1,10 @@ + +Подобные конструкции `index = index + 1` в JavaScript используются довольно часто, поэтому создатели языка добавили сокращённый вариант записи: `index += 1`. Такие сокращения принято называть **синтаксическим сахаром**, потому что они делают процесс написания кода немного проще и приятнее, «подслащивая» его :) + +Существуют сокращённые формы для всех арифметических операций и для конкатенации строк: + +- `a = a + 1` → `a += 1` +- `a = a - 1` → `a -= 1` +- `a = a * 2` → `a *= 2` +- `a = a / 1` → `a /= 1` +- `a = a + 'foo'` → `a += 'foo'` diff --git a/modules/50-loops/30-syntax-sugar/ru/data.yml b/modules/50-loops/30-syntax-sugar/ru/data.yml new file mode 100644 index 0000000..17df613 --- /dev/null +++ b/modules/50-loops/30-syntax-sugar/ru/data.yml @@ -0,0 +1,9 @@ +name: Синтаксический сахар +tips: + - | + [Синтаксический сахар](https://ru.wikipedia.org/wiki/Синтаксический_сахар) +definitions: + - name: Синтаксический сахар + description: > + это синтаксические возможности, применение которых не влияет на поведение + программы, но делает использование языка более удобным для человека. diff --git a/modules/50-loops/50-mutators/ru/EXERCISE.md b/modules/50-loops/50-mutators/ru/EXERCISE.md new file mode 100644 index 0000000..6d9e70c --- /dev/null +++ b/modules/50-loops/50-mutators/ru/EXERCISE.md @@ -0,0 +1,10 @@ + +Напишите функцию `makeItFunny()`, которая принимает на вход строку и возвращает её копию, у которой каждый n-ный элемент переведен в верхний регистр. n – задается на входе в функцию. + +Для определения каждого n-ного элемента понадобится остаток от деления `%`. Подумайте, как его можно использовать. + +```javascript +const text = 'I never look back'; +// Каждый третий элемент +makeItFunny(text, 3); // 'I NevEr LooK bAck' +``` diff --git a/modules/50-loops/50-mutators/ru/README.md b/modules/50-loops/50-mutators/ru/README.md new file mode 100644 index 0000000..52400f6 --- /dev/null +++ b/modules/50-loops/50-mutators/ru/README.md @@ -0,0 +1,62 @@ + +Из языка Си в JavaScript перекочевали две операции: **инкремент** `++` и **декремент** `--`, которые очень часто встречаются вместе с циклами. Эти унарные операции увеличивают и уменьшают на единицу число, записанное в переменную: + +```javascript +let i = 0; +i++; // 0 +i++; // 1 + +i--; // 2 +i--; // 1 +``` + +Кроме постфиксной формы, у них есть и префиксная: + +```javascript +let i = 0; +++i; // 1 +++i; // 2 + +--i; // 1 +--i; // 0 +``` + +Кажется, что нет никакой разницы между постфиксной и префиксной формами. Но тут начинаются сложности. + +В отличие от всех остальных операций, которые не имеют побочных эффектов и просто возвращают новое значение, инкремент и декремент не только возвращают значение, но и **изменяют** значение переменной. + +При использовании префиксной нотации сначала происходит изменение переменной, а потом возврат. + +При использовании постфиксной нотации — наоборот: можно считать, что сначала происходит возврат, а потом изменение переменной. + +Правило работает одинаково для инкремента и декремента. Для простоты рассмотрим только инкремент: + +```javascript +let x = 5; + +console.log(++x); // => 6 +console.log(x); // => 6 + +console.log(x++); // => 6 +console.log(x); // => 7 +``` + +https://replit.com/@hexlet/js-basic-mutators + +Что происходит? + +1. Вывели на экран `++x`. Это префиксный инкремент, поэтому сначала значение переменной увеличилось на 1, потом результат вернулся и вывелся на экран. +2. Так как значение изменилось, `console.log(x)` вывел 6. +3. Теперь выводим на экран `x++`. Это постфиксный инкремент, поэтому возвращено значение, содержавшееся в переменной до её увеличения на 1. +4. Так как значение изменилось, `console.log(x)` вывел 7. + +--- + +Особенно страшным это становится тогда, когда инкремент вставляют внутрь других операций: `x = i++ - 7 + --h`. Понять такой код почти невозможно, и его написание должно рассматриваться как тяжкое преступление. + +Например, в языке JavaScript линтер (программа, проверяющая код) сразу начинает ругаться, когда встречает использование инкремента или декремента. + +Рекомендации по использованию: + +* Никогда не мешайте в рамках одного выражения операции/функции без побочных эффектов с операциями/функциями, обладающими побочными эффектами. +* Используйте инкремент и декремент только там, где нет разницы между префиксным и постфиксным вариантом: отдельно от всего, на своей собственной строчке кода. diff --git a/modules/50-loops/50-mutators/ru/data.yml b/modules/50-loops/50-mutators/ru/data.yml new file mode 100644 index 0000000..077308f --- /dev/null +++ b/modules/50-loops/50-mutators/ru/data.yml @@ -0,0 +1,10 @@ +name: Инкремент и декремент +tips: + - > + [Оператор остатка от деления + (%)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder) +definitions: + - name: Побочный эффект + description: >- + действие, которое изменяет внешнее окружение (среду выполнения). Например, + вывод на экран или отправка письма. diff --git a/modules/50-loops/55-return-from-loops/ru/EXERCISE.md b/modules/50-loops/55-return-from-loops/ru/EXERCISE.md new file mode 100644 index 0000000..29055f7 --- /dev/null +++ b/modules/50-loops/55-return-from-loops/ru/EXERCISE.md @@ -0,0 +1,12 @@ + +Реализуйте функцию `hasChar()`, которая проверяет (с учётом регистра), содержит ли строка указанную букву. Функция принимает два параметра: + +* Строка +* Буква для поиска + +```javascript +hasChar('Hexlet', 'H'); // true +hasChar('Hexlet', 'h'); // false +hasChar('Awesomeness', 'm'); // true +hasChar('Awesomeness', 'd'); // false +``` diff --git a/modules/50-loops/55-return-from-loops/ru/README.md b/modules/50-loops/55-return-from-loops/ru/README.md new file mode 100644 index 0000000..18a3c52 --- /dev/null +++ b/modules/50-loops/55-return-from-loops/ru/README.md @@ -0,0 +1,40 @@ + +Работа с циклами обычно сводится к двум сценариям: + +1. Агрегация. Накопление результата во время итераций и работа с ним после цикла. Переворот строки как раз относится к такому варианту. +2. Выполнение цикла до достижения необходимого результата и выход. Например, задача поиска простых чисел. Напомним, что простое число — это число, которое делится без остатка только на себя и на единицу. + +Рассмотрим простой алгоритм проверки простоты числа. Будем делить искомое число `x` на все числа из диапазона от двух до `x - 1` и смотреть остаток от деления. Если в этом диапазоне не найден делитель, который делит число `x` без остатка, значит перед нами простое число. + +Если задуматься, то можно заметить, что достаточно проверять числа не до `x - 1`, а до половины числа. Например, 11 не делится на 2, 3, 4, 5. Но и дальше гарантированно не будет делиться на числа больше своей половины. Значит, можно провести небольшую оптимизацию и проверять деление только до `x / 2`. + +```javascript +const isPrime = (number) => { + if (number < 2) { + return false; + } + + let divider = 2; + + while (divider <= number / 2) { + if (number % divider === 0) { + return false; + } + + divider += 1; + } + + return true; +} + +isPrime(1); // false +isPrime(2); // true +isPrime(3); // true +isPrime(4); // false +``` + +https://replit.com/@hexlet/js-basics-conditions-inside-loops + +Алгоритм построен таким образом, что если во время последовательного деления на числа до `x / 2` находится хоть одно, которое делит без остатка, то переданный аргумент — не простое число, а значит дальнейшие вычисления не имеют смысла. В этом месте стоит возврат `false`. + +И только если цикл отработал целиком, можно сделать вывод, что число — простое, так как не было найдено ни одного числа, которое делит число без остатка. diff --git a/modules/50-loops/55-return-from-loops/ru/data.yml b/modules/50-loops/55-return-from-loops/ru/data.yml new file mode 100644 index 0000000..be81f4d --- /dev/null +++ b/modules/50-loops/55-return-from-loops/ru/data.yml @@ -0,0 +1,6 @@ +name: Возврат из циклов +tips: + - '[Список простых чисел](https://ru.wikipedia.org/wiki/Список_простых_чисел)' +definitions: + - name: Агрегация + description: Накопление результата во время итераций и работа с ним после цикла. diff --git a/modules/50-loops/70-for/ru/EXERCISE.md b/modules/50-loops/70-for/ru/EXERCISE.md new file mode 100644 index 0000000..534a3d5 --- /dev/null +++ b/modules/50-loops/70-for/ru/EXERCISE.md @@ -0,0 +1,14 @@ + +Сэмвелл обнаружил, что его сообщения перехватываются и читаются в замке «Близнецы», поэтому его атаки перестали быть внезапными. Немного подумав, он разработал программу, которая будет шифровать передаваемые сообщения по следующему алгоритму. Программа получает на вход строку и меняет местами в ней каждые 2 подряд идущих символа. Если длина строки нечётная, то последний символ остаётся на своём месте. + +```javascript +encrypt('move'); // omev +encrypt('attack'); // taatkc +// Если длина строки нечётное +// то последний символ остается на своем месте +encrypt('go!'); // og! +``` + +Реализуйте функцию `encrypt()`, которая принимает на вход исходное сообщение и возвращает зашифрованное. + +Подумайте. Может ли эта функция расшифровать зашифрованное сообщение? diff --git a/modules/50-loops/70-for/ru/README.md b/modules/50-loops/70-for/ru/README.md new file mode 100644 index 0000000..a45715a --- /dev/null +++ b/modules/50-loops/70-for/ru/README.md @@ -0,0 +1,38 @@ + +Цикл `while` идеален для ситуаций, когда количество итераций неизвестно заранее, например, при поиске простого числа. Когда количество итераций известно, предпочтительнее использовать цикл `for`. + +Посмотрим реализацию переворота строки через цикл `for`: + +```javascript +const reverseString = (str) => { + let result = ''; + for (let i = 0; i < str.length; i += 1) { + result = `${str[i]}${result}`; + } + + return result; +}; +``` + +https://replit.com/@hexlet/js-basics-for + +Можно читать так: *цикл с индексом `i` повторяется пока `i < str.length` и после каждого шага увеличивает `i` на 1*. + +В определении цикла `for` в круглых скобках есть три выражения, разделённые точкой с запятой: + +1. Начальное значение счётчика. Этот код выполняется ровно один раз перед первой итерацией. +2. Предикат — условие повторения циклов. Выполняется на каждой итерации. Точно так же как и в `while` +3. Описание изменения счётчика. Этот код выполняется в конце каждой итерации. + +В остальном принцип работы точно такой же, как у цикла `while`. + +В определении `for` не обязательно указывать все три выражения. Если не указать условие повторения цикла, то цикл будет выполняться бесконечно: + +```javascript +let i = 1; +// Можно даже не указывать все три выражения +for (;;) { + console.log(i); + i += 1; +} +``` diff --git a/modules/50-loops/70-for/ru/data.yml b/modules/50-loops/70-for/ru/data.yml new file mode 100644 index 0000000..6d9edef --- /dev/null +++ b/modules/50-loops/70-for/ru/data.yml @@ -0,0 +1,13 @@ +name: Цикл For +tips: + - > + [for](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) + + [шаблонные + строки](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Template_literals) + + [Логическое ИЛИ + (||)](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Logical_OR) +definitions: + - name: Агрегация + description: Накопление результата во время итераций и работа с ним после цикла.