master c02fa1d6e2ca cached
1171 files
3.9 MB
1.1M tokens
176 symbols
1 requests
Download .txt
Showing preview only (4,779K chars total). Download the full file or copy to clipboard to get everything.
Repository: javascript-tutorial/fr.javascript.info
Branch: master
Commit: c02fa1d6e2ca
Files: 1171
Total size: 3.9 MB

Directory structure:
gitextract_jgp5_eg_/

├── .gitattributes
├── .gitignore
├── 1-js/
│   ├── 01-getting-started/
│   │   ├── 1-intro/
│   │   │   └── article.md
│   │   ├── 2-manuals-specifications/
│   │   │   └── article.md
│   │   ├── 3-code-editors/
│   │   │   └── article.md
│   │   ├── 4-devtools/
│   │   │   ├── article.md
│   │   │   └── bug.html
│   │   └── index.md
│   ├── 02-first-steps/
│   │   ├── 01-hello-world/
│   │   │   ├── 1-hello-alert/
│   │   │   │   ├── index.html
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-hello-alert-ext/
│   │   │   │   ├── alert.js
│   │   │   │   ├── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-structure/
│   │   │   └── article.md
│   │   ├── 03-strict-mode/
│   │   │   └── article.md
│   │   ├── 04-variables/
│   │   │   ├── 1-hello-variables/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-declare-variables/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-uppercast-constant/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-types/
│   │   │   ├── 1-string-quotes/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-alert-prompt-confirm/
│   │   │   ├── 1-simple-page/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-type-conversions/
│   │   │   └── article.md
│   │   ├── 08-operators/
│   │   │   ├── 1-increment-order/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-assignment-result/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-primitive-conversions-questions/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-fix-prompt/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-comparison/
│   │   │   ├── 1-comparison-questions/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 10-ifelse/
│   │   │   ├── 1-if-zero-string/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-check-standard/
│   │   │   │   ├── ifelse_task2/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-sign/
│   │   │   │   ├── if_sign/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-rewrite-if-question/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-rewrite-if-else-question/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 11-logical-operators/
│   │   │   ├── 1-alert-null-2-undefined/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-alert-or/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-alert-1-null-2/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-alert-and/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-alert-and-or/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-check-if-in-range/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-check-if-out-range/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-if-question/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-check-login/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 12-nullish-coalescing-operator/
│   │   │   └── article.md
│   │   ├── 13-while-for/
│   │   │   ├── 1-loop-last-value/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-which-value-while/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-which-value-for/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-for-even/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-replace-for-while/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-repeat-until-correct/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-list-primes/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 14-switch/
│   │   │   ├── 1-rewrite-switch-if-else/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-rewrite-if-switch/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 15-function-basics/
│   │   │   ├── 1-if-else-required/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-rewrite-function-question-or/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-min/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-pow/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 16-function-expressions/
│   │   │   └── article.md
│   │   ├── 17-arrow-functions-basics/
│   │   │   ├── 1-rewrite-arrow/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 18-javascript-specials/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 03-code-quality/
│   │   ├── 01-debugging-chrome/
│   │   │   ├── article.md
│   │   │   ├── debugging.view/
│   │   │   │   ├── hello.js
│   │   │   │   └── index.html
│   │   │   └── head.html
│   │   ├── 02-coding-style/
│   │   │   ├── 1-style-errors/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-comments/
│   │   │   └── article.md
│   │   ├── 04-ninja-code/
│   │   │   └── article.md
│   │   ├── 05-testing-mocha/
│   │   │   ├── 3-pow-test-wrong/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── beforeafter.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── index.html
│   │   │   ├── pow-1.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-2.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-3.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-4.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-full.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-min.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   └── pow-nan.view/
│   │   │       ├── index.html
│   │   │       └── test.js
│   │   ├── 06-polyfills/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 04-object-basics/
│   │   ├── 01-object/
│   │   │   ├── 2-hello-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-is-empty/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-const-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-sum-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-multiply-numeric/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-object-copy/
│   │   │   └── article.md
│   │   ├── 03-garbage-collection/
│   │   │   └── article.md
│   │   ├── 04-object-methods/
│   │   │   ├── 4-object-property-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-calculator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-chain-calls/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-constructor-new/
│   │   │   ├── 1-two-functions-one-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-calculator-constructor/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-accumulator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-optional-chaining/
│   │   │   └── article.md
│   │   ├── 08-symbol/
│   │   │   └── article.md
│   │   ├── 09-object-toprimitive/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 05-data-types/
│   │   ├── 01-primitives-methods/
│   │   │   ├── 1-string-new-property/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-number/
│   │   │   ├── 1-sum-interface/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-why-rounded-down/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-repeat-until-number/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-endless-loop-error/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-random-min-max/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-random-int-min-max/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-string/
│   │   │   ├── 1-ucfirst/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-check-spam/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-truncate/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-extract-currency/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-array/
│   │   │   ├── 1-item-value/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-maximal-subarray/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-create-array/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-call-array-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-array-input-sum/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-array-methods/
│   │   │   ├── 1-camelcase/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-average-age/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 11-array-unique/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 12-reduce-object/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-filter-range/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-filter-range-in-place/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-sort-back/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-copy-sort-array/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-array-get-names/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-calculator-extendable/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-map-objects/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-sort-objects/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-shuffle/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-iterable/
│   │   │   └── article.md
│   │   ├── 07-map-set/
│   │   │   ├── 01-array-unique-map/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-filter-anagrams/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-iterable-keys/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 08-weakmap-weakset/
│   │   │   ├── 01-recipients-read/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-recipients-when-read/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-keys-values-entries/
│   │   │   ├── 01-sum-salaries/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-count-properties/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 10-destructuring-assignment/
│   │   │   ├── 1-destruct-user/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-max-salary/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 11-date/
│   │   │   ├── 1-new-date/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-get-week-day/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-weekday/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-get-date-ago/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-last-day-of-month/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-get-seconds-today/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-get-seconds-to-tomorrow/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-format-date-relative/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 12-json/
│   │   │   ├── 1-serialize-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-serialize-event-circular/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 06-advanced-functions/
│   │   ├── 01-recursion/
│   │   │   ├── 01-sum-to/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-factorial/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-fibonacci-numbers/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 04-output-single-linked-list/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 05-output-single-linked-list-reverse/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 02-rest-parameters-spread/
│   │   │   └── article.md
│   │   ├── 03-closure/
│   │   │   ├── 1-closure-latest-changes/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-make-army/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-closure-variable-access/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-counter-independent/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-counter-object-independent/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-function-in-if/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-closure-sum/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-let-scope/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-filter-through-function/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-sort-by-field/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-var/
│   │   │   └── article.md
│   │   ├── 05-global-object/
│   │   │   └── article.md
│   │   ├── 06-function-object/
│   │   │   ├── 2-counter-inc-dec/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-sum-many-brackets/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-new-function/
│   │   │   └── article.md
│   │   ├── 08-settimeout-setinterval/
│   │   │   ├── 1-output-numbers-100ms/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-rewrite-settimeout/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-settimeout-result/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-call-apply-decorators/
│   │   │   ├── 01-spy-decorator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-delay/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-debounce/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── debounce.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 04-throttle/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 10-bind/
│   │   │   ├── 2-write-to-object-after-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-second-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-function-property-after-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-question-use-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-ask-partial/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 12-arrow-functions/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 07-object-properties/
│   │   ├── 01-property-descriptors/
│   │   │   └── article.md
│   │   ├── 02-property-accessors/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 08-prototypes/
│   │   ├── 01-prototype-inheritance/
│   │   │   ├── 1-property-after-delete/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-search-algorithm/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-proto-and-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-hamster-proto/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-function-prototype/
│   │   │   ├── 1-changing-prototype/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-new-object-same-constructor/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-native-prototypes/
│   │   │   ├── 1-defer-to-prototype/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-defer-to-prototype-extended/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-prototype-methods/
│   │   │   ├── 2-dictionary-tostring/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-compare-calls/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 09-classes/
│   │   ├── 01-class/
│   │   │   ├── 1-rewrite-to-class/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── source.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-class-inheritance/
│   │   │   ├── 1-class-constructor-error/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-clock-class-extended/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── clock.js
│   │   │   │   │   ├── extended-clock.js
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── clock.js
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-static-properties-methods/
│   │   │   ├── 3-class-extend-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-private-protected-properties-methods/
│   │   │   └── article.md
│   │   ├── 05-extend-natives/
│   │   │   └── article.md
│   │   ├── 06-instanceof/
│   │   │   ├── 1-strange-instanceof/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-mixins/
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 10-error-handling/
│   │   ├── 1-try-catch/
│   │   │   ├── 1-finally-or-code-after/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 2-custom-errors/
│   │   │   ├── 1-format-error/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 11-async/
│   │   ├── 01-callbacks/
│   │   │   ├── article.md
│   │   │   └── one.js
│   │   ├── 02-promise-basics/
│   │   │   ├── 01-re-resolve/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-delay-promise/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-animate-circle-promise/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 03-promise-chaining/
│   │   │   ├── 01-then-vs-catch/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── getMessage.js
│   │   │   ├── head.html
│   │   │   ├── one.js
│   │   │   ├── three.js
│   │   │   ├── two.js
│   │   │   └── user.json
│   │   ├── 04-promise-error-handling/
│   │   │   ├── 01-error-async/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── getMessage.js
│   │   │   ├── head.html
│   │   │   ├── one.js
│   │   │   ├── three.js
│   │   │   ├── two.js
│   │   │   └── user.json
│   │   ├── 05-promise-api/
│   │   │   ├── article.md
│   │   │   ├── head.html
│   │   │   ├── iliakan.json
│   │   │   ├── one.js
│   │   │   └── two.js
│   │   ├── 06-promisify/
│   │   │   └── article.md
│   │   ├── 07-microtask-queue/
│   │   │   └── article.md
│   │   ├── 08-async-await/
│   │   │   ├── 01-rewrite-async/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-rewrite-async-2/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-async-from-regular/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 12-generators-iterators/
│   │   ├── 1-generators/
│   │   │   ├── 01-pseudo-random-generator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 2-async-iterators-generators/
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 13-modules/
│   │   ├── 01-modules-intro/
│   │   │   ├── article.md
│   │   │   ├── say.view/
│   │   │   │   ├── index.html
│   │   │   │   └── say.js
│   │   │   ├── scopes-working.view/
│   │   │   │   ├── hello.js
│   │   │   │   ├── index.html
│   │   │   │   └── user.js
│   │   │   └── scopes.view/
│   │   │       ├── hello.js
│   │   │       ├── index.html
│   │   │       └── user.js
│   │   ├── 02-import-export/
│   │   │   └── article.md
│   │   ├── 03-modules-dynamic-imports/
│   │   │   ├── article.md
│   │   │   └── say.view/
│   │   │       ├── index.html
│   │   │       └── say.js
│   │   └── index.md
│   ├── 99-js-misc/
│   │   ├── 01-proxy/
│   │   │   ├── 01-error-nonexisting/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-array-negative/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-observable/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-eval/
│   │   │   ├── 1-eval-calculator/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-currying-partials/
│   │   │   └── article.md
│   │   ├── 04-reference-type/
│   │   │   ├── 2-check-syntax/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-why-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-bigint/
│   │   │   └── article.md
│   │   ├── 06-unicode/
│   │   │   └── article.md
│   │   └── index.md
│   └── index.md
├── 2-ui/
│   ├── 1-document/
│   │   ├── 01-browser-environment/
│   │   │   └── article.md
│   │   ├── 02-dom-nodes/
│   │   │   ├── article.md
│   │   │   ├── elk.html
│   │   │   └── head.html
│   │   ├── 03-dom-navigation/
│   │   │   ├── 1-dom-children/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-navigation-links-which-null/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-select-diagonal-cells/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 04-searching-elements-dom/
│   │   │   ├── 1-find-elements/
│   │   │   │   ├── solution.md
│   │   │   │   ├── table.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-basic-dom-node-properties/
│   │   │   ├── 2-lastchild-nodetype-inline/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-tree-info/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-tag-in-comment/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-where-document-in-hierarchy/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-dom-attributes-and-properties/
│   │   │   ├── 1-get-user-attribute/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-yellow-links/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-modifying-document/
│   │   │   ├── 1-createtextnode-vs-innerhtml/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-clock-setinterval/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 11-append-to-list/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 12-sort-table/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 4-clear-elem/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-why-aaa/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-create-list/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 7-create-object-tree/
│   │   │   │   ├── build-tree-dom.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── innerhtml.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 8-tree-count/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 9-calendar-table/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 08-styles-and-classes/
│   │   │   ├── 2-create-notification/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-size-and-scroll/
│   │   │   ├── 1-get-scroll-height-bottom/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-scrollbar-width/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-put-ball-in-center/
│   │   │   │   ├── ball-half/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 6-width-vs-clientwidth/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── cssWidthScroll.view/
│   │   │   │   └── index.html
│   │   │   └── metric.view/
│   │   │       └── index.html
│   │   ├── 10-size-and-scroll-window/
│   │   │   └── article.md
│   │   ├── 11-coordinates/
│   │   │   ├── 1-find-point-coordinates/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-position-at/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-position-at-absolute/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 4-position-inside-absolute/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 2-events/
│   │   ├── 01-introduction-browser-events/
│   │   │   ├── 01-hide-other/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 02-hide-self-onclick/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-which-handlers-run/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 04-move-ball-field/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 05-sliding-menu/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 06-hide-message/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   └── task.md
│   │   │   ├── 07-carousel/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 02-bubbling-and-capturing/
│   │   │   ├── article.md
│   │   │   ├── both.view/
│   │   │   │   ├── example.css
│   │   │   │   ├── index.html
│   │   │   │   └── script.js
│   │   │   ├── bubble-target.view/
│   │   │   │   ├── example.css
│   │   │   │   ├── index.html
│   │   │   │   └── script.js
│   │   │   └── capture.view/
│   │   │       ├── example.css
│   │   │       ├── index.html
│   │   │       └── script.js
│   │   ├── 03-event-delegation/
│   │   │   ├── 1-hide-message-delegate/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   └── task.md
│   │   │   ├── 2-sliding-tree/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-sortable-table/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 4-behavior-tooltip/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── bagua.view/
│   │   │       ├── bagua.css
│   │   │       └── index.html
│   │   ├── 04-default-browser-action/
│   │   │   ├── 1-why-return-false-fails/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-catch-link-navigation/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-image-gallery/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── gallery.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── gallery.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── menu.view/
│   │   │       ├── index.html
│   │   │       ├── menu.css
│   │   │       └── menu.js
│   │   ├── 05-dispatch-events/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 3-event-details/
│   │   ├── 1-mouse-events-basics/
│   │   │   ├── 01-selectable-list/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 3-mousemove-mouseover-mouseout-mouseenter-mouseleave/
│   │   │   ├── 1-behavior-nested-tooltip/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-hoverintent/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── hoverIntent.js
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── style.css
│   │   │   │   │   └── test.js
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── hoverIntent.js
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── style.css
│   │   │   │   │   └── test.js
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── mouseenter-mouseleave-delegation-2.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseenter-mouseleave-delegation.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseleave-table.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseleave.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseoverout-child.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseoverout-fast.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   └── mouseoverout.view/
│   │   │       ├── index.html
│   │   │       ├── script.js
│   │   │       └── style.css
│   │   ├── 4-mouse-drag-and-drop/
│   │   │   ├── 1-slider/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   └── task.md
│   │   │   ├── 2-drag-heroes/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── soccer.css
│   │   │   │   │   └── soccer.js
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── soccer.css
│   │   │   │   │   └── soccer.js
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── ball.view/
│   │   │   │   └── index.html
│   │   │   ├── ball2.view/
│   │   │   │   └── index.html
│   │   │   ├── ball3.view/
│   │   │   │   └── index.html
│   │   │   └── ball4.view/
│   │   │       ├── index.html
│   │   │       └── style.css
│   │   ├── 6-pointer-events/
│   │   │   ├── article.md
│   │   │   ├── ball-2.view/
│   │   │   │   └── index.html
│   │   │   ├── ball.view/
│   │   │   │   └── index.html
│   │   │   ├── multitouch.view/
│   │   │   │   └── index.html
│   │   │   ├── slider-html.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   └── slider.view/
│   │   │       ├── index.html
│   │   │       └── style.css
│   │   ├── 7-keyboard-events/
│   │   │   ├── 2-check-sync-keydown/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── keyboard-dump.view/
│   │   │       ├── index.html
│   │   │       ├── script.js
│   │   │       └── style.css
│   │   ├── 8-onscroll/
│   │   │   ├── 1-endless-page/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-updown-button/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-load-visible-img/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 4-forms-controls/
│   │   ├── 1-form-elements/
│   │   │   ├── 1-add-select-option/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 2-focus-blur/
│   │   │   ├── 3-editable-div/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── my.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── my.css
│   │   │   │   └── task.md
│   │   │   ├── 4-edit-td-click/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── bagua.css
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── my.css
│   │   │   │   │   └── script.js
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── bagua.css
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── my.css
│   │   │   │   │   └── script.js
│   │   │   │   └── task.md
│   │   │   ├── 5-keyboard-mouse/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 3-events-change-input/
│   │   │   ├── 1-deposit-calculator/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 4-forms-submit/
│   │   │   ├── 1-modal-dialog/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 5-loading/
│   │   ├── 01-onload-ondomcontentloaded/
│   │   │   ├── article.md
│   │   │   ├── readystate.view/
│   │   │   │   ├── iframe.html
│   │   │   │   └── index.html
│   │   │   └── window-onbeforeunload.view/
│   │   │       └── index.html
│   │   ├── 02-script-async-defer/
│   │   │   ├── article.md
│   │   │   ├── long.js
│   │   │   └── small.js
│   │   ├── 03-onload-onerror/
│   │   │   ├── 1-load-img-callback/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── crossorigin.view/
│   │   │       └── error.js
│   │   └── index.md
│   ├── 99-ui-misc/
│   │   ├── 01-mutation-observer/
│   │   │   └── article.md
│   │   ├── 02-selection-range/
│   │   │   └── article.md
│   │   ├── 03-event-loop/
│   │   │   ├── 2-micro-macro-queue/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   └── index.md
├── 3-frames-and-windows/
│   ├── 01-popup-windows/
│   │   └── article.md
│   ├── 03-cross-window-communication/
│   │   ├── article.md
│   │   ├── postmessage.view/
│   │   │   ├── iframe.html
│   │   │   └── index.html
│   │   └── sandbox.view/
│   │       ├── index.html
│   │       └── sandboxed.html
│   ├── 06-clickjacking/
│   │   ├── article.md
│   │   ├── clickjacking-visible.view/
│   │   │   ├── facebook.html
│   │   │   └── index.html
│   │   ├── clickjacking.view/
│   │   │   ├── facebook.html
│   │   │   └── index.html
│   │   ├── protector.view/
│   │   │   ├── iframe.html
│   │   │   └── index.html
│   │   └── top-location.view/
│   │       ├── iframe.html
│   │       └── index.html
│   └── index.md
├── 4-binary/
│   ├── 01-arraybuffer-binary-arrays/
│   │   ├── 01-concat/
│   │   │   ├── _js.view/
│   │   │   │   ├── solution.js
│   │   │   │   ├── source.js
│   │   │   │   └── test.js
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 02-text-decoder/
│   │   └── article.md
│   ├── 03-blob/
│   │   └── article.md
│   ├── 04-file/
│   │   └── article.md
│   └── index.md
├── 5-network/
│   ├── 01-fetch/
│   │   ├── 01-fetch-users/
│   │   │   ├── _js.view/
│   │   │   │   ├── solution.js
│   │   │   │   ├── source.js
│   │   │   │   └── test.js
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── article.md
│   │   └── post.view/
│   │       └── server.js
│   ├── 02-formdata/
│   │   ├── article.md
│   │   └── post.view/
│   │       └── server.js
│   ├── 03-fetch-progress/
│   │   ├── article.md
│   │   └── progress.view/
│   │       ├── index.html
│   │       └── long.txt
│   ├── 04-fetch-abort/
│   │   ├── article.md
│   │   └── demo.view/
│   │       └── server.js
│   ├── 05-fetch-crossorigin/
│   │   ├── 1-do-we-need-origin/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 06-fetch-api/
│   │   ├── article.md
│   │   └── post.view/
│   │       ├── index.html
│   │       └── server.js
│   ├── 07-url/
│   │   └── article.md
│   ├── 08-xmlhttprequest/
│   │   ├── article.md
│   │   ├── example.view/
│   │   │   ├── index.html
│   │   │   └── server.js
│   │   ├── hello.txt
│   │   ├── phones-async.view/
│   │   │   ├── index.html
│   │   │   ├── phones.json
│   │   │   └── server.js
│   │   ├── phones.json
│   │   ├── phones.view/
│   │   │   ├── index.html
│   │   │   ├── phones.json
│   │   │   └── server.js
│   │   └── post.view/
│   │       ├── index.html
│   │       └── server.js
│   ├── 09-resume-upload/
│   │   ├── article.md
│   │   └── upload-resume.view/
│   │       ├── index.html
│   │       ├── server.js
│   │       └── uploader.js
│   ├── 10-long-polling/
│   │   ├── article.md
│   │   └── longpoll.view/
│   │       ├── browser.js
│   │       ├── index.html
│   │       └── server.js
│   ├── 11-websocket/
│   │   ├── article.md
│   │   ├── chat.view/
│   │   │   ├── index.html
│   │   │   └── server.js
│   │   └── demo.view/
│   │       └── server.js
│   ├── 12-server-sent-events/
│   │   ├── article.md
│   │   └── eventsource.view/
│   │       ├── index.html
│   │       └── server.js
│   └── index.md
├── 6-data-storage/
│   ├── 01-cookie/
│   │   ├── article.md
│   │   └── cookie.js
│   ├── 02-localstorage/
│   │   ├── 1-form-autosave/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   ├── source.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── article.md
│   │   └── sessionstorage.view/
│   │       ├── iframe.html
│   │       └── index.html
│   ├── 03-indexeddb/
│   │   ├── article.md
│   │   └── books.view/
│   │       └── index.html
│   └── index.md
├── 7-animation/
│   ├── 1-bezier-curve/
│   │   └── article.md
│   ├── 2-css-animations/
│   │   ├── 1-animate-logo-css/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   ├── source.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── 2-animate-logo-bezier-css/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── 3-animate-circle/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   ├── source.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── 4-animate-circle-callback/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── article.md
│   │   ├── boat.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── digits-negative-delay.view/
│   │   │   ├── index.html
│   │   │   ├── script.js
│   │   │   └── style.css
│   │   ├── digits.view/
│   │   │   ├── index.html
│   │   │   ├── script.js
│   │   │   └── style.css
│   │   ├── step-end.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── step-list.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── step.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── train-linear.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── train-over.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   └── train.view/
│   │       ├── index.html
│   │       └── style.css
│   ├── 3-js-animation/
│   │   ├── 1-animate-ball/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   ├── source.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   └── task.md
│   │   ├── 2-animate-ball-hops/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   └── task.md
│   │   ├── article.md
│   │   ├── back.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── bounce-easeinout.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── bounce-easeout.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── bounce.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── circ.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── elastic.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── move-raf.view/
│   │   │   └── index.html
│   │   ├── move.view/
│   │   │   └── index.html
│   │   ├── quad.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── quint.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── text.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   └── width.view/
│   │       ├── animate.js
│   │       └── index.html
│   └── index.md
├── 8-web-components/
│   ├── 1-webcomponents-intro/
│   │   ├── .vs/
│   │   │   ├── 1-webcomponents-intro/
│   │   │   │   └── v15/
│   │   │   │       └── .suo
│   │   │   └── VSWorkspaceState.json
│   │   └── article.md
│   ├── 2-custom-elements/
│   │   ├── 1-live-timer/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── live-timer.js
│   │   │   │   └── time-formatted.js
│   │   │   ├── source.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── live-timer.js
│   │   │   │   └── time-formatted.js
│   │   │   └── task.md
│   │   ├── article.md
│   │   └── head.html
│   ├── 3-shadow-dom/
│   │   └── article.md
│   ├── 4-template-element/
│   │   └── article.md
│   ├── 5-slots-composition/
│   │   ├── article.md
│   │   └── menu.view/
│   │       └── index.html
│   ├── 6-shadow-dom-style/
│   │   └── article.md
│   ├── 7-shadow-dom-events/
│   │   └── article.md
│   └── index.md
├── 9-regular-expressions/
│   ├── 01-regexp-introduction/
│   │   └── article.md
│   ├── 02-regexp-character-classes/
│   │   └── article.md
│   ├── 03-regexp-unicode/
│   │   └── article.md
│   ├── 04-regexp-anchors/
│   │   ├── 1-start-end/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 05-regexp-multiline-mode/
│   │   └── article.md
│   ├── 06-regexp-boundary/
│   │   ├── 1-find-time-hh-mm/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 07-regexp-escaping/
│   │   └── article.md
│   ├── 08-regexp-character-sets-and-ranges/
│   │   ├── 1-find-range-1/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 2-find-time-2-formats/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 09-regexp-quantifiers/
│   │   ├── 1-find-text-manydots/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 2-find-html-colors-6hex/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 10-regexp-greedy-and-lazy/
│   │   ├── 1-lazy-greedy/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 3-find-html-comments/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 4-find-html-tags-greedy-lazy/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 11-regexp-groups/
│   │   ├── 01-test-mac/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 02-find-webcolor-3-or-6/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 03-find-decimal-numbers/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 04-parse-expression/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 12-regexp-backreferences/
│   │   └── article.md
│   ├── 13-regexp-alternation/
│   │   ├── 01-find-programming-language/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 02-find-matching-bbtags/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 03-match-quoted-string/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 04-match-exact-tag/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 14-regexp-lookahead-lookbehind/
│   │   ├── 1-find-non-negative-integers/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 2-insert-after-head/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 15-regexp-catastrophic-backtracking/
│   │   └── article.md
│   ├── 16-regexp-sticky/
│   │   └── article.md
│   ├── 17-regexp-methods/
│   │   └── article.md
│   └── index.md
├── AUTHORING.md
├── LICENSE.md
├── README.md
├── changes.sketch
├── css.md
├── figures.sketch
├── property-accessors.md
├── script/
│   └── clean-unused-png.php
└── todo.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
* text=auto eol=lf
*.svg       binary


================================================
FILE: .gitignore
================================================
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.vi
*~
*.sass-cache

# OS or Editor folders
.DS_Store
.idea
.cache
.project
.settings
.tmproj
.nvmrc
sftp-config.json
Thumbs.db
tags

/svgs

================================================
FILE: 1-js/01-getting-started/1-intro/article.md
================================================
# Une Introduction à JavaScript

Voyons ce qui est spécial à propos de JavaScript, ce qu'il nous permet de faire et avec quelles autres technologies il s'accorde bien.

<iframe width="560" height="315" src="https://www.youtube.com/embed/-eEx3yRZ-sE" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## Qu'est-ce que JavaScript ?

_JavaScript_ a été initialement créé pour "rendre les pages web vivantes".

Les programmes dans ce langage sont appelés _scripts_. Ils peuvent être écrits directement dans une page HTML et exécutés automatiquement au chargement des pages.

Les scripts sont fournis et exécutés en texte brut. Ils n'ont pas besoin d'une préparation spéciale ou d'une compilation pour fonctionner.

De par cet aspect, JavaScript est très différent d'un autre langage appelé [Java](<https://fr.wikipedia.org/wiki/Java_(langage)>).

```smart header="Pourquoi est-il appelé <u>Java</u>Script ?"
Quand JavaScript a été créé, il portait initialement un autre nom : "LiveScript". Mais à cette époque le langage Java était très populaire, il a donc été décidé que positionner un nouveau langage en tant que "petit frère" de Java pourrait aider.

Mais au fur et à mesure de son évolution, JavaScript est devenu un langage totalement indépendant, avec ses propres spécifications appelées [ECMAScript](https://fr.wikipedia.org/wiki/ECMAScript), aujourd'hui il n'a aucun rapport avec Java.
```

Aujourd'hui, JavaScript peut s'exécuter non seulement dans le navigateur, mais également sur un serveur, ou encore sur n'importe quel appareil dans lequel existe un programme appelé [le moteur JavaScript](https://fr.wikipedia.org/wiki/Moteur_JavaScript).

Le navigateur a un moteur intégré, parfois il peut être également appelé "la machine virtuelle JavaScript".

Différents moteurs ont différents "nom de code", par exemple :

- [V8](<https://fr.wikipedia.org/wiki/V8_(moteur_JavaScript)>) -- dans Chrome et Opera.
- [SpiderMonkey](https://fr.wikipedia.org/wiki/SpiderMonkey) -- dans Firefox.
- … Il existe d'autres noms de code comme "Chakra" pour IE, "JavaScriptCore", "Nitro" et "SquirrelFish" pour Safari etc.

Les termes ci-dessus sont bons à retenir, car ils sont utilisés dans les articles destinés aux développeurs sur Internet. Nous les utiliserons aussi. Par exemple, si "une fonctionnalité X est prise en charge par V8", cela fonctionne probablement dans Chrome, Edge et Opera.

```smart header="Comment fonctionnent les moteurs ?"

Les moteurs sont compliqués. Mais le fonctionnement de base est facile à comprendre.

1. Le moteur (intégré si c’est un navigateur) lit ("analyse") le script.
2. Ensuite, il convertit ("compile") le script en langage machine.
3. Enfin le code machine s'exécute, très rapidement.

Le moteur applique des optimisations à chaque étape du processus. Il surveille même le script compilé en cours d'exécution, analyse les données qui le traversent et applique des optimisations au code machine en fonction de ces informations.
```

## Que peut faire JavaScript dans le navigateur ?

Le JavaScript moderne est un langage de programmation "sûr". Il ne fournit pas d'accès de bas niveau à la mémoire ou au processeur, parce qu'il a été initialement conçu pour les navigateurs qui n'en ont pas besoin.

Les fonctionnalités dépendent grandement de l'environnement qui exécute JavaScript. Par exemple, [Node.js](https://fr.wikipedia.org/wiki/Node.js) prend en charge les fonctions qui permettent à JavaScript de lire / écrire des fichiers arbitrairement, d'exécuter des requêtes réseau, etc.

JavaScript intégré au navigateur peut faire tout ce qui concerne la manipulation des pages Web, l'interaction avec l'utilisateur et le serveur Web.

Par exemple, JavaScript dans le navigateur est capable de :

- Ajouter un nouveau code HTML à la page, modifier le contenu existant, modifier les styles.
- Réagir aux actions de l'utilisateur, s'exécuter sur des clics de souris, des mouvements de pointeur, des appuis sur des touches.
- Envoyer des requêtes sur le réseau à des serveurs distants, télécharger et envoyer des fichiers (technologies [AJAX](<https://fr.wikipedia.org/wiki/Ajax_(informatique)>) et [COMET](<https://fr.wikipedia.org/wiki/Comet_(informatique)>)).
- Obtenir et définir des cookies, poser des questions au visiteur, afficher des messages.
- Se souvenir des données du côté client ("stockage local").

## Qu'est-ce que JavaScript ne peut pas faire dans le navigateur ?

Les capacités de JavaScript dans le navigateur sont limitées pour la sécurité de l'utilisateur. L'objectif est d'empêcher une page Web malveillante d'accéder à des informations privées ou de nuire aux données de l'utilisateur.

Les exemples de telles restrictions sont :

- JavaScript sur une page Web ne peut pas lire/écrire des fichiers arbitrairement sur le disque dur, les copier ou exécuter des programmes. Il n'a pas d'accès direct aux fonctions du système d'exploitation.

  Les navigateurs modernes lui permettent de fonctionner avec des fichiers, mais l'accès est limité et n'est fourni que si l'utilisateur effectue certaines actions, comme «déposer» un fichier dans une fenêtre de navigateur ou le sélectionner via une balise `<input>`.

  Il existe des moyens d’interagir avec une webcam/microphone et d’autres périphériques, mais ils nécessitent une autorisation explicite de l’utilisateur. Ainsi, une page contenant du JavaScript ne permet pas d'activer une caméra Web, d'observer l'environnement et d'envoyer les informations à la [NSA](https://fr.wikipedia.org/wiki/National_Security_Agency).

- Différents onglets / fenêtres ne se connaissent généralement pas. Parfois, ils se croisent, par exemple lorsqu'une fenêtre utilise JavaScript pour ouvrir l'autre. Mais même dans ce cas, le JavaScript d'une page ne peut pas accéder à l'autre si elle provient de sites différents (provenant d'un autre domaine, protocole ou port).

  C'est ce qu'on appelle la "politique de même origine" (“Same Origin Policy”). Pour contourner cette sécurité, _les deux pages_ doivent se mettre d'accord et contenir un code JavaScript spécial qui gère l'échange de données. Nous verrons cela plus loin dans ce tutoriel.

  Cette limitation concerne également la sécurité de l'utilisateur. Une page de `http://autresite.com` qu'un utilisateur a ouvert ne doit pas pouvoir accéder à un autre onglet du navigateur avec l'URL `http://gmail.com` et y voler des informations.

- JavaScript peut facilement communiquer sur le net avec le serveur d'où provient la page. Mais sa capacité à recevoir des données d'autres sites / domaines est paralysée. Bien que possible, il nécessite un accord explicite (exprimé dans les en-têtes HTTP) du côté distant. Encore une fois, ce sont des limites de sécurité.

![Schéma des limitations du JavaScript dans un navigateur](limitations.svg)

De telles limites n'existent pas si JavaScript est utilisé en dehors du navigateur, par exemple sur un serveur. Les navigateurs modernes permettent également l’installation de plug-ins / extensions susceptibles d’obtenir des autorisations étendues.

## Qu'est-ce qui rend JavaScript unique ?

Il y a au moins trois bonnes choses à propos de JavaScript :

```compare
+ Intégration complète avec HTML / CSS.
+ Les choses simples sont faites simplement.
+ Pris en charge par tous les principaux navigateurs et activé par défaut.
```

JavaScript est la seule technologie de navigateur qui combine ces trois éléments.

C’est ce qui rend JavaScript unique. C’est pourquoi il l’outil le plus répandu pour créer des interfaces de navigateur.

Cela dit, JavaScript permet également de créer des serveurs, des applications mobiles, etc.

## Les langages "par dessus" JavaScript

La syntaxe de JavaScript ne convient pas aux besoins de tous. Différentes personnes veulent des fonctionnalités différentes.

Il faut s’y attendre, parce que besoins sont différents pour tous.

Donc, récemment, une pléthore de nouveaux langages sont apparus, qui sont _transpilés_ (convertis) en JavaScript avant leur exécution dans le navigateur.

Les outils modernes rendent la [transpilation](https://fr.wiktionary.org/wiki/transpilation) très rapide et transparente, permettant aux développeurs de coder dans un autre langage et de le convertir automatiquement "sous le capot".

Les exemples de ce genre de langages :

- [CoffeeScript](http://coffeescript.org/) est un "sucre syntaxique" pour JavaScript, il introduit une syntaxe plus courte, permettant d’écrire du code plus précis et plus clair. Habituellement, les développeurs Ruby l'aiment bien.
- [TypeScript](http://www.typescriptlang.org/) se concentre sur l'ajout de "typage strict des données" pour simplifier le développement et la prise en charge de systèmes complexes. Il est développé par Microsoft.
- [Flow](http://flow.org/) ajoute également la saisie de données, mais de manière différente. Développé par Facebook.
- [Dart](https://www.dartlang.org/) est un langage autonome doté de son propre moteur qui s'exécute dans des environnements autres que les navigateurs (comme les applications mobiles), mais peut aussi être transpilé en JavaScript. Développé par Google.
- [Brython](https://brython.info/) est un transpiler (ou transpileur en bon français) Python vers JavaScript qui permet d'écrire des applications en Python pur sans JavaScript.
- [Kotlin](https://kotlinlang.org/docs/reference/js-overview.html) est un langage de programmation moderne, concis et sûr qui peut cibler le navigateur ou Node.js

Il en existe évidemment bien plus, cela dit, même si nous utilisons un de ces langages transpilés, nous devrions également connaître le langage JavaScript, pour bien comprendre ce que nous faisons.

## Résumé

- JavaScript a été initialement créé en tant que langage de navigateur uniquement, mais il est désormais également utilisé dans de nombreux autres environnements.
- En ce moment, JavaScript occupe une position unique en tant que langage de navigateur le plus largement adopté avec une intégration complète avec HTML/CSS.
- De nombreux langages sont _transpilés_ en JavaScript et fournissent certaines fonctionnalités. Il est recommandé d'y jeter un coup d'œil, au moins brièvement, après avoir maîtrisé JavaScript.


================================================
FILE: 1-js/01-getting-started/2-manuals-specifications/article.md
================================================

# Manuels et spécifications

Ce livre est un *tutoriel*. Il vise à vous aider à apprendre progressivement le langage. Mais une fois que vous maîtriserez les bases, vous aurez besoin d’autres ressources.

<iframe width="560" height="315" src="https://www.youtube.com/embed/TqQs_MKMqwU" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## Spécification

[The ECMA-262 specification](https://www.ecma-international.org/publications/standards/Ecma-262.htm) contient les informations les plus détaillées et formalisées sur JavaScript. C'est elle qui définit le langage.

Une nouvelle version de la spécification est publiée chaque année. La dernière version en cours est disponible à cette adresse : <https://tc39.es/ecma262/>.

Pour en savoir plus sur les fonctionnalités à venir, y compris celles qui sont "presque standards" (appelées aussi "stage 3"), vous pouvez consulter les propositions à cette adresse : <https://github.com/tc39/proposals>.

De plus, si vous développez pour le navigateur, d'autres spécifications sont couvertes dans la [seconde partie](info:browser-environment) du tutoriel.

## Manuels

- **La référence MDN (Mozilla) JavaScript** est le principal manuel avec des exemples et d’autres informations. C’est une excellente source pour obtenir des informations détaillées sur les fonctions linguistiques, les méthodes, etc.

    On peut la trouver à cette adresse : <https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference>.

  Cependant, il est souvent préférable d’utiliser une recherche sur Internet. Utilisez simplement "MDN [terme]" dans la requête, par exemple <https://google.com/search?q=MDN+parseInt> pour rechercher la fonction `parseInt`.


## Tableaux de compatibilité

JavaScript est un langage en développement, de nouvelles fonctionnalités sont ajoutées régulièrement.

Pour voir si elles sont supportées dans les moteurs, au sein des navigateurs et autres, voir :

- <http://caniuse.com> - tables de prise en charge par fonctionnalité, par exemple pour voir quels moteurs supportent les fonctions de cryptographie modernes : <http://caniuse.com/#feat=cryptography>.
- <https://kangax.github.io/compat-table> - un tableau avec les fonctionnalités linguistiques et les moteurs qui les prennent en charge ou non.

Toutes ces ressources sont utiles dans le quotidien des développeurs, parce qu'elles contiennent des informations précieuses sur les fonctionnalités du langage, leur support, etc.

Veuillez vous en souvenir (ou de cette page) pour les cas où vous avez besoin d'informations détaillées sur une fonctionnalité particulière.


================================================
FILE: 1-js/01-getting-started/3-code-editors/article.md
================================================
# Les éditeurs de code 

<iframe width="560" height="315" src="https://www.youtube.com/embed/KNs-GfVmt3A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Un éditeur de code est l'endroit où les programmeurs passent la plus grande partie de leur temps.

Il existe deux archétypes: IDE et les éditeurs légers. Beaucoup de personnes se sentent à l'aise pour choisir un outil de chaque type.

## IDE

Le terme [IDE](https://fr.wikipedia.org/wiki/Environnement_de_développement) (Integrated Development Environment) signifie un éditeur puissant avec de nombreuses fonctionnalités qui fonctionne généralement sur un "projet entier". Comme son nom l’indique, ce n’est pas seulement un éditeur, mais un environnement de développement complet.

Un IDE charge le projet (peut contenir de nombreux fichiers), permet la navigation entre les fichiers, fournit une auto-complétion basée sur l'ensemble du projet (pas seulement le fichier ouvert), s'intègre à un système de gestion de version (comme [git](https://git-scm.com/)), un environnement de test et d’autres éléments au niveau du projet.

Si vous n'avez pas encore pensé à sélectionner un IDE, examinez les variantes suivantes :

- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [WebStorm](https://www.jetbrains.com/webstorm/) (cross-platform, payant).

Pour Windows, il existe également "Visual Studio", à ne pas confondre avec "Visual Studio Code ". "Visual Studio" est un IDE payant et puissant, disponible sur Windows et Mac, bien adapté à la plate-forme .NET. C’est aussi bon en JavaScript. Il y a aussi une version gratuite [Visual Studio Community](https://www.visualstudio.com/vs/community/).

La plupart des IDE sont payants, mais ont une période d'essai. Leur coût est généralement négligeable par rapport au salaire d’un développeur qualifié, alors choisissez le meilleur pour vous.

## Les éditeurs légers

"Les éditeurs légers" ne sont pas aussi puissants que les IDE, mais ils sont rapides, élégants et simples.

Ils sont principalement utilisés pour ouvrir et éditer instantanément un fichier.

La principale différence entre un "éditeur léger" et un "IDE" réside dans le fait qu’un environnement de développement intégré fonctionne au niveau du projet. Il charge donc beaucoup plus de données au démarrage, analyse la structure du projet si nécessaire, etc. Un éditeur léger est beaucoup plus rapide si nous avons besoin d'un seul fichier.

En pratique, les éditeurs légers peuvent avoir beaucoup de plug-ins, y compris des analyseurs de syntaxe au niveau des répertoires et des autocompléteurs. Il n’y a donc pas de frontière stricte entre un éditeur léger et un IDE.

Il existe de nombreuses options, par exemple :

- [Sublime Text](http://www.sublimetext.com) (multiplateforme, payant).
- [Notepad++](https://notepad-plus-plus.org/) (Windows, gratuit).
- [Vim](https://www.vim.org/) et [Emacs](https://www.gnu.org/software/emacs/) sont également cool, si vous savez comment les utiliser.


## Ne discutons pas

Les éditeurs des listes ci-dessus sont ceux que moi-même ou mes amis, que je considère comme de bons développeurs, utilisent depuis longtemps et en sont satisfaits.

Il y a d'autres grands éditeurs dans notre vaste monde. Veuillez choisir celui que vous aimez le plus.

Le choix d'un éditeur, comme tout autre outil, est individuel et dépend de vos projets, de vos habitudes, de vos préférences personnelles.

L'avis personnel de l'auteur :

- J'utilise [Visual Studio Code](https://code.visualstudio.com/) si je développe principalement du frontend.
- Sinon, s'il s'agit principalement d'un autre langage/plate-forme et partiellement d'un frontend, envisagez d'autres éditeurs, tels que XCode (Mac), Visual Studio (Windows) ou la famille Jetbrains (Webstorm, PHPStorm, RubyMine, etc., selon le langage).


================================================
FILE: 1-js/01-getting-started/4-devtools/article.md
================================================
# La console de développement

<iframe width="560" height="315" src="https://www.youtube.com/embed/OFj8hFVS1KY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Le code est sujet aux erreurs. Vous êtes susceptible de faire des erreurs … Oh, de quoi je parle ? Vous allez absolument faire des erreurs, du moins si vous êtes un humain, pas un [robot](https://fr.wikipedia.org/wiki/Bender_Tordeur_Rodr%C3%ADguez).

Mais dans le navigateur, un utilisateur ne voit pas les erreurs par défaut. Ainsi, si quelque chose ne va pas dans le script, nous ne verrons pas ce qui ne va pas et nous ne pourrons pas le réparer.

Pour voir les erreurs et obtenir beaucoup d’informations utiles sur les scripts, les navigateurs intègrent des "outils de développement".

Le plus souvent, les développeurs se tournent vers Chrome ou Firefox pour le développement, car ces navigateurs disposent des meilleurs outils de développement. D'autres navigateurs fournissent également des outils de développement, parfois dotés de fonctions spéciales, mais jouent généralement le rôle de "rattrapage" pour Chrome ou Firefox. Donc, la plupart des gens ont un navigateur "favori" et passent à d'autres si un problème est spécifique au navigateur.

Les outils de développement sont très puissants ; ils possèdent de nombreuses fonctionnalités. Pour commencer, nous allons apprendre à les ouvrir, à examiner les erreurs et à exécuter des commandes JavaScript.

## Google Chrome

Ouvrez la page [bug.html](bug.html).

Il y a une erreur dans le code JavaScript. Elle est invisible à un visiteur habituel, alors ouvrons les outils de développement pour la voir.

Appuyez sur `key:F12` ou, si vous êtes sur Mac, utilisez la combinaison `key:Cmd+Opt+J`.

Les outils de développement s'ouvriront sous l'onglet Console par défaut.

Cela ressemble un peu à ceci :

![chrome](chrome.png)

L'aspect exact des outils de développement dépend de votre version de Chrome. Cela change de temps en temps, mais devrait être similaire.

- Ici, nous pouvons voir le message d'erreur de couleur rouge. Dans ce cas, le script contient une commande "lalala" inconnue.
- Sur la droite, il y a un lien cliquable vers le code source bug.html:12 avec le numéro de ligne où l'erreur s'est produite.

Sous le message d'erreur, il y a un symbole bleu `>`. Il marque une "ligne de commande" où l'on peut taper des commandes JavaScript et appuyer sur `key:Enter` pour les exécuter.

Nous pouvons maintenant voir les erreurs et c’est suffisant pour le début. Nous reviendrons plus tard sur les outils de développement et approfondirons le débogage plus loin dans le chapitre <info:debugging-chrome>.

```smart header="Multi-line input"
Habituellement, quand on met une ligne de code dans la console, puis qu'on appuie sur `key:Enter`, elle s'exécute.

Pour insérer plusieurs lignes, appuyez sur `key:Shift+Enter`. De cette façon, on peut saisir de longs fragments de code JavaScript.
```

## Firefox, Edge et autres

La plupart des autres navigateurs utilisent `key:F12` pour ouvrir les outils de développement.

Leur apparence est assez similaire. Une fois que vous savez comment utiliser l'un d'entre eux (vous pouvez commencer avec Chrome), vous pouvez facilement passer à un autre.

## Safari

Safari (navigateur Mac, non pris en charge par Windows / Linux) est un peu spécial ici. Nous devons d'abord activer le menu "Développement".

Ouvrez les préférences et accédez au volet "Avancé". Il y a une case à cocher en bas :

![safari](safari.png)

Maintenant `key:Cmd+Opt+C` peut activer la console. Notez également que le nouvel élément de menu supérieur nommé "Développement" est apparu. Il a beaucoup de commandes et d'options.



## Résumé

- Les outils de développement nous permettent de voir les erreurs, d'exécuter des commandes, d'examiner des variables et bien plus encore.
- Ils peuvent être ouverts avec `key:F12` pour la plupart des navigateurs sous Windows. Chrome pour Mac nécessite la combinaison `key:Cmd+Opt+J`, Safari: `key:Cmd+Opt+C` (doit être activé avant).


Nous avons maintenant notre environnement prêt. Dans la section suivante, nous passerons à JavaScript.


================================================
FILE: 1-js/01-getting-started/4-devtools/bug.html
================================================
<!DOCTYPE HTML>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

  There is an error in the script on this page.
  <script>
    lalala
  </script>

</body>

</html>

================================================
FILE: 1-js/01-getting-started/index.md
================================================
# Une introduction

A propos du langage JavaScript et de l'environnement pour le développeur.


================================================
FILE: 1-js/02-first-steps/01-hello-world/1-hello-alert/index.html
================================================
<!DOCTYPE html>
<html>

<body>

  <script>
    alert( "I'm JavaScript!" );
  </script>

</body>

</html>


================================================
FILE: 1-js/02-first-steps/01-hello-world/1-hello-alert/solution.md
================================================

[html src="index.html"]


================================================
FILE: 1-js/02-first-steps/01-hello-world/1-hello-alert/solution.view/index.html
================================================
<!DOCTYPE html>
<html>

<body>

  <script>
    alert( "I'm JavaScript!" );
  </script>

</body>

</html>

================================================
FILE: 1-js/02-first-steps/01-hello-world/1-hello-alert/task.md
================================================
importance: 5

---

# Afficher une alerte

Créez une page qui affiche un message "Je suis JavaScript!".

Faites-le dans un bac à sable ou sur votre disque dur, peu importe, assurez-vous simplement que cela fonctionne.

[demo src="solution"]



================================================
FILE: 1-js/02-first-steps/01-hello-world/2-hello-alert-ext/alert.js
================================================
alert("I'm JavaScript!");

================================================
FILE: 1-js/02-first-steps/01-hello-world/2-hello-alert-ext/index.html
================================================
<!DOCTYPE html>
<html>

<body>

  <script src="alert.js"></script>

</body>

</html>

================================================
FILE: 1-js/02-first-steps/01-hello-world/2-hello-alert-ext/solution.md
================================================
The HTML code:

[html src="index.html"]

pour le fichier `alert.js` dans le même dossier :

[js src="alert.js"]



================================================
FILE: 1-js/02-first-steps/01-hello-world/2-hello-alert-ext/task.md
================================================
importance: 5

---

# Afficher une alerte avec un script externe

Prendre la solution de l'exercice précédent <info:task/hello-alert>. Modifiez-le en extrayant le contenu du script dans un fichier externe `alert.js`, résidant dans le même dossier.

Ouvrez la page, assurez-vous que l'alerte fonctionne.


================================================
FILE: 1-js/02-first-steps/01-hello-world/article.md
================================================
# Hello, world!

<iframe width="560" height="315" src="https://www.youtube.com/embed/0WS0zqhT5fM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Cette partie du tutoriel est à propos du coeur de JavaScript, le langage lui même.

Mais nous avons besoin d'un environnement de travail pour exécuter nos scripts et, étant donné que ce guide est en ligne, le navigateur est un bon choix. Nous allons nous efforcer d'utiliser les commandes spécifiques au navigateur (comme `alert`) au minimum afin de ne pas y consacrer du temps si vous prévoyez de vous concentrer sur un autre environnement tel que Node.JS. Par ailleurs, les détails du navigateur sont expliqués dans [la partie suivante](/ui) du didacticiel.

Alors, voyons d'abord comment intégrer un script à une page Web. Pour les environnements côté serveur, vous pouvez simplement l'exécuter avec une commande comme `"node mon.js"` pour Node.JS.


## La balise "script"

Les programmes JavaScript peuvent être insérés dans n'importe quelle partie d'un document HTML à l'aide de la balise `<script>`.

Par exemple :

```html run height=100
<!DOCTYPE HTML>
<html>

<body>

  <p>Before the script...</p>

*!*
  <script>
    alert( 'Hello, world!' );
  </script>
*/!*

  <p>...After the script.</p>

</body>

</html>
```

```online
Vous pouvez exécuter l'exemple en cliquant sur le bouton "Play" dans son coin supérieur droit.
```

La balise `<script>` contient du code JavaScript qui est automatiquement exécuté lorsque le navigateur rencontre la balise.


## Le balisage moderne

La balise `<script>` a quelques attributs qui sont rarement utilisés de nos jours, mais nous pouvons les trouver dans l'ancien code :

 L'attribut `type` : <code>&lt;script <u>type</u>=...&gt;</code>
: L’ancien standard HTML4, nécessitait pour chaque script d'avoir un `type`. Habituellement c'était `type="text/javascript"`. Dorénavant ce n’est plus nécessaire. De plus, le standard HTML moderne a totalement changé la signification de cet attribut. Maintenant, il peut être utilisé pour les modules JavaScript. Mais c’est un sujet avancé, nous parlerons de modules dans une autre partie du tutoriel.

 L'attribut `language` : <code>&lt;script <u>language</u>=...&gt;</code>
: Cet attribut était destiné à afficher le langage du script. Pour l'instant, cet attribut n'a aucun sens, le langage est le JavaScript par défaut. Pas besoin de l'utiliser.

Commentaires avant et après les scripts.
: Dans des livres et des guides vraiment anciens, on peut trouver des commentaires dans `<script>`, comme ceci :

    ```html no-beautify
    <script type="text/javascript"><!--
        ...
    //--></script>
    ```

    Cette astuce n’est pas utilisée dans le JavaScript moderne. Ces commentaires ont été utilisés pour masquer le code JavaScript des anciens navigateurs qui ne savaient pas comment traiter une balise `<script>`. Comme les navigateurs nés au cours des 15 dernières années n’ont pas ce problème, ce type de commentaire peut vous aider à identifier un code très ancien.


## Scripts externes

Si nous avons beaucoup de code JavaScript, nous pouvons le placer dans un fichier séparé.

Le fichier de script est attaché à HTML avec l'attribut `src` :

```html
<script src="/chemin/vers/script.js"></script>
```

Ici, `/chemin/vers/script.js` est un chemin absolu du script depuis la racine du site. On peut également fournir un chemin relatif à partir de la page en cours. Par exemple `src="script.js"` signifierait un fichier `"script.js"` dans le dossier courant.

Nous pouvons également donner une URL complète, par exemple :

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
```

Pour joindre plusieurs scripts, utilisez plusieurs tags :

```html
<script src="/js/script1.js"></script>
<script src="/js/script2.js"></script>
…
```

```smart
En règle générale, seuls les scripts les plus simples sont mis en HTML. Les plus complexes résident dans des fichiers séparés.

L’avantage d’un fichier séparé est que le navigateur le télécharge puis le stocke dans son [cache](https://fr.wikipedia.org/wiki/Cache_web).

Après cela, les autres pages qui veulent le même script le récupéreront à partir du cache au lieu de le télécharger à nouveau. Le fichier n'est donc téléchargé qu'une seule fois.

Cela économise du trafic et rend les pages plus rapides.
```

````warn header="Si `src` est défini, le contenu de la balise script est ignoré."
Une seule balise `<script>` ne peut pas avoir à la fois l'attribut `src` et le code à l'intérieur.

Ceci ne fonctionnera pas :

```html
<script *!*src*/!*="file.js">
  alert(1); // le contenu est ignoré, parce que src est défini
</script>
```

Nous devons choisir : soit un script `<script src = "…">` externe, soit un `<script>` régulier avec du code.

L'exemple ci-dessus peut être divisé en deux scripts pour fonctionner :

```html
<script src="file.js"></script>
<script>
  alert(1);
</script>
```
````

## Résumé

- Nous pouvons utiliser une balise `<script>` pour ajouter du code JavaScript à la page.
- Les attributs de `type` et de `langue` ne sont pas requis.
- Un script dans un fichier externe peut être inséré avec `<script src = "chemin / vers / script.js"> </ script>`.


Il y a beaucoup plus à apprendre sur les scripts de navigateur et leur interaction avec la page Web. Mais gardons à l’esprit que cette partie du tutoriel est consacrée au langage JavaScript, nous ne devons donc pas nous en distraire. Nous utiliserons un navigateur comme moyen pour exécuter JavaScript, ce qui est très pratique pour la lecture en ligne, mais il en existe beaucoup d'autres.


================================================
FILE: 1-js/02-first-steps/02-structure/article.md
================================================
# Structure du code

La première chose à apprendre est de construire des blocs de code.

## Instructions

Les instructions sont des constructions de syntaxe et des commandes qui effectuent des actions.

Nous avons déjà vu une instruction `alert("Hello World!")` qui affiche le message.

Nous pouvons avoir autant d'instructions dans le code que nous le souhaitons. Une autre instruction peut être séparée par un point-virgule.

Par exemple, ici nous divisons le message en deux :

```js run no-beautify
alert("Hello"); alert("World");
```

Chaque instruction est généralement écrite sur une ligne distincte - le code devient donc plus lisible :

```js run no-beautify
alert("Hello");
alert("World");
```

## Les points-virgules [#semicolon]

Un point-virgule peut être omis dans la plupart des cas lorsqu'une rupture de ligne existe.

Cela fonctionnerait aussi :

```js run no-beautify
alert("Hello")
alert("World")
```

Ici, JavaScript interprète le saut de ligne comme un point-virgule "implicite". Cela s'appelle également [une insertion automatique de point-virgule](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion).

**Dans la plupart des cas, une nouvelle ligne implique un point-virgule. Mais "dans la plupart des cas" ne signifie pas "toujours"!**

Il y a des cas où une nouvelle ligne ne signifie pas un point-virgule, par exemple :

```js run no-beautify
alert(3 +
1
+ 2);
```

Le code génère `6`, car JavaScript n'insère pas de point-virgule ici. Il est intuitivement évident que si la ligne se termine par un plus `"+"`, alors c'est une "expression incomplète", donc un point-virgule serait incorrect. Et dans ce cas, cela fonctionne comme prévu.

**Mais il existe des situations où JavaScript "échoue" à prendre un point-virgule là où il est vraiment nécessaire.**

Les erreurs qui surviennent dans de tels cas sont assez difficiles à trouver et à corriger.

````smart header="Un exemple d'erreur"
Si vous êtes curieux de voir un exemple concret d’une telle erreur, vérifiez ce code :

```js run
alert("Hello");

[1, 2].forEach(alert);
```

Pas besoin de penser à la signification des crochets `[]` et `forEach` pour le moment. Nous les étudierons plus tard, pour l'instant, retenons simplement le résultat de l’exécution du code : il affiche `Hello`, puis `1`, puis `2`.

Supprimons maintenant le point-virgule après l’`alert` :

```js run no-beautify
alert("Hello")

[1, 2].forEach(alert);
```

La différence par rapport au code ci-dessus n'est qu'un caractère : le point-virgule à la fin de la première ligne a disparu.

Si nous exécutons ce code, seul le premier `Hello` s'affiche (et il y a une erreur, vous devrez peut-être ouvrir la console pour le voir). Il n'y a plus de chiffres.

C'est parce que JavaScript ne suppose pas de point-virgule avant les crochets `[...]`. Ainsi, le code du dernier exemple est traité comme une seule instruction.

Voici comment le moteur le voit :

```js run no-beautify
alert("Hello")[1, 2].forEach(alert);
```

Ça a l'air bizarre, non ? Une telle fusion dans ce cas est tout simplement une erreur. Nous devons mettre un point-virgule après l'`alert` pour que le code fonctionne correctement.

Cela peut arriver dans d'autres situations aussi.
````

Il est recommandé de mettre les points-virgules entre les instructions, même si elles sont séparées par des nouvelles lignes. Cette règle est largement adoptée par la communauté. Notons encore une fois - _il est possible_ de laisser de côté les points-virgules la plupart du temps. Mais il est plus sûr -- surtout pour un débutant -- de les utiliser.

## Les Commentaires [#code-comments]

Au fil du temps, le programme devient de plus en plus complexe. Il devient nécessaire d'ajouter des _commentaires_ qui décrivent ce qui se passe et pourquoi.

Les commentaires peuvent être placés à n'importe quel endroit du script. Ils n'affectent pas l'exécution, car le moteur les ignore simplement.

**Les commentaires sur une ligne commencent par deux barres obliques `//`.**

Le reste de la ligne est un commentaire. Il peut occuper une ligne complète ou suivre une déclaration.

Comme ici :

```js run
// Ce commentaire occupe une ligne à part
alert("Hello");

alert("World"); // Ce commentaire suit l'instruction
```

**Les commentaires multilignes commencent par une barre oblique et un astérisque <code>/\*</code> et se termine par un astérisque et une barre oblique <code>\*/</code>.**

Comme ceci :

```js run
/* Un exemple avec deux messages.
C'est un commentaire multiligne.
*/
alert("Hello");
alert("World");
```

Le contenu des commentaires est ignoré, donc si nous mettons du code à l'intérieur <code>/\* ... \*/</code> il ne s'exécutera pas.

Parfois, il est utile de désactiver temporairement une partie du code :

```js run
/* Commenter le code
alert('Hello');
*/
alert("World");
```

```smart header="Utiliser les raccourcis !"
Dans la plupart des éditeurs, une ligne de code peut être commentée par le raccourci `key:Ctrl+/` pour un commentaire sur une seule ligne et quelque chose comme `key:Ctrl+Shift+/` -- pour les commentaires multilignes (sélectionnez un morceau de code et appuyez sur la combinaison de touches). Pour Mac essayez `key:Cmd` au lieu de `key:Ctrl` et `key:Option` au lieu de `key:Shift`.
```

````warn header="Les commentaires imbriqués ne sont pas supportés !"
Il peut ne pas y avoir `/*...*/` à l'intérieur d'un autre `/*...*/`.

Un tel code se terminera avec une erreur :

```js run no-beautify
/*
  /* commentaire imbriqué ?!? */
*/
alert( 'World' );
```
````

N'hésitez pas à commenter votre code.

Les commentaires augmentent la taille globale du code, mais ce n'est pas un problème du tout. De nombreux outils permettent de réduire le code avant de le publier sur le serveur de production. Ils suppriment les commentaires, ils n'apparaissent donc pas dans les scripts de travail. Les commentaires n'ont donc aucun effet négatif sur la production.

Plus loin dans le tutoriel, il y aura un chapitre <info:coding-style> qui explique également comment écrire de meilleurs commentaires.


================================================
FILE: 1-js/02-first-steps/03-strict-mode/article.md
================================================
# Le mode moderne, "use strict"

JavaScript a longtemps évolué sans problèmes de compatibilité. De nouvelles fonctionnalités ont été ajoutées au langage, mais les anciennes fonctionnalités n’ont pas été modifiées.

Cela a l'avantage de ne jamais casser le code existant. Mais l'inconvénient était que toute erreur ou décision imparfaite prise par les créateurs de JavaScript restait bloquée dans le langage pour toujours.

Il en avait été ainsi jusqu'en 2009 lorsque ECMAScript 5 (ES5) est apparu. Il a ajouté de nouvelles fonctionnalités au langage et modifié certaines des fonctionnalités existantes. Pour conserver l'ancien code, la plupart des modifications sont désactivées par défaut. Vous devez les activer explicitement avec une directive spéciale : `"use strict"`.

## "use strict"

La directive ressemble à une chaîne de caractères : `"use strict"` ou `'use strict'`. Lorsqu'il se trouve en haut du script, l'ensemble du script fonctionne de manière "moderne".

Par exemple

```js
"use strict";

// ce code fonctionne de manière moderne
...
```

Nous allons bientôt apprendre les fonctions (un moyen de regrouper les commandes). À l'avenir, notons que `"use strict"` peut être placé au début du corps de la fonction. Faire cela active le mode strict dans cette fonction uniquement. Mais d'habitude, les gens l'utilisent pour tout le script.


````warn header="Assurez-vous que \"use strict\" est tout en haut"
Assurez-vous que `"use strict"` est en haut du script, sinon le mode strict peut ne pas être activé.

Il n'y a pas de mode strict ici :

```js no-strict
alert("some code");
// "use strict" ci-dessous est ignoré, il doit être en haut

"use strict";

// le mode strict n'est pas activé
```

Seuls les commentaires peuvent apparaître avant `"use strict"`.
````

```warn header="Il n'y a aucun moyen d'annuler `use strict`"
Il n'y a pas de directive `"no use strict"` ou similaire, qui réactiverait l'ancien comportement.

Une fois que nous entrons dans le mode strict, il n’y a plus de retour possible.
```
## Console du Navigateur

Pour l’avenir, lorsque vous utilisez une console de navigation pour tester des fonctionnalités, veuillez noter qu’elle n’utilise pas `use strict` par défaut.

Lorsque vous utilisez une [console de développement](info:devtools) pour exécuter du code, veuillez noter qu'elle n'utilise pas `use strict` par défaut.

Parfois, lorsque `use strict` fait une différence, vous obtenez des résultats incorrects.

Alors, comment utiliser `use strict` dans la console ?

D'abord, vous pouvez essayer d'appuyer sur `key:Shift+Enter` pour saisir plusieurs lignes et mettre `use strict` en haut comme cela :

```js
'use strict'; <Shift+Enter for a newline>
//  ...votre code
<Enter to run>
```

Cela fonctionne dans la plupart des navigateurs, à savoir Firefox et Chrome.

Si ce n’est pas le cas, comme par exemple dans un ancien navigateur, le moyen le plus fiable d’assurer `use strict` serait d'encapsuler le code dans la console comme ceci :

```js
(function() {
  'use strict';

  // ... votre code ici ...
})()
```

## Devrions-nous activer "use strict" ?

La question peut sembler évidente, mais ce n'est pas le cas.

On pourrait recommander de démarrer les scripts avec `"use strict"` ... Mais vous savez ce qui est cool ?

Le JavaScript moderne prend en charge les "classes" et les "modules" -- des structures de langage avancées (nous y arriverons sûrement), qui activent automatiquement `use strict`. Nous n'avons donc pas besoin d'ajouter la directive `"use strict"` si nous les utilisons.

**Donc, pour l'instant `"use strict";` est un invité bienvenu en haut de vos scripts. Plus tard, lorsque votre code est entièrement dans des classes et des modules, vous pouvez l'omettre.**

A partir de maintenant, nous devons connaître `use strict` en général.

Dans les chapitres suivants, au fur et à mesure que nous apprendrons les fonctionnalités du langage, nous verrons les différences entre les modes strict et anciens modes. Heureusement, il n'y en a pas beaucoup et ils améliorent en fait nos vies.

Tous les exemples de ce tutoriel supposent le mode strict, sauf indication contraire (très rarement).


================================================
FILE: 1-js/02-first-steps/04-variables/1-hello-variables/solution.md
================================================
Dans le code ci-dessous, chaque ligne correspond à l'élément de la liste des tâches.

```js run
let admin, name; // on peut déclarer deux variables à la fois

name = "John";

admin = name;

alert( admin ); // "John"
```



================================================
FILE: 1-js/02-first-steps/04-variables/1-hello-variables/task.md
================================================
importance: 2

---

# Travailler avec des variables

1. Déclarez deux variables : `admin` and `name`.
2. Assignez la valeur `"John"` à `name`.
3. Copiez la valeur de `name` à `admin`.
4. Afficher la valeur de `admin` en utilisant `alert` (devrait afficher "John").


================================================
FILE: 1-js/02-first-steps/04-variables/2-declare-variables/solution.md
================================================
## La variable pour notre planète

C’est simple :

```js
let notrePlanete = "Terre";
```

Notez que nous pourrions utiliser un nom `planète` plus court, mais la planète à laquelle il fait référence pourrait ne pas être évidente. C’est bien d’être plus verbeux. Au moins jusqu'à ce que la variable n'estPasTropLongue.

## le nom du visiteur actuel

```js
let currentUserName = "John";
```

Encore une fois, nous pourrions réduire cela à `userName` si nous savons avec certitude que c'est bien l'utilisateur actuel.

Les éditeurs modernes et la saisie semi-automatique facilitent l'écriture de noms de variables longs. Ne vous en privez pas. Un nom avec 3 mots est bien.

Et si votre éditeur ne dispose pas de l'autocomplétion correcte, [obtenez-en un](/editors).


================================================
FILE: 1-js/02-first-steps/04-variables/2-declare-variables/task.md
================================================
importance: 3

---

# Assigner le bon nom

1. Créez la variable avec le nom de notre planète. Comment nommeriez-vous une telle variable ?
2. Créez la variable pour stocker le nom du visiteur actuel. Comment nommeriez-vous cette variable ?

================================================
FILE: 1-js/02-first-steps/04-variables/3-uppercast-constant/solution.md
================================================
Nous utilisons généralement des majuscules pour les constantes "codées en dur". Ou, en d'autres termes, lorsque la valeur est connue avant exécution et directement écrite dans le code.

Dans ce code, `birthday` correspond exactement à cela. Nous pourrions donc utiliser les majuscules pour cela.

En revanche, `age` est évalué en exécution. Aujourd'hui, nous avons un âge, un an après, nous en aurons un autre. C'est constant dans le sens où cela ne change pas avec l'exécution du code. Mais c’est un peu "moins constant" que `birthday` : il est calculé, nous devrions donc garder les minuscules pour cela.


================================================
FILE: 1-js/02-first-steps/04-variables/3-uppercast-constant/task.md
================================================
importance: 4

---

# Constante en majuscule ?

Examinez le code suivant :

```js
const birthday = '18.04.1982';

const age = someCode(birthday);
```

Ici, nous avons une constante `birthday` pour la date de naissance, ainsi que la constante `age`.

L'`age` est calculé à partir de `birthday` en utilisant `someCode()`, ce qui signifie un appel de fonction que nous n'avons pas encore expliqué (nous le ferons bientôt !), mais les détails n'ont pas d'importance ici, le fait est que l'`age` est calculé d'une manière ou d'une autre en fonction de la date de naissance `birthday`.

Serait-il juste d'utiliser des majuscules pour `birthday`? Pour `age`? Ou même pour les deux ?

```js
const BIRTHDAY = '18.04.1982'; // mettre l'anniversaire en majuscule ?

const AGE = someCode(BIRTHDAY); // mettre l'âge en majuscule ?
```


================================================
FILE: 1-js/02-first-steps/04-variables/article.md
================================================
# Les variables

La plupart du temps, une application JavaScript doit utiliser des informations. Voici 2 exemples :
1. Une boutique en ligne - les informations peuvent inclure des articles vendus et un panier d'achat. 
2. Une application de chat - les informations peuvent inclure des utilisateurs, des messages et bien plus encore.

Les variables sont utilisées pour stocker ces informations.

## Une variable

Une [variable](https://fr.wikipedia.org/wiki/Variable_(informatique)) est un "stockage nommé" pour les données. Nous pouvons utiliser des variables pour stocker des goodies, des visiteurs et d'autres données.

Pour créer une variable en JavaScript, nous devons utiliser le mot-clé `let`.

L'instruction ci-dessous crée (autrement dit: *déclare*) une variable avec le nom "message" :

```js
let message;
```

Maintenant, nous pouvons y mettre des données en utilisant l'opérateur d'affectation `=` :

```js
let message;

*!*
message = 'Hello'; // stocke la chaîne de caractères 'Hello' dans la variable nommée message
*/!*
```

La chaîne de caractères est maintenant enregistrée dans la zone de mémoire associée à la variable. Nous pouvons y accéder en utilisant le nom de la variable :

```js run
let message;
message = 'Hello!';

*!*
alert(message); // affiche le contenu de la variable
*/!*
```

Pour être concis, nous pouvons fusionner la déclaration et l'affectation de variables en une seule ligne :

```js run
let message = 'Hello!'; // définir la variable et assigner la valeur

alert(message); // Hello!
```

Nous pouvons également déclarer plusieurs variables sur une seule ligne :

```js no-beautify
let user = 'John', age = 25, message = 'Hello';
```

Cela peut sembler plus court, mais ce n'est pas recommandé. Pour une meilleure lisibilité, veuillez utiliser une seule ligne par variable.

La variante multiligne est un peu plus longue, mais plus facile à lire :

```js
let user = 'John';
let age = 25;
let message = 'Hello';
```

Certaines personnes définissent également plusieurs variables dans ce style multiligne :

```js no-beautify
let user = 'John',
  age = 25,
  message = 'Hello';
```

... Ou même dans le style "virgule première" :

```js no-beautify
let user = 'John'
  , age = 25
  , message = 'Hello';
```

Techniquement, toutes ces variantes font la même chose. C'est donc une question de goût personnel et d'esthétique.

````smart header="`var` au lieu de `let`"
Dans les anciens scripts, vous pouvez également trouver un autre mot-clé : `var` au lieu de `let` :

```js
*!*var*/!* message = 'Hello';
```

Le mot-clé `var` est *presque* identique à `let`. Il déclare également une variable, mais d'une manière légèrement différente, à la mode "old school".

Il y a des différences subtiles entre `let` et `var`, mais elles n'ont pas encore d'importance pour nous. Nous les couvrirons en détails plus tard, dans le chapitre <info:var>.
````

## Une analogie avec la vie réelle

Nous pouvons facilement saisir le concept d'une "variable" si nous l'imaginons comme une "boîte" pour les données, avec un autocollant portant un nom unique.

Par exemple, la variable message peut être imaginée comme une boîte étiquetée "message" avec la valeur "Hello!" à l'intérieur :

![](variable.svg)

Nous pouvons mettre n'importe quelle valeur dans la boîte.

On peut aussi le changer autant de fois qu'on veut :

```js run
let message;

message = 'Hello!';

message = 'World!'; // valeur changée

alert(message);
```

Lorsque la valeur est modifiée, les anciennes données sont supprimées de la variable :

![](variable-change.svg)

Nous pouvons également déclarer deux variables et copier des données de l'une à l'autre.

```js run
let hello = 'Hello world!';

let message;

*!*
// copier 'Hello world' de hello vers message
message = hello;
*/!*

// maintenant les deux variables contiennent les mêmes données
alert(hello); // Hello world!
alert(message); // Hello world!
```

````warn header="Déclarer deux fois déclenche une erreur"
Une variable ne doit être déclarée qu'une seule fois.

Une déclaration répétée de la même variable est une erreur :

```js run
let message = "This";

// répéter 'let' conduit à une erreur
let message = "That"; // SyntaxError: 'message' has already been declared
```
Donc, nous devrions déclarer une variable une fois et y faire référence sans `let`.
````

```smart header="Langages fonctionnels"
Il peut être intéressant de savoir qu'il existe aussi des langages de [programmation purement fonctionelle](https://fr.wikipedia.org/wiki/Programmation_fonctionnelle), comme [Haskell](https://www.scala-lang.org/) qui interdisent de modifier une valeur de variable.

Dans ce genre de langage, une fois la valeur stockée dans la boîte, elle est là pour toujours. Si nous devons stocker autre chose, le langage nous oblige à créer une nouvelle boîte (déclarer une nouvelle variable). Nous ne pouvons pas réutiliser l’ancienne.

Bien que cela puisse paraître un peu étrange à première vue, ces langages sont tout à fait capables de développements sérieux. Plus que cela, il existe des domaines tels que les calculs parallèles où cette limitation confère certains avantages.
```

## Nom de variable [#variable-naming]

Il existe deux limitations pour un nom de variable en JavaScript :

1. Le nom ne doit contenir que des lettres, des chiffres, des symboles `$` et `_`.
2. Le premier caractère ne doit pas être un chiffre.

Noms valides, par exemple :

```js
let userName;
let test123;
```

Lorsque le nom contient plusieurs mots, le [camelCase](https://fr.wikipedia.org/wiki/Camel_case) est couramment utilisé. C'est-à-dire que les mots se succèdent, chaque mot à l'exception du premier commence par une majuscule : `monTresLongNom`.

Ce qui est intéressant -- le signe dollar `'$'` et l'underscore `'_'` peuvent également être utilisé dans les noms. Ce sont des symboles réguliers, tout comme les lettres, sans aucune signification particulière.

Ces noms sont valides :

```js run untrusted
let $ = 1; // déclarer une variable avec le nom "$"
let _ = 2; // et maintenant une variable avec le nom "_"

alert($ + _); // 3
```

Exemples de noms de variables incorrects :

```js no-beautify
let 1a; // ne peut pas commencer avec un chiffre

let mon-nom; // un trait d'union '-' n'est pas autorisé dans le nom
```

```smart header="La casse est importante"
Des variables nommées `apple` et `APPLE` sont deux variables différentes.
```

````smart header="Les lettres non latines sont autorisées mais non recommandées"
Il est possible d'utiliser n'importe quelle langue, y compris les lettres cyrilliques, les logogrammes chinois, etc., comme ceci :

```js
let имя = '...';
let 我 = '...';
```

Techniquement, il n'y a pas d'erreur ici, ces noms sont autorisés, mais il existe une convention internationale d'utiliser l'anglais dans les noms de variables. Même si nous écrivons un petit script, sa vie peut être longue. Les personnes d'autres pays peuvent avoir besoin de les lire quelque temps.

````

````warn header="Noms réservés"
Il existe une [liste de mots réservés](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Grammaire_lexicale#Mots-cl%C3%A9s), qui ne peuvent pas être utilisés comme noms de variables, car ils sont utilisés par le langage lui-même.

Par exemple, les mots `let`, `class`, `return`, `function` sont réservés.

Le code ci-dessous donne une erreur de syntaxe :

```js run no-beautify
let let = 5; // impossible de nommer une variable "let", erreur!
let return = 5; // on ne peut pas la nommer "return" aussi, erreur!
```
````

````warn header="Une affectation sans : `use strict`"

Normalement, nous devons définir une variable avant de l'utiliser. Mais jadis, il était techniquement possible de créer une variable par simple affectation de la valeur, sans `let`. Cela fonctionne toujours maintenant si nous ne mettons pas `use strict`. Le comportement est conservé pour la compatibilité avec les anciens scripts.

```js run no-strict
// note : pas de "use strict" dans cet exemple

num = 5; // la variable "num" est créée si elle n'existe pas

alert(num); // 5
```

C’est une mauvaise pratique, cela donne une erreur en mode strict :

```js run untrusted
"use strict";

*!*
num = 5; // erreur: num n'est pas défini
*/!*
```
````


## Les Constantes

Pour déclarer une constante (non changeante), on peut utiliser `const` plutôt que `let` :

```js
const myBirthday = '18.04.1982';
```

Les variables déclarées à l'aide de `const` sont appelées "constantes". Elles ne peuvent pas être réassignées. Une tentative de le faire provoquerait une erreur :

```js run
const myBirthday = '18.04.1982';

myBirthday = '01.01.2001'; // erreur, ne peut pas réaffecter la constante !
```

Lorsqu'un programmeur est certain que la variable ne doit jamais changer, il peut utiliser `const` pour le garantir et également le montrer clairement à tout le monde.


### Les constantes en majuscules

Il existe une pratique répandue d’utiliser des constantes comme alias pour des valeurs difficiles à mémoriser, qui sont connues avant leur exécution.

Ces constantes sont nommées en utilisant des majuscules et des underscores.

Par exemple, créons des constantes pour les couleurs au format dit "web" (hexadécimal) :

```js run
const COLOR_RED = "#F00";
const COLOR_GREEN = "#0F0";
const COLOR_BLUE = "#00F";
const COLOR_ORANGE = "#FF7F00";

// ... quand il faut choisir une couleur
let color = COLOR_ORANGE;
alert(color); // #FF7F00
```

Bénéfices:

- `COLOR_ORANGE` est beaucoup plus facile à retenir que `"#FF7F00"`.
- Il est beaucoup plus facile de mal saisir `"#FF7F00"` que `COLOR_ORANGE`.
- En lisant le code, `COLOR_ORANGE` est beaucoup plus significatif que `#FF7F00`.

Quand devrions-nous utiliser les majuscules pour une constante et quand devrions-nous les nommer normalement ? Soyons clairs.

Être une "constante" signifie simplement que la valeur ne change jamais. Mais il existe des constantes connues avant l'exécution (comme une valeur hexadécimale pour le rouge), et il y a celles qui sont *calculées* en temps réel, pendant l'exécution, mais ne changent pas après l'affectation.

Par exemple :

```js
const pageLoadTime = /* temps pris par une page Web pour charger */;
```

La valeur de `pageLoadTime` n’est pas connue avant le chargement de la page, elle est donc nommée normalement. Mais cela reste une constante, car elle ne change pas après l’affectation.

En d'autres termes, les constantes nommées en majuscules ne sont utilisées que comme alias pour les valeurs "codées en dur".

## Nommez les choses correctement

En parlant de variables, il y a une autre chose extrêmement importante.

Un nom de variable doit avoir une signification claire et évidente, décrivant les données qu'elle stocke.

Le nommage de variables est l’une des compétences les plus importantes et les plus complexes de la programmation. Un rapide coup d’œil sur les noms de variables peut révéler quel code est écrit par un débutant et par un développeur expérimenté.

Dans un projet réel, la majeure partie du temps est consacrée à la modification et à l'extension de la base de code existant, plutôt que d'écrire quelque chose de complètement séparé de zéro. Et lorsque nous revenons au code après un certain temps, il est beaucoup plus facile de trouver des informations bien étiquetées. Ou, en d'autres termes, lorsque les variables ont de bons noms.

Veuillez prendre le temps de réfléchir à un nom pertinent pour une variable avant de la déclarer. Cela vous facilitera énormément la vie.

Voici quelques règles à suivre :

- Utilisez des noms lisibles par des humains comme `userName` ou `shoppingCart`.
- Restez à l’écart des abréviations ou des noms courts tels que `a`, `b`, `c`, à moins que vous ne sachiez vraiment ce que vous faites.
- Faire en sorte que le nom soit le plus descriptif et concis possible. Des exemples de noms incorrects sont `data` et `value`. Un tel nom ne dit rien. C’est tout à fait acceptable de les utiliser si le contexte dans lequel les données ou les valeurs sont impliquées est particulièrement évident.
- S'accorder avec son équipe (et soi-même) sur les termes utilisés. Si un visiteur du site est appelé un "utilisateur", nous devrions nommer les variables connexes comme `currentUser` ou `newUser`, mais non `currentVisitor` ou encore `newManInTown`.

Cela semble simple ? En effet, ça l'est, mais la création de noms descriptifs et concis dans la pratique ne l'est pas. Fonce.

```smart header="Réutiliser ou créer ?"
Une dernière note. Certains programmeurs paresseux, au lieu de déclarer une nouvelle variable, ont tendance à réutiliser ceux qui existent déjà.

En conséquence, la variable est comme une boîte où les gens jettent des choses différentes sans changer l'autocollant. Qu'est-ce qu'il y a dedans maintenant ? Qui sait … Nous devons creuser et vérifier.

Un tel programmeur économise un peu sur la déclaration de variable, mais perd dix fois plus sur le débogage du code.

Une variable supplémentaire est une bonne chose, cela ne complique pas le code, bien au contraire.

Les minificateurs et navigateurs modernes optimisent suffisamment le code pour ne pas créer de problèmes de performances. L'utilisation de différentes variables pour différentes valeurs peut même aider le moteur à optimiser.
```

## Résumé

Nous pouvons déclarer des variables pour stocker des données. Cela peut être fait en utilisant `var` ou `let` ou `const`.

- `let` -- est une déclaration de variable moderne.
- `var` -- est une déclaration de variable old-school. Normalement, nous ne l’utilisons pas du tout, mais nous couvrirons les différences subtiles par rapport à `let` dans le chapitre <info:var>, juste au cas où vous en auriez besoin.
- `const` -- est équivalent à `let`, mais la valeur de la variable ne peut pas être modifiée.

Les variables doivent être nommées d’une manière qui nous permet de comprendre facilement ce qui est à l’intérieur.


================================================
FILE: 1-js/02-first-steps/05-types/1-string-quotes/solution.md
================================================

Backticks incorpore l'expression à l'intérieur de `${...}` dans la chaîne de caractères.

```js run
let name = "Ilya";

// l'expression est un numéro 1
alert( `hello ${1}` ); // hello 1

// l'expression est une chaîne de caractères "name"
alert( `hello ${"name"}` ); // hello name

// l'expression est une variable, il intègre son contenu
alert( `hello ${name}` ); // hello Ilya
```


================================================
FILE: 1-js/02-first-steps/05-types/1-string-quotes/task.md
================================================
importance: 5

---

# String quotes

Quelle est la sortie du script ?

```js
let name = "Ilya";

alert( `hello ${1}` ); // ?

alert( `hello ${"name"}` ); // ?

alert( `hello ${name}` ); // ?
```


================================================
FILE: 1-js/02-first-steps/05-types/article.md
================================================
# Les types de données

Une valeur en JavaScript est toujours d'un certain type. Par exemple, une chaîne de caractères ou un nombre.

Il existe huit types de données de base en JavaScript. Ici, nous les couvrirons en général et dans les prochains chapitres, nous parlerons de chacun d'eux en détail.

Nous pouvons mettre n'importe quel type dans une variable. Par exemple, une variable peut à un moment être une chaîne de caractères puis stocker un nombre :

```js
// pas d'erreur
let message = "hello";
message = 123456;
```

Les langages de programmation qui permettent de telles choses sont appelés "typés dynamiquement", ce qui signifie qu'il existe des types de données, mais que les variables ne sont liées à aucun d'entre eux.


## Number

```js
let n = 123;
n = 12.345;
```

Le type *number* sert à la fois à des nombres entiers et à des nombres à virgule flottante.

Il existe de nombreuses opérations pour les nombres, par ex. multiplication `*`, division `/`, addition `+`, soustraction `-` et ainsi de suite.

Outre les nombres réguliers, il existe des "valeurs numériques spéciales" qui appartiennent également à ce type: `Infinity`, `-Infinity` et `NaN`.

- `Infinity` représente l'[Infini](https://fr.wikipedia.org/wiki/Infini) ∞ mathématique. C'est une valeur spéciale qui est plus grande que n'importe quel nombre.

    Nous pouvons l'obtenir à la suite d'une division par zéro :

    ```js run
    alert( 1 / 0 ); // Infinity
    ```

    Ou mentionnez-le simplement dans le code directement :

    ```js run
    alert( Infinity ); // Infinity
    ```

- `NaN` représente une erreur de calcul. C'est le résultat d'une opération mathématique incorrecte ou non définie, par exemple :

    ```js run
    alert( "pas un nombre" / 2 ); // NaN, une telle division est erronée
    ```

    `NaN` est contagieux. Toute autre opération sur `NaN` donnerait un `NaN` :

    ```js run
    alert( NaN + 1 ); // NaN
    alert( 3 * NaN ); // NaN
    alert( "not a number" / 2 - 1 ); // NaN
    ```

    Donc, s'il y a `NaN` quelque part dans une expression mathématique, il se propage à l'ensemble du résultat (il n'y a qu'une seule exception : `NaN ** 0` vaut `1`).

```smart header="Les opérations mathématiques sont sûres"
Faire des maths est sans danger en JavaScript. Nous pouvons faire n'importe quoi : diviser par zéro, traiter les chaînes non numériques comme des nombres, etc.

Le script ne s'arrêtera jamais avec une erreur fatale ("die"). Au pire, nous aurons `NaN` comme résultat.
```

Les valeurs numériques spéciales appartiennent formellement au type "number". Bien sûr, ce ne sont pas des nombres au sens commun de ce mot.

Nous allons en voir plus sur le travail avec les nombres dans le chapitre <info:number>.

## BigInt [#bigint-type]

En JavaScript, le type "number" ne peut pas représenter des valeurs entières supérieures à <code>(2<sup>53</sup>-1)</code> (c'est `9007199254740991`), ou moins que <code>-(2<sup>53</sup>-1)</code> pour les chiffres négatifs. C'est une limitation technique causée par leur représentation interne.

Pour être vraiment précis, le type "number" peut stocker des entiers plus grands (jusqu'à <code>1.7976931348623157 * 10<sup>308</sup></code>), mais en dehors de la plage d'entiers sûrs <code>±(2 <sup>53</sup>-1)</code> il y aura une erreur de précision, car tous les chiffres ne rentrent pas dans le stockage 64 bits fixe. Ainsi, une valeur "approximative" peut être stockée.

Par exemple, ces deux nombres (juste au-dessus de la plage de sécurité) sont identiques :

```js
console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992
```

Ainsi, tous les entiers impairs supérieurs à <code>(2<sup>53</sup>-1)</code> ne peuvent pas du tout être stockés dans le type "number".

Dans la plupart des cas, la plage <code>±(2<sup>53</sup>-1)</code> est tout à fait suffisante, mais parfois nous avons besoin de toute la plage de très grands nombres entiers, par ex. pour la cryptographie ou les horodatages de précision à la microseconde.

`BigInt` a récemment été ajouté au langage pour représenter des entiers de longueur arbitraire.

Une valeur `BigInt` est créé en ajoutant `n` à la fin d'un entier :

```js
// le "n" à la fin signifie que c'est un BigInt
const bigInt = 1234567890123456789012345678901234567890n;
```

Comme les chiffres `BigInt` sont rarement nécessaires, nous leur avons consacré un chapitre dédié <info:bigint>. Lisez-le lorsque vous avez besoin d'aussi gros chiffres.

```smart header="Problèmes de compatibilité"
À l'heure actuelle, `BigInt` est pris en charge dans Firefox/Chrome/Edge/Safari, mais pas dans IE.
```

You can check [*MDN* BigInt compatibility table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) to know which versions of a browser are supported.

## String

Une chaîne de caractères en JavaScript doit être entre guillemets.

```js
let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed another ${str}`;
```

En JavaScript, il existe 3 types de guillemets.

1. Double quotes: `"Hello"`.
2. Single quotes: `'Hello'`.
3. Backticks: <code>&#96;Hello&#96;</code>.

Les guillemets simples et doubles sont des guillemets "simples". Il n'y a pratiquement pas de différence entre eux en JavaScript.

Les backticks sont des guillemets "à fonctionnalité étendue". Ils nous permettent d’intégrer des variables et des expressions dans une chaîne en les encapsulant dans `${…}`, par exemple :

```js run
let name = "John";

// une variable encapsulée
alert( `Hello, *!*${name}*/!*!` ); // Hello, John!

// une expression encapsulée
alert( `the result is *!*${1 + 2}*/!*` ); // le résultat est 3
```

L'expression à l'intérieur de `${…}` est évaluée et le résultat devient une partie de la chaîne. On peut y mettre n'importe quoi : une variable comme `name` ou une expression arithmétique comme `1 + 2` ou quelque chose de plus complexe.

Veuillez noter que cela ne peut être fait que dans les backticks. Les autres guillemets ne permettent pas une telle intégration !

```js run
alert( "the result is ${1 + 2}" ); // le résultat est ${1 + 2} (les doubles quotes ne font rien)
```

Nous couvrirons les chaînes de caractères plus en détails dans le chapitre <info:string>.

```smart header="Il n'y a pas de type *character*."
Dans certains langages, il existe un type spécial "character" pour un seul caractère. Par exemple, en langage C et en Java, il s'agit de "char".

En JavaScript, ce type n'existe pas. Il n'y a qu'un seul type: `string`. Une chaîne de caractères peut être composée de zéro caractère (être vide), d'un caractère ou de plusieurs d'entre eux.
```

## Boolean (type logique)

Le type booléen n'a que deux valeurs: `true` et `false`.

Ce type est couramment utilisé pour stocker des valeurs oui / non: `true` signifie "oui, correct" et `false` signifie "non, incorrect".

Par exemple :

```js
let nameFieldChecked = true; // oui, le champ de nom est coché
let ageFieldChecked = false; // non, le champ d'âge n'est pas coché
```

Les valeurs booléennes résultent également de comparaisons :

```js run
let isGreater = 4 > 1;

alert( isGreater ); // true (le résultat de la comparaison est "oui")
```

Nous couvrirons plus profondément les booléens plus tard dans le chapitre <info:logical-operators>.

## La valeur "null"

La valeur spéciale `null` n'appartient à aucun type de ceux décrits ci-dessus.

Il forme un type bien distinct qui ne contient que la valeur `null` :

```js
let age = null;
```

En JavaScript, `null` n'est pas une "référence à un objet non existant" ou un "pointeur nul" comme dans d'autres langages.

C’est juste une valeur spéciale qui a le sens de "rien", "vide" ou "valeur inconnue".

Le code ci-dessus indique que l'`age` est inconnu.

## La valeur "undefined"

La valeur spéciale `undefined` se distingue des autres. C'est un type à part entière, comme `null`.

La signification de `undefined` est "la valeur n'est pas attribuée".

Si une variable est déclarée mais non affectée, alors sa valeur est exactement `undefined` :

```js run
let age;

alert(age); // affiche "undefined"
```

Techniquement, il est possible d'affecter explicitement `undefined` à une variable :

```js run
let age = 100;

// change the value to undefined
age = undefined;

alert(age); // "undefined"
```

… Mais il n’est pas recommandé de faire cela. Normalement, nous utilisons `null` pour assigner une valeur "vide" ou "inconnue" à une variable, tandis que `undefined` est réservé comme valeur initiale par défaut pour les éléments non attribués.

## Objects et Symbols

Le type `object` est spécial.

Tous les autres types sont appelés "primitifs", car leurs valeurs ne peuvent contenir qu’une seule chose (que ce soit une chaîne de caractères, un nombre ou autre). À contrario, les objets servent à stocker des collections de données et des entités plus complexes.

Étant aussi important, les objets méritent un traitement spécial. Nous les traiterons plus tard dans le chapitre <info:object>, après en savoir plus sur les primitifs.

Le type `symbol` est utilisé pour créer des identificateurs uniques pour les objets. Nous devons le mentionner ici par souci d'exhaustivité, mais nous allons le voir en détails après avoir étudié les objets.

## L'opérateur typeof [#type-typeof]

L'opérateur `typeof` renvoie le type de l'opérande. Il est utile lorsqu'on souhaite traiter différemment les valeurs de différents types ou de faire une vérification rapide.

L'appel `typeof x` renvoie une chaîne de caractères avec le nom du type :

```js
typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol"

*!*
typeof Math // "object"  (1)
*/!*

*!*
typeof null // "object"  (2)
*/!*

*!*
typeof alert // "function"  (3)
*/!*
```

Les trois dernières lignes peuvent nécessiter des explications supplémentaires :

1. `Math` est un objet interne au langage qui fournit des opérations mathématiques. Nous allons l'apprendre dans le chapitre <info:number>. Ici, il sert uniquement comme exemple d'un objet.
2. Le résultat de `typeof null` est `"object"`. C'est une erreur officiellement reconnue dans `typeof`, datant des premiers jours de JavaScript et conservée pour compatibilité. Bien sûr, `null` n'est pas un objet. C'est une valeur spéciale avec un type distinct qui lui est propre. Le comportement de `typeof` est incorrect ici.
3. Le résultat de `typeof alert` est `"function"`, car `alert` est une fonction. Nous étudierons les fonctions dans les chapitres suivants, et nous verrons qu’il n’y a pas de type "fonction" en JavaScript. Les fonctions appartiennent au type `object` mais `typeof` les traite différemment en retournant `"function"`. Cela vient également des débuts de JavaScript. Techniquement ce n’est pas tout à fait correct, mais très pratique à l'usage.

```smart header="La syntaxe `typeof(x)`"
Vous pouvez également rencontrer une autre syntaxe : `typeof(x)`. C'est la même chose que `typeof x`.

Pour être clair : `typeof` est un opérateur, pas une fonction. Les parenthèses ici ne font pas partie de `typeof`. C'est le genre de parenthèses utilisées pour le regroupement mathématique.

Habituellement, ces parenthèses contiennent une expression mathématique, telle que `(2 + 2)`, mais ici elles ne contiennent qu'un seul argument `(x)`. Syntaxiquement, ils permettent d'éviter un espace entre l'opérateur `typeof` et son argument, et certains aiment ça.

Certaines personnes préfèrent `typeof(x)`, bien que la syntaxe `typeof x` soit beaucoup plus courante.
```

## Résumé

Il existe 8 types de données de base en JavaScript.

- Sept types de données primitifs :
    - `number` pour les nombres de toute nature : entier ou virgule flottante, les nombres entiers sont limités à <code>±(2<sup>53</sup>-1)</code>.
    - `bigint` pour des nombres entiers de longueur arbitraire.
    - `string` pour les chaînes de caractères. Une chaîne de caractères peut avoir zéro ou plusieurs caractères, il n'y a pas de type à caractère unique distinct.
    - `boolean` pour `true`/`false` (vrai/faux).
    - `null` pour les valeurs inconnues - un type autonome qui a une seule valeur `null`.
    - `undefined` pour les valeurs non attribuées - un type autonome avec une valeur unique `undefined`.
    - `symbol` pour les identifiants uniques.
- Et un type de données non primitif :
    - `object` pour des structures de données plus complexes.

L'opérateur `typeof` nous permet de voir quel type est stocké dans la variable.

- Généralement utilisé sous cette forme `typeof x`, mais `typeof(x)` est également possible.
- Renvoie une chaîne de caractères avec le nom du type, comme `"string"`.
- Pour `null` il renvoie `"object"` -- C’est une erreur dans le langage, ce n’est pas un objet en fait.

Dans les chapitres suivants, nous nous concentrerons sur les valeurs primitives et une fois que nous les connaîtrons, nous passerons aux objets.


================================================
FILE: 1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/solution.md
================================================
JavaScript-code:

```js demo run
let name = prompt("What is your name?", "");
alert(name);
```

La page complète :

```html
<!DOCTYPE html>
<html>
<body>

  <script>
    'use strict';

    let name = prompt("What is your name?", "");
    alert(name);
  </script>

</body>
</html>
```


================================================
FILE: 1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/task.md
================================================
importance: 4

---

# Une simple page

Créez une page Web qui demande un nom et l'affiche

[demo]


================================================
FILE: 1-js/02-first-steps/06-alert-prompt-confirm/article.md
================================================
# Interaction: alert, prompt, confirm

Comme nous allons utiliser le navigateur comme environnement de démonstration, voyons quelques fonctions pour interagir avec l'utilisateur : `alert`, `prompt` et `confirm`.

## alert

Celui-ci, nous l'avons déjà vu. Il affiche un message et attend que l'utilisateur appuie sur "OK".

Par exemple :

```js run
alert("Hello");
```

La mini-fenêtre avec le message s'appelle une *fenêtre modale*. Le mot "modal" signifie que le visiteur ne peut pas interagir avec le reste de la page, appuyer sur d'autres boutons, etc., tant qu'il n'a pas traité la fenêtre. Dans ce cas -- jusqu'à ce qu'ils appuient sur "OK".

## prompt

La fonction `prompt` accepte deux arguments :

```js no-beautify
result = prompt(title, [default]);
```

Elle affiche une fenêtre modale avec un message texte, un champ de saisie pour le visiteur et les boutons OK/Annuler.

`title`
: Le texte à afficher au visiteur.

`default`
: Un deuxième paramètre facultatif, la valeur initiale du champ d'entrée.

```smart header="Les crochets dans la syntaxe `[...]`"
Les crochets autour de `default` dans la syntaxe ci-dessus indiquent que le paramètre est facultatif, non requis.
```

Le visiteur peut taper quelque chose dans le champ de saisie d'invite et appuyer sur OK. Ensuite, nous obtenons ce texte dans le `result`. Ou ils peuvent annuler l'entrée en appuyant sur Annuler ou en appuyant sur la touche `key:Esc`, puis nous obtenons `null` comme `result`.

L'appel à `prompt` renvoie le texte du champ de saisie ou `null` si l'entrée a été annulée.

Par exemple :

```js run
let age = prompt('How old are you?', 100);

alert(`You are ${age} years old!`); // You are 100 years old!
```

````warn header="Dans IE : fournissez toujours un `default`"
Le second paramètre est facultatif, mais si nous ne le fournissons pas, Internet Explorer insérera le texte `"undefined"` dans l'invite.

Exécutez ce code dans Internet Explorer pour voir :

```js run
let test = prompt("Test");
```

Donc, pour que les invites semblent bonnes dans IE, nous vous recommandons de toujours fournir le deuxième argument :

```js run
let test = prompt("Test", ''); // <-- pour IE
```
````

## confirm

La syntaxe :

```js
result = confirm(question);
```

La fonction `confirm` affiche une fenêtre modale avec une `question` et deux boutons : OK et Annuler.

Le résultat est `true` si vous appuyez sur OK et `false` dans le cas contraire.

Par exemple :

```js run
let isBoss = confirm("Are you the boss?");

alert( isBoss ); // true si OK est pressé
```

## Résumé

Nous avons couvert 3 fonctions spécifiques au navigateur pour interagir avec les visiteurs :

`alert`
: affiche un message.

`prompt`
: affiche un message demandant à l'utilisateur de saisir du texte. Il renvoie le texte ou `null`, si vous cliquez sur le bouton Annuler ou sur `key:Esc`.

`confirm`
: affiche un message et attend que l'utilisateur appuie sur "OK" ou "Annuler". Il retourne `true` pour OK et `false` pour Annuler/`key:Esc`.

Toutes ces méthodes sont modales: elles suspendent l'exécution du script et ne permettent pas au visiteur d'interagir avec le reste de la page tant que la fenêtre n'a pas été fermée.

Il existe deux limitations partagées par toutes les méthodes ci-dessus :

1. L'emplacement exact de la fenêtre modale est déterminé par le navigateur. Habituellement, c'est au centre.
2. L'aspect exact de la fenêtre dépend également du navigateur. Nous ne pouvons pas le modifier.

C'est le prix de la simplicité. Il existe d'autres moyens d'afficher des fenêtres plus jolies et une interaction plus riche avec le visiteur, mais si l'aspect graphique n'ont pas beaucoup d'importance, ces méthodes fonctionnent très bien.


================================================
FILE: 1-js/02-first-steps/07-type-conversions/article.md
================================================
# Les conversions de types

La plupart du temps, les opérateurs et les fonctions convertissent automatiquement les valeurs qui leur sont attribuées dans le bon type.

Par exemple, `alert` convertit automatiquement toute valeur en chaîne de caractères pour l'afficher. Les opérations mathématiques convertissent les valeurs en nombres.

Il y a aussi des cas où nous devons convertir explicitement une valeur pour corriger les choses.

```smart header="On ne parle pas encore des objets"
Dans ce chapitre, nous ne couvrons pas encore les objets. Ici, nous étudions d'abord les primitives. 

Plus tard, après avoir appris les objets, nous verrons comment la conversion d’objets fonctionne dans le chapitre <info:object-toprimitive>.
```

## String Conversion

La conversion `String` se produit lorsque nous avons besoin de la forme chaîne de caractères d'une valeur.

Par exemple, `alert(value)`  le fait pour afficher la valeur.

Nous pouvons également utiliser un appel de fonction `String(value)` pour ça :

```js run
let value = true;
alert(typeof value); // boolean

*!*
value = String(value); // maintenant la valeur est une chaîne de caractères "true"
alert(typeof value); // string
*/!*
```

La conversion `String` est assez évidente. Un `false` devient `"false"`, `null` devient `"null"` etc.

## Numeric Conversion

La conversion numérique dans les fonctions et expressions mathématiques s'effectue automatiquement.

Par exemple, lorsque la division `/` est appliqué à des non-numéros :

```js run
alert( "6" / "2" ); // 3, les chaînes de caractères sont converties en nombres
```

Nous pouvons utiliser une fonction `Number(value)` pour convertir explicitement une valeur :

```js run
let str = "123";
alert(typeof str); // string

let num = Number(str); // devient un nombre 123

alert(typeof num); // nombre
```

Une conversion explicite est généralement requise lorsque nous lisons une valeur à partir d'une source basée sur des chaînes de caractères, par exemple un champ texte, mais qu'un nombre doit être entré.

Si la chaîne de caractères n'est pas un nombre valide, le résultat de cette conversion est `NaN`, par exemple :

```js run
let age = Number("une chaîne de caractères arbitraire au lieu d'un nombre");

alert(age); // NaN, la conversion a échoué
```

Règles de conversion numériques :

| Valeur                               | Devient ... |
|--------------------------------------|-------------|
| `undefined`                          | `NaN`       |
| `null`                               | `0`         |
| <code>true&nbsp;et&nbsp;false</code> | `1` et `0`  |
| `string`                              | Les espaces blancs du début et de la fin sont supprimés. Ensuite, si la chaîne restante est vide, le résultat est `0`. Sinon, le nombre est «lu» dans la chaîne. Une erreur donne `NaN`.

Exemples:

```js run
alert( Number("   123   ") ); // 123
alert( Number("123z") );      // NaN (erreur de lecture d'un nombre à "z")
alert( Number(true) );        // 1
alert( Number(false) );       // 0
```

Veuillez noter que `null` et `undefined` se comportent différemment ici : `null` devient un zéro, alors qu'`undefined` devient `NaN`.

La plupart des opérateurs mathématiques effectuent également une telle conversion, nous le verrons dans le chapitre suivant.

## Boolean Conversion

La conversion booléenne est la plus simple.

Cela se produit dans les opérations logiques (plus tard, nous nous intéresserons aux tests de condition et à d’autres types de tests), mais nous pouvons également l’effectuer manuellement avec l’appel de `Boolean(value)`.

La règle de conversion :

- Les valeurs qui sont intuitivement "vides", comme `0`, une chaîne de caractères vide, `null`, `undefined` `NaN` deviennent `false`.
- Les autres valeurs deviennent `true`.

Par exemple :

```js run
alert( Boolean(1) ); // true
alert( Boolean(0) ); // false

alert( Boolean("hello") ); // true
alert( Boolean("") ); // false
```

````warn header="Veuillez noter que la chaîne de caractères avec un zero `\"0\"` est `true`"
Certains langages (à savoir PHP) traitent `"0"` comme faux. Mais en JavaScript, une chaîne non vide est toujours `true`.

```js run
alert( Boolean("0") ); // true
alert( Boolean(" ") ); // espaces, également vrai (toute chaîne de caractères non vide est vraie)
```
````

## Résumé

Les  trois conversions de types les plus utilisées sont :  to string, to number et to boolean.

**`La conversion en String`** -- Se produit lorsque nous sortons quelque chose, peut être effectué avec `String(value)`. La conversion en chaîne de caractères est généralement évidente pour les valeurs primitives.

**`La conversion en Number`** -- Se produit dans les opérations mathématiques, peut être effectué avec `Number(value)`.

La conversion vers `number` suit les règles suivantes :

| Valeur                              | Devient ...                                                                                                                               |
|-------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| `undefined`                         | `NaN`                                                                                                                                     |
| `null`                              | `0`                                                                                                                                       |
| <code>true&nbsp;/&nbsp;false</code> | `1 / 0`                                                                                                                                   |
| `string`                            | La chaîne de caractères est lue "tel quel", les espaces des deux côtés sont ignorés. Une chaîne vide devient `0`. Une erreur donne `NaN`. |

**`La conversion en Boolean`** -- Se produit dans des opérations logiques, ou peut être effectué avec `Boolean(value)`.

La conversion vers `boolean` suit les règles suivantes :

| Valeur                                | Devient ... |
|---------------------------------------|-------------|
| `0`, `null`, `undefined`, `NaN`, `""` | `false`     |
| tout autre valeur                     | `true`      |


La plupart de ces règles sont faciles à comprendre et à mémoriser. Les exceptions notables où les gens font généralement des erreurs sont :

- `undefined` est `NaN` en tant que number, non `0`.
- `"0"` et les espaces dans les chaines de caractères comme `"   "` sont "true" en booléen.

Les objets ne sont pas couverts ici, nous y reviendrons plus tard dans le chapitre <info:object-toprimitive> qui est consacré exclusivement aux objets, après avoir appris plus de choses basiques sur JavaScript.


================================================
FILE: 1-js/02-first-steps/08-operators/1-increment-order/solution.md
================================================

La réponse est :

- `a = 2`
- `b = 2`
- `c = 2`
- `d = 1`

```js run no-beautify
let a = 1, b = 1;

alert( ++a ); // 2, la forme préfixe renvoie la nouvelle valeur
alert( b++ ); // 1, la forme postfixe renvoie l'ancienne valeur

alert( a ); // 2, incrémenté une fois
alert( b ); // 2, incrémenté une fois
```



================================================
FILE: 1-js/02-first-steps/08-operators/1-increment-order/task.md
================================================
importance: 5

---

# Les formes postfixes et préfixes

Quelles sont les valeurs finales de toutes les variables `a`, `b`, `c` et `d` après le code ci-dessous ?

```js
let a = 1, b = 1;

let c = ++a; // ?
let d = b++; // ?
```


================================================
FILE: 1-js/02-first-steps/08-operators/2-assignment-result/solution.md
================================================
La réponse est :

- `a = 4` (multiplié par 2)
- `x = 5` (calculé comme 1 + 4)


================================================
FILE: 1-js/02-first-steps/08-operators/2-assignment-result/task.md
================================================
importance: 3

---

# Résultat d'affectation

Quelles sont les valeurs de `a` et `x` après le code ci-dessous ?

```js
let a = 2;

let x = 1 + (a *= 2);
```


================================================
FILE: 1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md
================================================

```js no-beautify
"" + 1 + 0 = "10" // (1)
"" - 1 + 0 = -1 // (2)
true + false = 1
6 / "3" = 2
"2" * "3" = 6
4 + 5 + "px" = "9px"
"$" + 4 + 5 = "$45"
"4" - 2 = 2
"4px" - 2 = NaN
"  -9  " + 5 = "  -9  5" // (3)
"  -9  " - 5 = -14 // (4)
null + 1 = 1 // (5)
undefined + 1 = NaN // (6)
" \t \n" - 2 = -2 // (7)
```

1. L'addition avec une chaîne de caractères `"" + 1` converti `1` vers une chaîne de caractères : `"" + 1 = "1"`, ensuite nous avons `"1" + 0`, la même règle est appliquée.
2. La soustraction `-` (comme la plupart des opérations mathématiques) ne fonctionne qu'avec des nombres, il convertit une chaîne de caractères vide `""` vers `0`.
3. L'addition avec un string ajoute le number `5` au string.
4. La soustraction est toujours convertie en nombres, donc elle fait de `"  -9  "` un number `-9` (en ignorant les espaces qui l'entourent).
5. `null` devient `0` après la conversion numérique.
6. `undefined` devient `NaN` après la conversion numérique.
7. Les caractères d'espacement sont coupés au début et à la fin de la chaîne de caractères lorsque celle-ci est convertie en nombre. Ici toute la chaîne se compose d'espaces, tels que `\t`, `\n` et d'un espace "normal" entre eux. Ainsi, de manière similaire à une chaîne de caractères vide, elle devient `0`.


================================================
FILE: 1-js/02-first-steps/08-operators/3-primitive-conversions-questions/task.md
================================================
importance: 5

---

# Les conversions de type 

Quels sont les résultats de ces expressions ?

```js no-beautify
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
"  -9  " + 5
"  -9  " - 5
null + 1
undefined + 1
" \t \n" - 2
```

Réfléchissez bien, notez et comparez avec la réponse.


================================================
FILE: 1-js/02-first-steps/08-operators/4-fix-prompt/solution.md
================================================
La raison en est que le prompt renvoie l'entrée utilisateur sous forme de chaîne de caractères.

Les variables ont donc respectivement les valeurs `"1"` et `"2"`.

```js run
let a = "1"; // prompt("First number?", 1);
let b = "2"; // prompt("Second number?", 2);

alert(a + b); // 12
```

Ce que nous devons faire est de convertir les chaînes de caractères en nombres avant `+`. Par exemple, en utilisant `Number()` ou en les préfixant avec `+`.

Par exemple, juste avant `prompt` :

```js run
let a = +prompt("First number?", 1);
let b = +prompt("Second number?", 2);

alert(a + b); // 3
```

Ou dans l'`alert`:

```js run
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);

alert(+a + +b); // 3
```

Nous utilisons à la fois unaire et binaire `+` dans le dernier code. Ça a l'air drôle, non ?


================================================
FILE: 1-js/02-first-steps/08-operators/4-fix-prompt/task.md
================================================
importance: 5

---

# Corrigez l'addition

Voici un code qui demande à l'utilisateur deux nombres et affiche leur somme.

Cela ne fonctionne pas correctement. La sortie dans l'exemple ci-dessous est `12` (pour les valeurs d'invite par défaut).

Pourquoi ? Réparez-le. Le résultat doit être `3`.

```js run
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);

alert(a + b); // 12
```


================================================
FILE: 1-js/02-first-steps/08-operators/article.md
================================================
# Opérateurs de base, mathématiques

De nombreux opérateurs nous sont connus de l'école. Ce sont les additions `+`, multiplications `*`, soustractions `-` et ainsi de suite.

Dans ce chapitre, nous nous concentrons sur les aspects qui ne sont pas couverts par l'arithmétique scolaire.

## Termes: "unaire", "binaire", "opérande"

Avant de continuer, saisissons la terminologie commune.

- Un opérande est ce à quoi les opérateurs sont appliqués. Par exemple, dans la multiplication `5 * 2`, il y a deux opérandes : l'opérande gauche est `5` et l'opérande droit est `2`. Parfois, les gens disent "arguments" au lieu de "opérandes".
- Un opérateur est unaire s'il a un seul opérande. Par exemple, la négation unaire `-` inverse le signe du nombre :

    ```js run
    let x = 1;

    *!*
    x = -x;
    */!*
    alert( x ); // -1, le moins unaire a été appliqué
    ```
- Un opérateur est *binaire* s'il a deux opérandes. La même négation existe également dans la forme binaire :

    ```js run no-beautify
    let x = 1, y = 3;
    alert( y - x ); // 2, le moins binaire soustrait des valeurs
    ```

    D'un point de vue formel, dans les exemples ci-dessus, nous avons deux opérateurs différents qui partagent le même symbole : l'opérateur de négation, un opérateur unaire qui inverse le signe, et l'opérateur de soustraction, un opérateur binaire qui soustrait un nombre d'un autre.

## Opérations mathématiques

Les opérations mathématiques suivantes sont supportées :

- Addition `+`,
- Soustraction `-`,
- Multiplication `*`,
- Division `/`,
- Reste `%`,
- Exponentiation `**`.

Les quatre premières sont assez simples, tandis que `%` et `**` nécessitent quelques explications.

### Reste % (Modulo)

L'opérateur reste `%`, malgré son apparence, n'est pas lié aux pourcentages.

Le résultat de `a % b` est le [reste](https://fr.wikipedia.org/wiki/Reste) de la division entière de `a` par `b`.

Par exemple :

```js run

alert( 5 % 2 ); // 1, le reste de 5 divisé par 2
alert( 8 % 3 ); // 2, le reste de 8 divisé par 3
alert( 8 % 4 ); // 0, le reste de 8 divisé par 4

```

### Exponentiation **

L'opérateur d'exponentiation `a ** b` multiplie `a` par lui-même `b` fois.
En mathématiques à l'école, nous écrivons cela a<sup>b</sup>.

Par exemple :

```js run
alert( 2 ** 2 ); // 2² = 4
alert( 2 ** 3 ); // 2³ = 8
alert( 2 ** 4 ); // 2⁴ = 16
```

Tout comme en mathématiques, l'opérateur d'exponentiation est également défini pour les nombres non entiers.

Par exemple, une racine carrée est une exponentiation de `½` :

```js run
alert( 4 ** (1/2) ); // 2 (la puissance de 1/2 équivaut à une racine carrée)
alert( 8 ** (1/3) ); // 2 (la puissance de 1/3 équivaut à une racine cubique)
```


## Concaténation de chaînes de caractères, binaire `+`

Découvrons les fonctionnalités des opérateurs JavaScript qui vont au-delà de l'arithmétique scolaire.

Habituellement, l'opérateur `+` additionne des chiffres.

Mais si le binaire `+` est appliqué aux chaînes de caractères, il les fusionne (concatène) :

```js
let s = "my" + "string";
alert(s); // mystring
```

Notez que si l'un des opérandes est une chaîne de caractères, l'autre est automatiquement converti en chaîne de caractères.

Par exemple :

```js run
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
```

Peu importe que le premier opérande soit une chaîne de caractères ou le second. La règle est simple : si l'un des opérandes est une chaîne de caractères, convertissez l'autre également en une chaîne de caractères.

Cependant, notez que les opérations se déroulent de gauche à droite. S'il y a deux nombres suivis d'une chaîne, les nombres seront ajoutés avant d'être convertis en chaîne :


```js run
alert(2 + 2 + '1' ); // "41" et non "221"
```

Ici, les opérateurs travaillent les uns après les autres. Le premier `+` additionne deux nombres, donc il renvoie `4`, puis le `+` suivant ajoute la chaîne de caractères `1`, donc c'est comme `4 + '1' = 41`.

```js run
alert('1' + 2 + 2); // "122" and not "14"
```
Ici, le premier opérande est une chaîne de caractères, le compilateur traite également les deux autres opérandes comme des chaînes de caractères. Le `2` est concaténé à `'1'`, donc c'est comme `'1'+ 2 = "12"` et `"12" + 2 = "122"`.


Le binaire `+` est le seul opérateur qui prend en charge les chaînes de caractères de cette manière. D'autres opérateurs arithmétiques ne fonctionnent qu'avec des nombres et convertissent toujours leurs opérandes en nombres.

Voici l'exemple pour la soustraction et la division :
```js run
alert( 6 - '2' ); // 4, convertit '2' en nombre
alert( '6' / '2' ); // 3, convertit les deux opérandes en nombres
```

## Conversion numérique, unaire +

Le plus `+` existe sous deux formes. La forme binaire que nous avons utilisée ci-dessus et la forme unaire.

L’unaire plus ou, en d’autres termes, l’opérateur plus `+` appliqué à une seule valeur, ne fait rien avec les nombres, mais si l’opérande n’est pas un nombre, alors il est converti en nombre.

Par exemple :

```js run
// Aucun effet sur les nombres
let x = 1;
alert( +x ); // 1

let y = -2;
alert( +y ); // -2

*!*
// Convertit les non-nombres
alert( +true ); // 1
alert( +"" );   // 0
*/!*
```

En fait, il fait la même chose que `Number(...)`, mais il est plus court.

La nécessité de convertir des chaînes de caractères en nombres est très fréquente. Par exemple, si nous obtenons des valeurs à partir de champs de formulaire HTML, il s’agit généralement de chaînes de caractères. Et si on veut les additionner ?

Le binaire plus les ajouterait comme des chaînes de caractères :

```js run
let apples = "2";
let oranges = "3";

alert( apples + oranges ); // "23", le binaire plus concatène les chaînes de caractères
```

Si nous voulons les traiter comme des nombres, nous devons d'abord les convertir et ensuite seulement nous pouvons les additionner :

```js run
let apples = "2";
let oranges = "3";

*!*
// les deux valeurs converties en nombres avant le binaire plus
alert( +apples + +oranges ); // 5
*/!*

// c'est équivalent à cette variante plus longue
// alert( Number(apples) + Number(oranges) ); // 5
```

Du point de vue du mathématicien, l’abondance des `+` peut sembler étrange. Mais du point de vue du programmeur, il n’y a rien de spécial : les plus unaires sont appliqués en premier, ils convertissent les chaînes de caractères en nombres, puis le plus binaire les additionne.

Pourquoi les plus unaires sont-ils appliqués aux valeurs avant les binaires ? Comme nous allons le voir, c’est à cause de *leur précédence supérieure*.

## Précédence des opérateurs

Si une expression à plusieurs opérateurs, l’ordre d’exécution est défini par leur *priorité* ou, en d’autres termes, il existe un ordre de priorité implicite entre les opérateurs.

De l'école, nous savons tous que la multiplication dans l'expression `1 + 2 * 2` devrait être calculée avant l'addition. C’est exactement cela la précédence. La multiplication est dite avoir une *précédence supérieure* à l'addition.

Les parenthèses outrepassent toute priorité, donc si nous ne sommes pas satisfaits de l'ordre par défaut, nous pouvons les utiliser, comme : `(1 + 2) * 2`.

Il y a beaucoup d'opérateurs en JavaScript. Chaque opérateur a un numéro correspondant à sa priorité de précédence. Celui qui est plus haut sur le tableau s'exécute en premier. Si la priorité est la même, l'ordre d'exécution est de gauche à droite.

Un extrait du [tableau de précédence](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence) (vous n'avez pas besoin de vous en souvenir, mais notez que les opérateurs unaires ont une priorité plus élevée que les binaires correspondants) :

| Précédence | Nom             | Symbole |
|------------|-----------------|---------|
| ...        | ...             | ...     |
| 14         | plus unaire     | `+`     |
| 14         | négation unaire | `-`     |
| 13         | exponentiation  | `**`    |
| 12         | multiplication  | `*`     |
| 12         | division        | `/`     |
| 11         | addition        | `+`     |
| 11         | soustraction    | `-`     |
| ...        | ...             | ...     |
| 2          | affectation     | `=`     |
| ...        | ...             | ...     |

Comme on peut le voir, le "plus unaire" a une priorité de `14`, ce qui est supérieur à `11` pour "l'addition" (plus binaire). C’est pourquoi, dans l’expression `"+apples + +oranges"`, les plus unaires fonctionnent avant l’addition.

## Affectation

Notons qu’une affectation `=` est aussi un opérateur. Il est répertorié dans le tableau des précédences avec la très faible priorité de `2`.

C’est pourquoi lorsque nous assignons une variable, comme `x = 2 * 2 + 1`, les calculs sont effectués en premier, puis le `=` est évalué, stockant le résultat dans `x`.

```js
let x = 2 * 2 + 1;

alert( x ); // 5
```

### Assignment = retourne une valeur

Le fait que `=` soit un opérateur, pas une construction de langage "magique" a une implication intéressante.

Tous les opérateurs en JavaScript renvoient une valeur. C'est évident pour `+` et `-`, mais aussi vrai pour `=`.

L'appel `x = valeur` écrit la `valeur` dans `x` *puis la renvoie*.

Voici un exemple qui utilise une affectation dans le cadre d'une expression plus complexe :

```js run
let a = 1;
let b = 2;

*!*
let c = 3 - (a = b + 1);
*/!*

alert( a ); // 3
alert( c ); // 0
```

Dans l'exemple ci-dessus, le résultat de l'expression`(a = b + 1)` est la valeur qui a été affectée à `a` (c'est-à-dire `3`). Il est ensuite utilisé pour d'autres évaluations.

Drôle de code, n'est-ce pas? Nous devons comprendre comment cela fonctionne, car parfois nous le voyons dans les bibliothèques JavaScript.

Cependant, n'écrivez pas le code comme ça. De telles astuces ne rendent certainement pas le code plus clair ou lisible.

### Affectations chaînées

Une autre caractéristique intéressante est la possibilité de chaîner des affectations :

```js run
let a, b, c;

*!*
a = b = c = 2 + 2;
*/!*

alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
```

Les affectations en chaîne sont évaluées de droite à gauche. D'abord, l'expression la plus à droite `2 + 2` est évaluée puis assignée aux variables de gauche : `c`, `b` et `a`. À la fin, toutes les variables partagent une seule valeur.

Encore une fois, pour des raisons de lisibilité, il est préférable de diviser ce code en quelques lignes :

```js
c = 2 + 2;
b = c;
a = c;
```
C'est plus facile à lire, en particulier lors de la numérisation rapide du code.

## Modification sur place

Nous avons souvent besoin d'appliquer un opérateur à une variable et d'y stocker le nouveau résultat.

Par exemple :

```js
let n = 2;
n = n + 5;
n = n * 2;
```

Cette notation peut être raccourcie en utilisant les opérateurs `+=` et `*=` :

```js run
let n = 2;
n += 5; // maintenant n = 7 (identique à n = n + 5)
n *= 2; // maintenant n = 14 (identique à n = n * 2)

alert( n ); // 14
```

Il existe des opérateurs de "modification et assignation" courts pour tous les opérateurs arithmétiques et binaires : `/=`, `-=` etc.

Ces opérateurs ont la même précédence qu'une affectation normale. Ils s'exécutent donc après la plupart des autres calculs :

```js run
let n = 2;

n *= 3 + 5; // la partie de droite est évaluée en premier (identique à n *= 8)

alert( n ); // 16
```

## Incrémentation / décrémentation

<!-- Can't use -- in title, because built-in parse turns it into – -->

L'augmentation ou la diminution d'un nombre par `1` compte parmi les opérations numériques les plus courantes.

Il y a donc des opérateurs spéciaux pour cela :

- **Incrémentation** `++` augmente une variable de 1 :

    ```js run no-beautify
    let counter = 2;
    counter++;        // fonctionne de la même manière que counter = counter + 1, mais c'est plus court
    alert( counter ); // 3
    ```
- **Décrémentation** `--` diminue une variable de 1 :

    ```js run no-beautify
    let counter = 2;
    counter--;        // fonctionne de la même manière que counter = counter - 1, mais c'est plus court
    alert( counter ); // 1
    ```

```warn
L'incrémentation / décrémentation ne peut être appliquée qu'à une variable. Une tentative pour l'utiliser sur une valeur comme `5++` donnera une erreur.
```

Les opérateurs `++` et `--` peuvent être placés à la fois après et avant la variable.

- Lorsque l'opérateur va après la variable, cela s'appelle une "forme postfixe" : `counter++`.
- La "forme préfixe" est celle où l'opérateur se place devant la variable : `++counter`.

Ces deux opérateurs font la même chose : augmenter le `counter` de `1`.

Y a-t-il une différence ? Oui, mais nous ne pouvons le voir que si nous utilisons la valeur renvoyée de `++/--`.

Soyons clairs. Comme nous le savons, tous les opérateurs renvoient une valeur. L'incrémentation / décrémentation n'est pas une exception ici. La forme préfixe renvoie la nouvelle valeur, tandis que la forme postfixe renvoie l'ancienne valeur (avant l'incrémentation / décrémentation).

Pour voir la différence, voici un exemple :

```js run
let counter = 1;
let a = ++counter; // (*)

alert(a); // *!*2*/!*
```

Ici, dans la ligne `(*)`, l'appel du *préfixe* `++counter` incrémente le compteur et retourne la nouvelle valeur qui est `2`. Ainsi, l'`alert` affiche `2`.

Maintenant, utilisons la forme postfixe :

```js run
let counter = 1;
let a = counter++; // (*) changé ++counter pour counter++

alert(a); // *!*1*/!*
```

Dans la ligne `(*)`, la forme postfixe `counter++` incrémente également `counter`, mais renvoie l'*ancienne* valeur (avant l'incrémentation). Donc, l'`alert` montre `1`.

Pour résumer :

- Si le résultat de l'incrémentation/décrémentation n'est pas utilisé, alors il n'y a pas de différence dans la forme à utiliser :

    ```js run
    let counter = 0;
    counter++;
    ++counter;
    alert( counter ); // 2, les lignes ci-dessus ont fait la même chose
    ```
- Si nous souhaitons augmenter la valeur et utiliser le résultat de l'opérateur immédiatement, nous avons besoin de la forme préfixe :

    ```js run
    let counter = 0;
    alert( ++counter ); // 1
    ```
- Si nous souhaitons incrémenter, mais utiliser la valeur précédente, alors nous avons besoin de la forme postfixe :

    ```js run
    let counter = 0;
    alert( counter++ ); // 0
    ```

````smart header="Incrémentation / décrémentation parmi d'autres opérateurs"
Les opérateurs `++/--` peuvent également être utilisés dans une expression. Leur précédence est plus élevée que la plupart des autres opérations arithmétiques.

Par exemple :

```js run
let counter = 1;
alert( 2 * ++counter ); // 4
```

A comparer avec :

```js run
let counter = 1;
alert( 2 * counter++ ); // 2, counter++ renvoie "l'ancienne" valeur
```

Bien que techniquement acceptable, une telle notation rend le code moins lisible. Une ligne fait plusieurs choses -- pas bien.

Lors de la lecture du code, un scan oculaire "vertical" rapide peut facilement manquer un tel `counter++`, et il n’est pas évident que la variable augmente.

Le style "une ligne -- une action" est conseillé :

```js run
let counter = 1;
alert( 2 * counter );
counter++;
```
````

## Opérateurs binaires

Les opérateurs binaires traitent les arguments comme des nombres entiers de 32 bits et travaillent au niveau de leur représentation binaire.

Ces opérateurs ne sont pas spécifiques à JavaScript. Ils sont pris en charge dans la plupart des langages de programmation.

La liste des opérateurs :

- AND ( `&` )
- OR ( `|` )
- XOR ( `^` )
- NOT ( `~` )
- LEFT SHIFT ( `<<` )
- RIGHT SHIFT ( `>>` )
- ZERO-FILL RIGHT SHIFT ( `>>>` )

Ces opérateurs sont très rarement utilisés, lorsque nous devons jouer avec des nombres au niveau le plus bas (bit à bit). Nous n'aurons pas besoin de ces opérateurs de si tôt, car le développement Web les utilise peu, mais dans certains domaines particuliers, comme la cryptographie, ils sont utiles. Vous pouvez lire le chapitre [Opérateurs binaires](https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Expressions_et_Op%C3%A9rateurs#Op%C3%A9rateurs_binaires) sur MDN en cas de besoin.


## Virgule

L'opérateur virgule `,` est l'un des opérateurs les plus rares et les plus inhabituels. Parfois, il faut écrire un code plus court, il faut donc le connaître pour comprendre ce qui se passe.

L'opérateur virgule nous permet d'évaluer plusieurs expressions en les divisant par une virgule `,`. Chacun d'eux est évalué, mais seulement le résultat de la dernière est renvoyé.

Par exemple :

```js run
*!*
let a = (1 + 2, 3 + 4);
*/!*

alert( a ); // 7 (le résultat de 3 + 4)
```

Ici, la première expression `1 + 2` est évaluée mais son résultat n'est pas utilisé, puis `3 + 4` est évalué et renvoyé comme résultat.

```smart header="La virgule a une très faible précédence"
Veuillez noter que l'opérateur virgule a une précédence très basse, inférieure à `=`, donc les parenthèses sont importantes dans l'exemple ci-dessus.

Sans eux : `a = 1 + 2, 3 + 4` évalue d'abord `+`, additionnant les nombres dans `a = 3, 7`, ensuite l'opérateur d'affectation `=` assigne `a = 3`, et le reste est ignoré. C'est comme `(a = 1 + 2), 3 + 4`.
```

Pourquoi avons-nous besoin d'un tel opérateur qui jette tout sauf la dernière partie ?

Parfois, les gens l'utilisent dans des constructions plus complexes pour placer plusieurs actions sur une seule ligne.

Par exemple :

```js
// trois opérations en une seule ligne
for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) {
 ...
}
```

Ces astuces sont utilisées dans de nombreux frameworks JavaScript, c’est pourquoi nous les mentionnons. Mais généralement, ils n'améliorent pas la lisibilité du code, nous devrions bien réfléchir avant de les utiliser.


================================================
FILE: 1-js/02-first-steps/09-comparison/1-comparison-questions/solution.md
================================================


```js no-beautify
5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false
```

Quelques raisons :

1. Évidemment, c'est vrai.
2. Comparaison du dictionnaire, donc fausse. `"a"` est plus petit que `"p"`.
3. Encore une fois, comparaison du dictionnaire, le premier caractère de `"2"` est plus grand que le premier caractère de `"1"`.
4. Les valeurs `null` et `undefined` sont exclusivement égale entre elles.
5. L'égalité stricte est stricte. Des types différents des deux côtés conduisent à `false`.
6. Similaire à `(4)`, `null` n'est égale qu'à `undefined`.
7. Egalité stricte de différents types.


================================================
FILE: 1-js/02-first-steps/09-comparison/1-comparison-questions/task.md
================================================
importance: 5

---

# Comparaisons

Quel sera le résultat pour les expressions suivantes :

```js no-beautify
5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"
```



================================================
FILE: 1-js/02-first-steps/09-comparison/article.md
================================================
# Comparaisons

Il y a de nombreux opérateurs de comparaison que nous connaissons des mathématiques :

- Plus grand/petit que : <code>a &gt; b</code>, <code>a &lt; b</code>.
- Plus grand/petit ou égal à : <code>a &gt;= b</code>, <code>a &lt;= b</code>.
- Égalité : `a == b` (veuillez noter le signe de la double égalité `==` signifie un test d’égalité. Un seul symbole `a = b` signifierait une affectation).
- Pas égal : en maths la notation est <code>&ne;</code>, mais en JavaScript elle est écrite comme une assignation avec un signe d’exclamation : <code>a != b</code>.

Dans cet article, nous en apprendrons plus sur les différents types de comparaisons, sur la façon dont JavaScript les fait, y compris sur les particularités importantes.

À la fin, vous trouverez une bonne recette pour éviter les problèmes liés aux "bizarreries JavaScript".

## Booléen est le résultat

Tout comme tous les autres opérateurs, une comparaison renvoie une valeur de type booléenne.

- `true` -- signifie "oui", "correct" ou "vrai".
- `false` -- signifie "non", "incorrect" ou "faux".

Par exemple :

```js run
alert( 2 > 1 );  // true (correct)
alert( 2 == 1 ); // false (faux)
alert( 2 != 1 ); // true (correct)
```

Un résultat de comparaison peut être affecté à une variable, comme toute valeur :

```js run
let result = 5 > 4; // attribue le résultat de la comparaison
alert( result ); // true
```

## Comparaison de chaînes de caractères

Pour voir quelle chaîne de caractères est plus grande que l'autre, on utilise l'ordre dit "dictionnaire" ou "lexicographique".

En d'autres termes, les chaînes de caractères sont comparées lettre par lettre.

Par exemple :

```js run
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
alert( '9' > '10' ); // true
```

L'algorithme pour comparer deux chaînes  de caractères est simple :

1. Compare les premiers caractères des deux chaînes de caractères.
2. Si le premier est supérieur (ou inférieur), la première chaîne de caractères est supérieure (ou inférieure) à la seconde. Nous en avons fini.
3. Sinon, si les premiers caractères sont égaux, comparez les deuxièmes caractères de la même manière.
4. Répéter jusqu'à la fin d'une chaîne de caractères.
5. Si les deux chaînes de caractères se sont terminées simultanément, alors elles sont égales. Sinon, la chaîne la plus longue est plus grande.

Dans l'exemple ci-dessus, la comparaison `'Z' > 'A'` obtient le résultat à la première étape.

La deuxième comparaison `'Glow'` et `'Glee'` nécessite plus d'étapes car les chaînes de caractères sont comparées caractère par caractère :

1. `G` est identique à `G`.
2. `l` est identique à `l`.
3. `o` est plus grand que `e`. On stop ici. La première chaîne de caractères est plus grande.

```smart header="Pas vraiment un dictionnaire, mais plutôt l'ordre Unicode"
L'algorithme de comparaison ci-dessus est à peu près équivalent à celui utilisé dans les dictionnaires ou les annuaires téléphoniques. Mais ce n’est pas exactement la même chose.

Par exemple, cette notion est importante à comprendre. Une lettre majuscule `"A"` n'est pas égale à la lettre minuscule `"a"`. Lequel est le plus grand ? En fait, le minuscule `"a"` l'est. Pourquoi ? Parce que le caractère minuscule a un index plus grand dans la table de codage interne (Unicode). Nous reviendrons sur les détails spécifiques et leurs conséquences dans le chapitre <info:string>.
```

## Comparaison de différents types

Lorsque les valeurs comparées appartiennent à différents types, elles sont converties en nombres.

Par exemple :

```js run
alert( '2' > 1 ); // true, la chaîne '2' devient un numéro 2
alert( '01' == 1 ); // true, chaîne '01' devient un numéro 1
```

Pour les valeurs booléennes, `true` devient `1` et `false` devient `0`.

Par exemple :

```js run
alert( true == 1 ); // true
alert( false == 0 ); // true
```

````smart header="Une conséquence amusante"
Il est possible que dans le même temps :

- Deux valeurs sont égales.
- L'un d'eux est `vrai` comme booléen et l'autre est `faux` comme booléen.

Par exemple :

```js run
let a = 0;
alert( Boolean(a) ); // false

let b = "0";
alert( Boolean(b) ); // true

alert(a == b); // true!
```

Du point de vue de JavaScript, c'est tout à fait normal. Un contrôle d'égalité convertit en utilisant la conversion numérique (par conséquent, `"0"` devient `0`), tandis que la `conversion booléenne` utilise un autre ensemble de règles.
````

## Égalité stricte

Une vérification d'égalité régulière `==` a un problème. Elle ne peut pas faire la différence entre `0` et `false` :

```js run
alert( 0 == false ); // true
```

La même chose avec une chaîne de caractères vide :

```js run
alert( '' == false ); // true
```

C’est parce que les opérandes de différents types sont convertis en un nombre par l’opérateur d’égalité `==`. Une chaîne de caractères vide, tout comme `false`, devient un zéro.

Que faire si nous voulons différencier `0` de `faux` ?

**Un opérateur d'égalité stricte `===` vérifie l'égalité sans conversion de type.**

En d'autres termes, si `a` et `b` sont de types différents, alors `a === b` renvoie immédiatement `false` sans tenter de les convertir.

Essayons :

```js run
alert( 0 === false ); // false, parce que les types sont différents
```

Il existe également un opérateur de "strict non-égalité" `!==`, par analogie à la non-égalité `!=`.

L’opérateur de vérification de l’égalité stricte est un peu plus long à écrire, mais rend évident ce qui se passe et laisse moins d’espace pour les erreurs.

## Comparaison avec null et undefined

Il existe un comportement non intuitif lorsque `null` ou `undefined` sont comparés à d’autres valeurs.


Pour un contrôle de strict égalité `===`
: Ces valeurs sont différentes car chacune d’entre elles appartient à un type distinct.

    ```js run
    alert( null === undefined ); // false
    ```

Pour un contrôle d'égalité non strict `==`
: Il y a une règle spéciale. Ces deux là forment "un beau couple" : ils sont égaux (au sens de `==`), mais pas à d'autres valeurs.

    ```js run
    alert( null == undefined ); // true
    ```

Pour les maths et autres comparaisons `<`, `>`, `<=`, `>=`
: Les valeurs `null`/`undefined` sont converties en un nombre : `null` devient `0`, alors qu'`undefined` devient `NaN`.

Voyons maintenant des choses amusantes qui se produisent lorsque nous appliquons ces règles. Et, ce qui est plus important, comment ne pas tomber dans un piège avec ces caractéristiques.

### L'étrange résultat : null vs 0

Comparons `null` avec un zéro :

```js run
alert( null > 0 );  // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) *!*true*/!*
```

Ouais, mathématiquement c'est étrange. Le dernier résultat indique que "`null` est supérieur ou égal à zéro". Alors que l'une des comparaisons au dessus devrait être correcte, mais les deux sont fausses.

La raison est qu'une vérification d'égalité (`==`) et les comparaisons (`<`, `>`, `<=`, `>=`) fonctionnent différemment. Les comparaisons convertissent `null` en un nombre, donc le traitent comme `0`. C'est pourquoi (3) `null >= 0` est vrai et (1) `null > 0` est faux.

D’un autre côté, la vérification de l’égalité `==` pour `undefined` et `null` est définie de telle sorte que, sans aucune conversion, ils sont égaux et ne correspondent à rien d’autre. C'est pourquoi (2) `null == 0` est faux.

### Un undefined incomparable

La valeur `undefined` ne doit pas du tout participer aux comparaisons :

```js run
alert( undefined > 0 );  // false (1)
alert( undefined < 0 );  // false (2)
alert( undefined == 0 ); // false (3)
```

Pourquoi est-ce qu'il n'aime pas le zéro ? Toujours faux!

Nous avons ces résultats parce que :

- Les comparaisons `(1)` et `(2)` renvoient `false` car `undefined` est converti en `NaN` et `NaN` est une valeur numérique spéciale qui renvoie `false` pour toutes les comparaisons.
- Le contrôle d'égalité `(3)` renvoie `false`, car `undefined` est uniquement égal à `null` et à aucune autre valeur.

### Éviter les problèmes

Pourquoi avons-nous observé ces exemples? Devrions-nous nous souvenir de ces particularités tout le temps ? Eh bien pas vraiment. En fait, ces notions délicates deviennent progressivement familières au fil du temps, mais il existe un moyen solide d’éviter tout problème avec elles.

Il suffit de traiter toute comparaison avec `null`/`undefined` (à l'exception de la stricte égalité `===`) avec un soin exceptionnel.

N'utilisez pas de comparaisons `=>`, `>`, `<`, `<=` avec une variable qui peut être `null`/`undefined`, sauf si vous êtes vraiment sûr de ce que vous faites. Si une variable peut avoir de telles valeurs, vérifiez-les séparément.

## Résumé

- Les opérateurs de comparaison renvoient une valeur logique.
- Les chaînes de caractères sont comparées lettre par lettre dans l'ordre "dictionnaire".
- Lorsque des valeurs de différents types sont comparées, elles sont converties en nombres (à l'exclusion d'un contrôle d'égalité strict).
- Les valeurs `null` et `undefined` sont égales (`==`) et ne correspondent à aucune autre valeur.
- Soyez prudent lorsque vous utilisez des comparaisons telles que `>` ou `<` avec des variables pouvant parfois être `null`/`undefined`. Faire une vérification séparée pour `null`/`undefined` est une bonne idée.


================================================
FILE: 1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md
================================================
**Oui, il sera affiché.**

Toute chaîne de caractères à l'exception d'une chaîne vide (et `"0"` n'est pas vide) devient vraie dans le contexte logique.

Nous pouvons exécuter et vérifier:

```js run
if ("0") {
  alert( 'Hello' );
}
```



================================================
FILE: 1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md
================================================
importance: 5

---

# if (une chaîne de caractères avec zéro)

Est-ce que `alert` sera affiché ?

```js
if ("0") {
  alert( 'Hello' );
}
```



================================================
FILE: 1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2/index.html
================================================
<!DOCTYPE html>
<html>

<body>
  <script>
    'use strict';

    let value = prompt('What is the "official" name of JavaScript?', '');

    if (value == 'ECMAScript') {
      alert('Right!');
    } else {
      alert("You don't know? ECMAScript!");
    }
  </script>


</body>

</html>


================================================
FILE: 1-js/02-first-steps/10-ifelse/2-check-standard/solution.md
================================================


[html run src="ifelse_task2/index.html"]



================================================
FILE: 1-js/02-first-steps/10-ifelse/2-check-standard/task.md
================================================
importance: 2

---

# Le nom de JavaScript

En utilisant la construction `if..else`, écrivez le code qui demande : 'Quel est le nom "officiel" de JavaScript?'

Si le visiteur entre "ECMAScript", alors éditez une sortie "Bonne réponse !", Sinon -- retourne "Ne sait pas ? ECMAScript!"

![](ifelse_task2.svg)

[demo src="ifelse_task2"]


================================================
FILE: 1-js/02-first-steps/10-ifelse/3-sign/if_sign/index.html
================================================
<!DOCTYPE html>
<html>

<body>

  <script>
    'use strict';

    let value = prompt('Type a number', 0);

    if (value > 0) {
      alert(1);
    } else if (value < 0) {
      alert(-1);
    } else {
      alert(0);
    }
  </script>

</body>

</html>


================================================
FILE: 1-js/02-first-steps/10-ifelse/3-sign/solution.md
================================================


```js run
let value = prompt('Type a number', 0);

if (value > 0) {
  alert( 1 );
} else if (value < 0) {
  alert( -1 );
} else {
  alert( 0 );
}
```



================================================
FILE: 1-js/02-first-steps/10-ifelse/3-sign/task.md
================================================
importance: 2

---

# Afficher le signe

En utilisant `if..else`, écrivez le code qui obtient un numéro via le `prompt`, puis l'affiche en `alert` :

- `1`, si la valeur est supérieure à zéro,
- `-1`, si inférieur à zéro,
- `0`, si est égal à zéro.

Dans cet exercice, nous supposons que l'entrée est toujours un nombre.

[demo src="if_sign"]


================================================
FILE: 1-js/02-first-steps/10-ifelse/5-rewrite-if-question/solution.md
================================================


```js
let result = (a + b < 4) ? 'Below' : 'Over';
```



================================================
FILE: 1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md
================================================
importance: 5

---

# Réécrire 'if' en '?'

Réécrivez ce `if` en utilisant l'opérateur conditionnel `'?'` :

```js
let result;

if (a + b < 4) {
  result = 'Below';
} else {
  result = 'Over';
}
```


================================================
FILE: 1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/solution.md
================================================


```js
let message = (login == 'Employee') ? 'Hello' :
  (login == 'Director') ? 'Greetings' :
  (login == '') ? 'No login' :
  '';
```



================================================
FILE: 1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/task.md
================================================
importance: 5

---

# Réécrire 'if..else' en '?'

Réécrire ce `if..else` en utilisant plusieurs opérateurs ternaires `'?'`.

Pour plus de lisibilité, il est recommandé de diviser le code en plusieurs lignes.

```js
let message;

if (login == 'Employee') {
  message = 'Hello';
} else if (login == 'Director') {
  message = 'Greetings';
} else if (login == '') {
  message = 'No login';
} else {
  message = '';
}
```


================================================
FILE: 1-js/02-first-steps/10-ifelse/article.md
================================================
# Branche conditionnelle : if, '?'

Parfois, nous devons effectuer différentes actions en fonction d'une condition.

Pour ce faire, nous pouvons utiliser l'instruction `if` et l'opérateur conditionnel `? `, également appelé opérateur "point d'interrogation".

## L'instruction "if"

L'instruction `if(...)` évalue une condition entre parenthèses et, si le résultat est `true`, exécute un bloc de code.

Par exemple :

```js run
let year = prompt('In which year was ECMAScript-2015 specification published?', '');

*!*
if (year == 2015) alert( 'You are right!' );
*/!*
```

Dans l'exemple ci-dessus, la condition est une vérification d'égalité simple : `year == 2015`, mais elle peut être beaucoup plus complexe.

S'il y a plus d'une instruction à exécuter, nous devons envelopper notre bloc de code entre accolades :

```js
if (year == 2015) {
  alert( "That's correct!" );
  alert( "You're so smart!" );
}
```

Il est recommandé d'entourer votre bloc de code avec des accolades `{}` à chaque fois avec `if`, même s’il n’y a qu’une seule instruction. Cela améliore la lisibilité.

## Conversion booléenne

L'instruction `if (…)` évalue l'expression entre parenthèses et la convertit en type booléen.

Rappelons les règles de conversion du chapitre <info:type-conversions>:

- Un nombre `0`, une chaîne de caractères vide `""`, `null`, `undefined` et `NaN` deviennent `false`. À cause de cela, on dit de ces valeurs qu'elles sont "falsy".
- Les autres valeurs deviennent `true`, on dit qu'elles sont "truthy".

Donc, le code sous cette condition ne sera jamais exécuté :

```js
if (0) { // 0 est falsy
  ...
}
```

… Et à l'intérieur de cette condition - il fonctionne toujours :

```js
if (1) { // 1 est truthy
  ...
}
```

Nous pouvons également transmettre une valeur booléenne pré-évaluée à `if`, comme ici :

```js
let cond = (year == 2015); // l'égalité évalue à vrai ou faux

if (cond) {
  ...
}
```

## La clause "else"


L'instruction `if` peut contenir un bloc optionnel `else`. Il s'exécute lorsque la condition est fausse.

Par exemple :
```js run
let year = prompt('In which year was the ECMAScript-2015 specification published?', '');

if (year == 2015) {
  alert( 'You guessed it right!' );
} else {
  alert( 'How can you be so wrong?' ); // toute autre valeur que 2015
}
```

## Plusieurs conditions : "else if"

Parfois, nous aimerions tester plusieurs variantes d'une condition. Il y a une clause `else if` pour cela.

Par exemple :

```js run
let year = prompt('En quelle année la spécification ECMAScript-2015 a-t-elle été publiée ?', '');

if (year < 2015) {
  alert( 'Too early...' );
} else if (year > 2015) {
  alert( 'Too late' );
} else {
  alert( 'Exactly!' );
}
```

Dans le code ci-dessus, JavaScript vérifie `year < 2015`. S'il est falsy, il passe à l'année de condition suivante `year > 2015` et c'est toujours `false` il passe à la dernière instruction et affiche la dernière alerte.

Il peut y avoir plus de blocks `else if`. Le dernier `else` est optionnel.

## Opérateur ternaire '?'

Parfois, nous devons attribuer une variable en fonction d'une condition.

Par exemple :

```js run no-beautify
let accessAllowed;
let age = prompt('How old are you?', '');

*!*
if (age > 18) {
  accessAllowed = true;
} else {
  accessAllowed = false;
}
*/!*

alert(accessAllowed);
```

L'opérateur dit "ternaire" ou "point d'interrogation" nous permet de le faire plus rapidement et plus simplement.

L'opérateur est représenté par un point d'interrogation `?`. Appelé aussi "ternaire" parce que l'opérateur a trois opérandes. C'est en fait le seul et unique opérateur en JavaScript qui en a autant.

La syntaxe est :
```js
let result = condition ? value1 : value2
```

La `condition` est évaluée, si elle est vraie, alors `value1` est retournée, sinon -- `value2`.

Par exemple :

```js
let accessAllowed = (age > 18) ? true : false;
```

Techniquement, nous pouvons omettre les parenthèses autour de `age > 18`. L'opérateur point d'interrogation a une faible précédence, il s'exécute donc après la comparaison `>`.

Cet exemple fera la même chose que le précédent :

```js
// l'opérateur de comparaison "age > 18" s'exécute en premier quoiqu'il en soit
// (pas besoin de l'envelopper entre parenthèses)
let accessAllowed = age > 18 ? true : false;
```

Mais les parenthèses rendent le code plus lisible, il est donc recommandé de les utiliser.

````smart
Dans l'exemple ci-dessus, il est possible d'éviter l'opérateur ternaire, parce que la comparaison elle-même renvoie un `true/false`:

```js
// la même chose
let accessAllowed = age > 18;
```
````

## Multiple '?'

Une séquence d'opérateurs point d'interrogation `?` permettent de renvoyer une valeur qui dépend de plusieurs conditions.

Par exemple :
```js run
let age = prompt('age?', 18);

let message = (age < 3) ? 'Hi, baby!' :
  (age < 18) ? 'Hello!' :
  (age < 100) ? 'Greetings!' :
  'What an unusual age!';

alert( message );
```

Il peut être difficile au début de comprendre ce qui se passe. Mais après un examen plus approfondi, nous constatons que ce n’est qu’une séquence de tests ordinaire.


1. Le premier point d'interrogation vérifie si `age < 3`.

2. Si vrai -- retourne `'Hi, baby!'`, Sinon, il continue avec l'expression après les deux points ":" suivants et vérifie si `age < 18`.
3. Si vrai -- retourne `'Hello!'`, Sinon, il continue avec l'expression après les deux points ":" suivants et vérifie si `age < 100`.
4. Si vrai -- retourne `'Greetings!'`, Sinon, l'expression continue après les derniers deux-points et retourne `'What an unusual age!'`.

La même logique utilisant `if..else` :

```js
if (age < 3) {
  message = 'Hi, baby!';
} else if (age < 18) {
  message = 'Hello!';
} else if (age < 100) {
  message = 'Greetings!';
} else {
  message = 'What an unusual age!';
}
```

## Utilisation non traditionnelle de '?'

Parfois, le point d'interrogation `?` est utilisé en remplacement de `if` :

```js run no-beautify
let company = prompt('Which company created JavaScript?', '');

*!*
(company == 'Netscape') ?
   alert('Right!') : alert('Wrong.');
*/!*
```

Selon si la condition  `company == 'Netscape'` est vraie ou non, la première ou la deuxième partie après `?` s'exécute et affiche l'alerte correspondante.

Nous n’attribuons pas de résultat à une variable ici. L'idée est d'exécuter un code différent en fonction de la condition.

**Il n'est pas recommandé d'utiliser l'opérateur ternaire de cette manière.**

La notation semble être plus courte qu'un `if`, ce qui plaît à certains programmeurs. Mais c'est moins lisible.

Voici le même code avec `if` pour comparaison :

```js run no-beautify
let company = prompt('Which company created JavaScript?', '');

*!*
if (company == 'Netscape') {
  alert('Right!');
} else {
  alert('Wrong.');
}
*/!*
```

Nos yeux scrutent le code verticalement. Les constructions qui couvrent plusieurs lignes sont plus faciles à comprendre qu'un jeu d'instructions horizontal long.

L'idée d'un point d'interrogation `?` est de renvoyer l'une ou l'autre valeur selon la condition. Veuillez l'utiliser pour cela exactement. Il y a `if` pour exécuter différentes branches du code.


================================================
FILE: 1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/solution.md
================================================
La réponse est `2`, c'est la première valeur vraie.

```js run
alert( null || 2 || undefined );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/task.md
================================================
importance: 5

---

# Quel est le résultat de OR ?

Qu'est-ce que le code ci-dessous va sortir ?

```js
alert( null || 2 || undefined );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/2-alert-or/solution.md
================================================
La réponse : d'abord `1` puis `2`.

```js run
alert( alert(1) || 2 || alert(3) );
```

Règle importante à retenir : **L'appel de l'`alert` ne renvoie pas de valeur. Ou, en d'autres termes, il retourne `undefined`.**

1. Le premier OR `||` évalue son opérande gauche `alert(1)`. Cela affiche le premier message avec `1`.
2. L'`alert` retourne `undefined`, donc OR passe au deuxième opérande en recherchant une valeur vraie.
3. Le deuxième opérande `2` est vrai, donc l'exécution est interrompue, `2` est renvoyé puis affiché par l'alerte externe.

Il n'y aura pas de `3`, car l'évaluation n'atteint pas l'`alert (3)`.


================================================
FILE: 1-js/02-first-steps/11-logical-operators/2-alert-or/task.md
================================================
importance: 3

---

# Quel est le résultat des alertes OR ?

Qu'est-ce que le code ci-dessous va sortir ?

```js
alert( alert(1) || 2 || alert(3) );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md
================================================
La réponse : `null`, car c'est la première valeur `false` de la liste.

```js run
alert(1 && null && 2);
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/task.md
================================================
importance: 5

---

# Quel est le résultat de AND ?

Qu'est-ce que ce code va afficher ?

```js
alert( 1 && null && 2 );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/4-alert-and/solution.md
================================================
La réponse : `1`, et ensuite `undefined`.

```js run
alert( alert(1) && alert(2) );
```

L’appel de l'`alert` renvoie undefined (il affiche juste un message, donc il n’ya pas de retour significatif dans le code).

À cause de cela, `&&` évalue l'opérande gauche (sortie 1), et s'arrête immédiatement, car `undefined` est une valeur `false`. Et comme `&&` recherche la première valeur fausse et la retourne, donc il s'arrête là.



================================================
FILE: 1-js/02-first-steps/11-logical-operators/4-alert-and/task.md
================================================
importance: 3

---

# Quel est le résultat des alertes AND ?

Qu’est-ce que ce code va afficher ?

```js
alert( alert(1) && alert(2) );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/5-alert-and-or/solution.md
================================================
La réponse : `3`.

```js run
alert( null || 2 && 3 || 4 );
```

La priorité de AND `&&` est supérieure à OR `||`, elle s'exécute donc en premier.

Le résultat de `2 && 3 = 3`, donc l'expression devient :

```
null || 3 || 4
```

Maintenant, le résultat est la première valeur vraie : `3`.



================================================
FILE: 1-js/02-first-steps/11-logical-operators/5-alert-and-or/task.md
================================================
importance: 5

---

# Le résultat de OR AND OR

Quel sera le résultat ?

```js
alert( null || 2 && 3 || 4 );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/6-check-if-in-range/solution.md
================================================


```js
if (age >= 14 && age <= 90)
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/6-check-if-in-range/task.md
================================================
importance: 3

---

# Vérifiez la plage entre

Ecrivez une condition `"if"` pour vérifier que l’`age` est compris entre `14` et `90` ans inclus.

"Inclus" signifie que l’`age` peut atteindre les `14` ou `90` ans.


================================================
FILE: 1-js/02-first-steps/11-logical-operators/7-check-if-out-range/solution.md
================================================
La première variante :

```js
if (!(age >= 14 && age <= 90))
```

La seconde variante :

```js
if (age < 14 || age > 90)
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/7-check-if-out-range/task.md
================================================
importance: 3

---

# Vérifiez à l'extérieur de la plage

Ecrivez une condition `if` pour vérifier que l’`age` n’est PAS compris entre `14` et `90` ans inclus.

Créez deux variantes: la première utilisant NOT `!`, La seconde - sans ce dernier.


================================================
FILE: 1-js/02-first-steps/11-logical-operators/8-if-question/solution.md
================================================
La réponse: le premier et le troisième vont s'exécuter.

Details:

```js run
// S'éxécute
// le résultat de -1 || 0 = -1, vrai
if (-1 || 0) alert( 'first' );

// Ne s'éxécute pas
// -1 && 0 = 0, faux
if (-1 && 0) alert( 'second' );

// S'éxécute
// L'opérateur && a une précédence plus élevée que ||
// donc -1 && 1 s'exécute en premier, nous donnant la chaîne :
// null || -1 && 1  ->  null || 1  ->  1
if (null || -1 && 1) alert( 'third' );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/8-if-question/task.md
================================================
importance: 5

---

# Une question à propos de "if"

Lesquelles de ces `alert`es vont s'exécuter ?

Quels seront les résultats des expressions à l'intérieur de `if (...)` ?  

```js
if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
```



================================================
FILE: 1-js/02-first-steps/11-logical-operators/9-check-login/solution.md
================================================


```js run demo
let userName = prompt("Who's there?", '');

if (userName === 'Admin') {

  let pass = prompt('Password?', '');

  if (pass === 'TheMaster') {
    alert( 'Welcome!' );
  } else if (pass === '' || pass === null) {
    alert( 'Canceled' );
  } else {
    alert( 'Wrong password' );
  }

} else if (userName === '' || userName === null) {
  alert( 'Canceled' );
} else {
  alert( "I don't know you" );
}
```

Notez les retraits verticaux à l'intérieur des blocs `if`. Ils ne sont techniquement pas nécessaires, mais rendent le code plus lisible.


================================================
FILE: 1-js/02-first-steps/11-logical-operators/9-check-login/task.md
================================================
importance: 3

---

# Check the login

Écrivez le code qui demande une connexion avec `prompt`.

Si le visiteur entre `"Admin"`, puis `prompt` pour un mot de passe, si l'entrée est une ligne vide ou `key:Esc` -- affichez "Canceled", s'il s'agit d'une autre chaîne de caractères -- alors affichez "I don't know you".

Le mot de passe est vérifié comme suit :

- S'il est égal à "TheMaster", alors affichez "Welcome!",
- Une autre chaînede caractères -- affichez "Wrong password",
- Pour une chaîne de caractères vide ou une entrée annulée, affichez "Canceled".

Le schéma :

![](ifelse_task.svg)

Veuillez utiliser des blocs `if` imbriqués. Attention à la lisibilité globale du code.

Astuce: passer une entrée vide à un prompt renvoie une chaîne de caractères vide `''`. En pressant `key:ESC` lors d'un prompt cela retourne `null`.

[demo]


================================================
FILE: 1-js/02-first-steps/11-logical-operators/article.md
================================================
# Opérateurs logiques

Il y a trois opérateurs logiques en JavaScript : `||` (OR), `&&` (AND), `!` (NOT), `??` (Coalescence des nulles). Nous couvrons ici les trois premiers, l'opérateur `??` est dans l'article suivant.

Bien qu'ils soient appelés "logiques", ils peuvent être appliqués à des valeurs de tout type, pas seulement booléennes. Le résultat peut également être de tout type.

Voyons les détails.

## || (OR)

L'opérateur "OR" est représenté avec deux symboles de ligne verticale :

```js
result = a || b;
```

En programmation classique, le OU logique est destiné à manipuler uniquement les valeurs booléennes. Si l'un de ses arguments est `true`, alors il renvoie `true`, sinon il renvoie `false`.

En JavaScript, l'opérateur est un peu plus compliqué et puissant. Mais voyons d’abord ce qui se passe avec les valeurs booléennes.

Il existe quatre combinaisons logiques possibles :

```js run
alert( true  || true  ); // true
alert( false || true  ); // true
alert( true  || false ); // true
alert( false || false ); // false
```

Comme on peut le voir, le résultat est toujours `true` sauf pour le cas où les deux opérandes sont `false`.

Si un opérande n'est pas booléen, il est converti en booléen pour l'évaluation.

Par exemple, un nombre `1` est traité comme `true`, un nombre `0` - comme `false` :

```js run
if (1 || 0) { // fonctionne comme si ( true || false )
  alert( 'truthy!' );
}
```

La plupart du temps, OR `||` est utilisé dans une instruction `if` pour tester si `l'une` des conditions données est correcte.

Par exemple :

```js run
let hour = 9;

*!*
if (hour < 10 || hour > 18) {
*/!*
  alert( 'The office is closed.' );
}
```

Nous pouvons passer plus de conditions :

```js run
let hour = 12;
let isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
  alert( 'The office is closed.' ); // c'est le weekend
}
```

### OR "||" cherche la première valeur vraie [#or-cherche-la-premiere-valeur-vraie]

La logique décrite ci-dessus est quelque peu classique. Maintenant, apportons les fonctionnalités "supplémentaires" de JavaScript.

L'algorithme étendu fonctionne comme suit.

En cas de multiples valeurs liées par OR :

```js
result = value1 || value2 || value3;
```

L'opérateur OR `||` fait ce qui suit :

- Évaluez les opérandes de gauche à droite.
- Pour chaque opérande, il le convertit en booléen. Si le résultat est `true`, arrêtez et retournez la valeur d'origine de cet opérande.
- Si tous les autres opérandes ont été évalués (c’est-à-dire que tous étaient `false`), renvoyez le dernier opérande.

Une valeur est renvoyée sous sa forme d'origine, sans conversion.

En d'autres termes, une chaîne de OR `||` renvoie la première valeur `true` ou la dernière valeur si aucune valeur `true` n'a été trouvée.

Par exemple :

```js run
alert( 1 || 0 ); // 1 (1 est vrai)

alert( null || 1 ); // 1 (1 est la première valeur vraie)
alert( null || 0 || 1 ); // 1 (la première valeur vraie)

alert( undefined || null || 0 ); // 0 (tous faux, renvoie la dernière valeur)
```

Cela conduit à des usages intéressants par rapport à un "OR pur, classique, booléen uniquement".

1. **Obtenir la première valeur vraie dans la liste des variables ou des expressions.**

    Par exemple, nous avons les variables `firstName`, `lastName` et `nickName`, toutes optionnelles (c'est-à-dire peut être indéfini ou avoir des valeurs fausses).

    Utilisons OR `||` pour choisir celui qui contient les données et l'afficher (ou `Anonymous` si rien n'est défini) :

    ```js run
    let firstName = "";
    let lastName = "";
    let nickName = "SuperCoder";

    *!*
    alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
    */!*
    ```

    Si toutes les variables étaient fausses, ce serait `"Anonymous"` qui apparaîtrait.

2. **Évaluation des courts-circuits.**

    Une autre caractéristique de l'opérateur OR `||` est l'évaluation dite de "court-circuit".

    Cela signifie que `||` traite ses arguments jusqu'à ce que la première valeur de vérité soit atteinte, puis la valeur est renvoyée immédiatement, sans même toucher l'autre argument.

    L'importance de cette fonctionnalité devient évidente si un opérande n'est pas seulement une valeur, mais une expression avec un effet secondaire, comme une affectation de variable ou un appel de fonction.

    Dans l'exemple ci-dessous, seul le deuxième message est imprimé :

    ```js run no-beautify
    *!*true*/!* || alert("not printed");
    *!*false*/!* || alert("printed");
    ```

    Dans la première ligne, l'opérateur OR `||` arrête l'évaluation immédiatement après avoir vu `true`, de sorte que `alert` n'est pas exécuté.

    Parfois, les gens utilisent cette fonctionnalité pour exécuter des commandes uniquement si la condition sur la partie gauche est fausse.

## && (AND)

L'opérateur AND est représenté avec deux esperluettes `&&` :

```js
result = a && b;
```

En programmation classique, AND retourne `true` si les deux opérandes sont `true` et `false` dans les autres cas :

```js run
alert( true  && true  ); // true
alert( false && true  ); // false
alert( true  && false ); // false
alert( false && false ); // false
```

Un exemple avec `if`:

```js run
let hour = 12;
let minute = 30;

if (hour == 12 && minute == 30) {
  alert( 'Time is 12:30' );
}
```

Tout comme pour OR, toute valeur est autorisée en tant qu'opérande de AND :

```js run
if (1 && 0) { // évalué comme true && false
  alert( "Ne marchera pas, car le résultat est faux" );
}
```


## AND "&&" cherche la première valeur fausse

En cas de multiples valeurs liées par AND :

```js
result = value1 && value2 && value3;
```

L'opérateur AND `&&` effectue les opérations suivantes :

- Évalue les opérandes de gauche à droite.
- Pour chaque opérande, il le convertit en booléen. Si le résultat est `false`, arrêtez et retournez la valeur d'origine de cet opérande.
- Si tous les autres opérandes ont été évalués (c’est-à-dire tous étaient vrais), retournez le dernier opérande.

En d'autres termes, une chaîne de AND `&&` renvoie la première valeur `false` ou la dernière valeur si aucune valeur `false` n'a été trouvée.

Les règles ci-dessus sont similaires à OR. La différence est que AND retourne la première valeur `false` tandis que OR renvoie la première valeur `true`.

Exemples :

```js run
// si le premier opérande est vrai,
// AND retourne le second opérande :
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// si le premier opérande est faux,
// AND le retourne. Le deuxième opérande est ignoré
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
```

Nous pouvons également transmettre plusieurs valeurs à la suite sur une même ligne. Voyez comment le premier faux est retourné :

```js run
alert( 1 && 2 && null && 3 ); // null
```

Lorsque toutes les valeurs sont vraies, la dernière valeur est renvoyée :

```js run
alert( 1 && 2 && 3 ); // 3, la dernière
```

````smart header="La précédence de AND `&&` est supérieure à OR `||`"
La priorité de l'opérateur AND `&&` est supérieure à OR `||`.

Donc, le code `a && b || c && d` est essentiellement le même que si `&&` était entre parenthèses: `(a && b) || (c && d)`.
````

````warn header="Ne remplacez pas `if` par `||` ou `&&`"
Parfois, les gens utilisent l'opérateur AND `&&` comme "plus court pour écrire `if`".

Par exemple :

```js run
let x = 1;

(x > 0) && alert( 'Greater than zero!' );
```

L'action dans la partie droite de `&&` ne s'exécutera que si l'évaluation lui parvient. C'est-à-dire que seulement si `(x > 0)` est vrai.

Donc, nous avons une analogie pour :

```js run
let x = 1;

if (x > 0) alert( 'Greater than zero!' );
```

Bien que la variante avec `&&` semble plus courte, `if` est plus évidente et a tendance à être un peu plus lisible. Nous recommandons donc d'utiliser chaque construction dans son but : utilisez `if` si nous voulons `if` et utilisez `&&` si nous voulons ET.
````


## ! (NOT)

L'opérateur booléen NOT est représenté par un point d'exclamation `!`.

La syntaxe est assez simple :

```js
result = !value;
```

L'opérateur accepte un seul argument et effectue les opérations suivantes :

1. Convertit l'opérande en type booléen : `true/false`.
2. Renvoie la valeur inverse.

Par exemple :

```js run
alert( !true ); // false
alert( !0 ); // true
```

Un double NOT `!!` est parfois utilisé pour convertir une valeur en type booléen :

```js run
alert( !!"non-empty string" ); // true
alert( !!null ); // false
```

C'est-à-dire que le premier NOT convertit la valeur en booléen et retourne l'inverse, et que le second NOT l'inverse encore. À la fin, nous avons une conversion valeur à booléen simple.

Il existe un moyen un peu plus verbeux de faire la même chose -- une fonction `Boolean` intégrée :

```js run
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
```

La précédence de NOT `!` est la plus élevée de tous les opérateurs binaire, il est donc toujours exécuté en premier, avant les autres.


================================================
FILE: 1-js/02-first-steps/12-nullish-coalescing-operator/article.md
================================================
# L'opérateur de coalescence des nuls '??'

[recent browser="new"]

L'opérateur de coalescence des nuls est écrit sous la forme de deux points d'interrogation `??`.

Comme il traite `null` et `undefined` de la même manière, nous utiliserons un terme spécial ici, dans cet article. Par souci de brièveté, nous dirons qu'une expression est "définie" lorsqu'elle n'est ni `null` ni `undefined`.

Le résultat de `a ?? b` est :
- si `a` est défini, alors `a`,
- si `a` n'est pas défini, alors `b`.

En d'autres termes, `??` renvoie le premier argument s'il n'est pas `null`/`undefined`. Sinon, le second.

L'opérateur de coalescence des nuls n'est pas complètement nouveau. C'est juste une belle syntaxe pour obtenir la première valeur "defined" des deux.

Nous pouvons réécrire `result = a ?? b` en utilisant les opérateurs que nous connaissons déjà, comme ceci :

```js
result = (a !== null && a !== undefined) ? a : b;
```

Maintenant, il devrait être absolument clair ce que fait `??`. Voyons où cela aide.

Le cas d'utilisation courant de `??` est de fournir une valeur par défaut.

Par exemple, nous affichons ici `user` si sa valeur n'est pas `null`/`undefined`, sinon `Anonymous` :

```js run
let user;

alert(user ?? "Anonymous"); // Anonymous (user is undefined)
```

Voici l'exemple avec `user` attribué à un nom :

```js run
let user = "John";

alert(user ?? "Anonymous"); // John (user is not null/undefined)
```

Nous pouvons également utiliser une séquence de `??` pour sélectionner la première valeur dans une liste qui n'est pas `null`/`undefined`.

Disons que nous avons les données d'un utilisateur dans les variables `firstName`, `lastName` ou `nickName`. Tous peuvent être indéfinis, si l'utilisateur décide de ne pas entrer de valeurs correspondantes.

Nous aimerions afficher le nom d'utilisateur à l'aide de l'une de ces variables, ou afficher "Anonyme" si toutes sont `null`/`undefined`.

Utilisons l'opérateur `??` pour cela :

```js run
let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// affiche la première valeur définie :
*!*
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
*/!*
```

## Comparaison avec ||

L'opérateur OR `||` peut être utilisé de la même manière que `??`, comme il a été décrit dans le [chapitre précédent](info:logical-operators#or-finds-the-first-truthy-value).

Par exemple, dans le code ci-dessus, nous pourrions remplacer `??` par `||` et toujours obtenir le même résultat :

```js run
let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// affiche la première valeur vraie :
*!*
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
*/!*
```

Historiquement, l'opérateur OR `||` était là en premier. Il existe depuis le début de JavaScript, donc les développeurs l'utilisaient à de telles fins depuis longtemps.

D'un autre côté, l'opérateur de coalescence des nuls `??` n'a été ajouté à JavaScript que récemment, et la raison en était que les gens n'étaient pas tout à fait satisfaits de `||`.

La différence importante entre eux est que :
- `||` renvoie la première valeur *vraie*.
- `??` renvoie la première valeur *définie*.

En d'autres termes, `||` ne fait pas la distinction entre `false`, `0`, une chaîne vide `" "` et `null`/`undefined`. Ce sont tous les mêmes -- des valeurs fausses. Si l'un de ceux-ci est le premier argument de `||`, alors nous obtiendrons le deuxième argument comme résultat.

Dans la pratique cependant, nous pouvons vouloir utiliser la valeur par défaut uniquement lorsque la variable est `null`/`undefined`. Autrement dit, lorsque la valeur est vraiment inconnue/non définie.

Par exemple, considérez ceci :

```js run
let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0
```

- L'expression `height || 100` vérifie que `height` est une valeur fausse, et c'est `0`, elle est fausse en effet.
    - donc le résultat de `||` est le deuxième argument, `100`.
- L'expression `height ?? 100` vérifie que `height` est `null`/`undefined`, et ce n'est pas le cas,
    - donc le résultat est `height` "tel quel", c'est-à-dire `0`.

En pratique, la hauteur zéro est souvent une valeur valide, qui ne doit pas être remplacée par la valeur par défaut. Alors `??` fait ce qu'il faut.

## Priorité

La priorité de l'opérateur `??` est la même que celle de `||`. Elle est égale à `3` dans le [tableau MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table).

Cela signifie que, tout comme `||`, l'opérateur de coalescence des nuls `??` est évalué avant `=` et `?`, mais après la plupart des autres opérations, telles que `+`, `*`.

Nous devrons donc peut-être ajouter des parenthèses dans des expressions comme celle-ci :

```js run
let height = null;
let width = null;

// important : utilisez des parenthèses
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000
```

Sinon, si nous omettons les parenthèses, alors que `*` a une priorité plus élevée que `??`, il s'exécuterait en premier, conduisant à des résultats incorrects.

```js
// sans parenthèses
let area = height ?? 100 * width ?? 50;

// ...fonctionne de cette façon (pas ce que nous voulons) :
let area = height ?? (100 * width) ?? 50;
```

### En utilisant ?? avec && ou ||

Pour des raisons de sécurité, JavaScript interdit d'utiliser `??` avec les opérateurs `&&` et `||`, à moins que la priorité ne soit explicitement spécifiée entre parenthèses.

Le code ci-dessous déclenche une erreur de syntaxe :

```js run
let x = 1 && 2 ?? 3; // Syntax error
```

La limitation est sûrement discutable, mais elle a été ajoutée à la spécification du langage dans le but d'éviter les erreurs de programmation, quand les gens commencent à passer de `||` à `??`.

Utilisez des parenthèses explicites pour la contourner :

```js run
*!*
let x = (1 && 2) ?? 3; // fonctionne
*/!*

alert(x); // 2
```

## Résumé

- L'opérateur de coalescence des nuls `??` fournit un moyen court de choisir une valeur "définie" à partir d'une liste.

    Il est utilisé pour attribuer des valeurs par défaut aux variables :

    ```js
    // configurer height = 100, si height est null ou undefined
    height = height ?? 100;
    ```

- L'opérateur `??` a une priorité très faible, un peu plus élevée que `?` et `=`, pensez donc à ajouter des parenthèses lors de son utilisation dans une expression.
- Il est interdit de l'utiliser avec `||` ou `&&` sans parenthèses explicites.


================================================
FILE: 1-js/02-first-steps/13-while-for/1-loop-last-value/solution.md
================================================
La réponse : `1`.

```js run
let i = 3;

while (i) {
  alert( i-- );
}
```

Chaque itération de boucle diminue `i` de `1`. La vérification `while(i)` arrête la boucle lorsque `i = 0`.

Par conséquent, les étapes de la boucle forment la séquence suivante ("boucle décomposée") :

```js
let i = 3;

alert(i--); // affiche 3, diminue i à 2

alert(i--) // affiche 2, diminue i à 1

alert(i--) // affiche 1, diminue i à 0

// terminé, la vérification while(i) termine la boucle
```


================================================
FILE: 1-js/02-first-steps/13-while-for/1-loop-last-value/task.md
================================================
importance: 3

---

# Dernière valeur de boucle

Quelle est la dernière valeur affichée par ce code ? Pourquoi ?

```js
let i = 3;

while (i) {
  alert( i-- );
}
```


================================================
FILE: 1-js/02-first-steps/13-while-for/2-which-value-while/solution.md
================================================
L'exercice montre comment les formes postfix/prefix peuvent conduire à des résultats différents lorsqu’ils sont utilisés dans des comparaisons.

1. **De 1 à 4**

    ```js run
    let i = 0;
    while (++i < 5) alert( i );
    ```

    La première valeur est `i=1`, parce que `++i` incrémente d'abord `i` puis renvoie la nouvelle valeur. La première comparaison est donc `1 < 5` et `alert` indique `1`.

    Ensuite, viennent `2,3,4…` -- les valeurs apparaissent les unes après les autres. La comparaison utilise toujours la valeur incrémentée, car `++` est avant la variable.

    Enfin, `i=4` est incrémenté à `5`, la comparaison `while(5 < 5)` échoue et la boucle s'arrête. Donc `5` n'est pas affiché.
2. **De 1 à 5**

    ```js run
    let i = 0;
    while (i++ < 5) alert( i );
    ```

    La première valeur est encore `i=1`. La forme postfixée de `i++` incrémente `i` puis renvoie *l'ancienne* valeur, la comparaison `i++ < 5` utilisera donc `i=0` (contrairement à `++i < 5`).

    Mais l'appel d'`alert` est séparé. C’est une autre instruction qui s’exécute après l’incrémentation et la comparaison. Donc, on obtient `i=1`.

    Ensuite viennent `2,3,4…`

    Arrêtons-nous sur `i=4`. Le préfixe sous forme `++i` l'incrémenterait et utiliserait `5` dans la comparaison. Mais ici nous avons la forme postfixée `i++`. Donc, `i` augmente à `5`, mais renvoie l'ancienne valeur. Par conséquent, la comparaison est en réalité `while(4 < 5)` -- true, et le contrôle continue à `alert`.

    La valeur `i=5` est la dernière, car à l'étape suivante `while(5 <5)` est faux. 


================================================
FILE: 1-js/02-first-steps/13-while-for/2-which-value-while/task.md
================================================
importance: 4

---

# Quelles valeurs affiche la boucle while ?

A votre avis, quelles sont les valeurs affichées pour chaque boucle ?  Notez-les puis comparer avec la réponse.

Les deux boucles affichent-elles les mêmes valeurs dans l'`alert` ou pas ?

1. Le préfixe sous forme `++i` :

    ```js
    let i = 0;
    while (++i < 5) alert( i );
    ```
2. Le postfixe sous forme `i++` :

    ```js
    let i = 0;
    while (i++ < 5) alert( i );
    ```


================================================
FILE: 1-js/02-first-steps/13-while-for/3-which-value-for/solution.md
================================================
**La réponse: de `0` à `4` dans les deux cas.**

```js run
for (let i = 0; i < 5; ++i) alert( i );

for (let i = 0; i < 5; i++) alert( i );
```

Cela peut être facilement déduit de l'algorithme de `for` :

1. Exécute une fois `i = 0` avant tout (début).
2. Vérifie l'état `i < 5`
3. Si `true` -- execute le corps de la boucle `alert(i)`, et ensuite `i++`

L'incrément `i++` est séparé de la vérification de condition (2). C’est juste une autre déclaration.

La valeur renvoyée par l’incrémentation n’est pas utilisée ici, il n’y a donc pas de différence entre `i++` et `++i`.


================================================
FILE: 1-js/02-first-steps/13-while-for/3-which-value-for/task.md
================================================
importance: 4

---

# Quelles valeurs sont affichées par la boucle "for" ?

Pour chaque boucle, notez les valeurs qui vont s'afficher. Ensuite, comparez avec la réponse.

Les deux boucles `alert` les mêmes valeurs ou pas ?

1. La forme postfix :

    ```js
    for (let i = 0; i < 5; i++) alert( i );
    ```
2. La forme préfix :

    ```js
    for (let i = 0; i < 5; ++i) alert( i );
    ```


================================================
FILE: 1-js/02-first-steps/13-while-for/4-for-even/solution.md
================================================


```js run demo
for (let i = 2; i <= 10; i++) {
  if (i % 2 == 0) {
    alert( i );
  }
}
```

Ici nous utilisons l'opérateur “modulo” `%` pour obtenir le reste et vérifier si c'est pair ou pas.


================================================
FILE: 1-js/02-first-steps/13-while-for/4-for-even/task.md
================================================
importance: 5

---

# Extraire les nombres pairs dans la boucle

Utilisez la boucle `for` pour afficher les nombres pairs de `2` à `10`.

[demo]


================================================
FILE: 1-js/02-first-steps/13-while-for/5-replace-for-while/solution.md
================================================


```js run
let i = 0;
while (i < 3) {
  alert( `number ${i}!` );
  i++;
}
```



================================================
FILE: 1-js/02-first-steps/13-while-for/5-replace-for-while/task.md
================================================
importance: 5

---

# Remplacer "for" par "while"

Réécrivez le code en modifiant la boucle `for` en `while` sans modifier son comportement (la sortie doit rester la même).

```js run
for (let i = 0; i < 3; i++) {
  alert( `number ${i}!` );
}
```



================================================
FILE: 1-js/02-first-steps/13-while-for/6-repeat-until-correct/solution.md
================================================

```js run demo
let num;

do {
  num = prompt("Enter a number greater than 100?", 0);
} while (num <= 100 && num);
```

La boucle `do..while` se répète tant que les deux vérifications sont vrai :

1. La vérification de `num <= 100` - c’est-à-dire que la valeur entrée n’est toujours pas supérieure à `100`.
2. La vérification que `&& num` est `false` lorsque `num` est `null` ou une chaîne vide. Ensuite, la boucle `while` s'arrête aussi.

P.S. Si `num` est `null`, alors `num <= 100` est `true`. Par conséquent, sans la seconde vérification, la boucle ne s’arrêterait pas si l’utilisateur cliquait sur CANCEL. Les deux vérifications sont obligatoires.


================================================
FILE: 1-js/02-first-steps/13-while-for/6-repeat-until-correct/task.md
================================================
importance: 5

---

# Répéter jusqu'à ce que l'entrée soit correcte

Ecrivez une boucle qui demande un nombre supérieur à `100`. Si le visiteur saisit un autre numéro, demandez-lui de le saisir à nouveau.

La boucle doit demander un numéro jusqu'à ce que le visiteur saisisse un nombre supérieur à `100` ou annule l'entrée/entre une ligne vide.

Ici, nous pouvons supposer que le visiteur ne saisit que des chiffres. Il n’est pas nécessaire de mettre en œuvre un traitement spécial pour une entrée non numérique dans cette tâche.

[demo]


================================================
FILE: 1-js/02-first-steps/13-while-for/7-list-primes/solution.md
================================================
Il existe de nombreux algorithmes pour cette tâche.

Utilisons une boucle imbriquée :

```js
Pour chaque i dans l'intervalle {
  vérifier si i a un diviseur de 1..i
  si oui => la valeur n'est pas un nombre premier
  si non => la valeur est un nombre premier, affichez-le
}
```

Un code utilisant un label :

```js run
let n = 10;

nextPrime:
for (let i = 2; i <= n; i++) { // Pour chaque i...

  for (let j = 2; j < i; j++) { // cherche un diviseur ..
    if (i % j == 0) continue nextPrime; // pas un premier, on passe au prochain i
  }

  alert( i ); // un premier
}
```

Il y a beaucoup d’espace pour l’optimiser. Par exemple, nous pourrions rechercher les diviseurs de `2` à la racine carrée de `i`. Quoi qu’il en soit, si nous voulons être vraiment efficaces pour les grands intervalles, nous devons changer d’approche et nous baser sur des mathématiques avancées et des algorithmes complexes comme [Crible quadratique](https://fr.wikipedia.org/wiki/Crible_quadratique), [Crible algébrique](https://fr.wikipedia.org/wiki/Crible_alg%C3%A9brique) etc.


================================================
FILE: 1-js/02-first-steps/13-while-for/7-list-primes/task.md
================================================
importance: 3

---

# Extraire des nombres premiers

Un nombre entier supérieur à 1 est appelé un [Nombre premier](https://fr.wikipedia.org/wiki/Nombre_premier) s'il ne peut être divisé sans reste par rien d'autre que 1 et lui-même.

En d’autres termes, `n > 1` est un nombre premier s’il ne peut être divisé de manière égale par autre chose que `1` et `n`.

Par exemple, `5` est un nombre premier, car il ne peut pas être divisé sans reste par `2`, `3` et `4`.

**Écrivez un code qui produit les nombres premiers dans l’intervall e 2 à n.**

Pour `n = 10`, le résultat sera `2`,`3`,`5`,`7`.

P.S. Le code devrait fonctionner pour n'importe quel `n` et aucune valeur fixe ne doit être codé en dur.


================================================
FILE: 1-js/02-first-steps/13-while-for/article.md
================================================
# Boucles : while et for

Nous avons souvent besoin d'effectuer des actions similaires plusieurs fois de suite.

Par exemple, lorsque nous devons extraire des marchandises d'une liste les unes à la suite des autres. Ou exécutez simplement le même code pour chaque numéro de 1 à 10.

*Les boucles* permettent de répéter plusieurs fois la même partie du code.

```smart header="Les boucles for..of et for..in"
Une petite annonce pour les lecteurs avertis.

Cet article ne couvre que les boucles de base : `while`, `do..while` et `for(..;..;..)`.

Si vous êtes venu à cet article à la recherche d'autres types de boucles, voici les pointeurs :

- Voir [for..in](info:object#forin) pour boucler sur les propriétés de l'objet.
- Voir [for..of](info:array#loops) et [iterables](info:iterable) pour boucler sur des tableaux et des objets itérables.

Sinon, lisez la suite.
```

## La boucle "while"

La boucle `while` a la syntaxe suivante :

```js
while (condition) {
  // code
  // appelé "loop body" ("corps de boucle")
}
```

Tant que la `condition` est vraie, le `code` du corps de la boucle est exécuté.

Par exemple, la boucle ci-dessous affiche `i` tant que `i < 3` :

```js run
let i = 0;
while (i < 3) { // affiche 0, puis 1, puis 2
  alert( i );
  i++;
}
```

Une unique exécution du corps de la boucle est appelée **une itération**. La boucle dans l'exemple ci-dessus fait trois itérations.

S'il n'y avait pas d'`i++` dans l'exemple ci-dessus, la boucle se répèterait (en théorie) pour toujours. En pratique, le navigateur fournit des moyens d’arrêter ces boucles, et pour JavaScript côté serveur, nous pouvons tuer le processus.

Toute expression ou variable peut être une condition de boucle, pas seulement une comparaison. Ils sont évalués et convertis en un booléen par `while`.

Par exemple, le moyen le plus court d'écrire `while (i != 0)` pourrait être `while (i)` :

```js run
let i = 3;
*!*
while (i) { // quand i devient 0, la condition devient fausse et la boucle s'arrête
*/!*
  alert( i );
  i--;
}
```

````smart header="Les accolades ne sont pas requis pour un corps à une seule ligne"
Si le corps de la boucle a une seule déclaration, nous pouvons omettre les accolades `{…}` :

```js run
let i = 3;
*!*
while (i) alert(i--);
*/!*
```
````

## La boucle "do…while"

La vérification de la condition peut être déplacée *sous* le corps de la boucle en utilisant la syntaxe `do..while` :

```js
do {
  // corps de la boucle
} while (condition);
```

La boucle exécute d'abord le corps, puis vérifie la condition et, tant que c'est vrai, l'exécute encore et encore.

Par exemple :

```js run
let i = 0;
do {
  alert( i );
  i++;
} while (i < 3);
```

Cette forme de syntaxe est rarement utilisée, sauf lorsque vous souhaitez que le corps de la boucle s'exécute **au moins une fois**, quelle que soit la condition. Habituellement, l'autre forme est préférée : `while(…) {…}`.

## La boucle "for"

La boucle `for` est plus complexe, mais c’est aussi la boucle la plus utilisée.

Cela ressemble à ceci :

```js
for (début; condition; étape) {
  // ... corps de la boucle ...
}
```

Apprenons la signification de ces parties par l'exemple. La boucle ci-dessous exécute `alert(i)` pour `i` en partant de `0` jusqu'à `3` (mais non compris) :

```js run
for (let i = 0; i < 3; i++) { // affiche 0, puis 1, puis 2
  alert(i);
}
```

Examinons la déclaration `for` partie par partie :

| partie    |            |                                                                                        |
|-----------|------------|----------------------------------------------------------------------------------------|
| début     | `let i = 0`    | Exécute une fois en entrant dans la boucle.                                            |
| condition | `i < 3`    | Vérifié avant chaque itération de la boucle, en cas d'échec, la boucle s'arrête.       |
| corps     | `alert(i)` | Exécute encore et encore tant que la condition est vraie                               |
| étape     | `i++`      | Exécute après le corps à chaque itération |


L'algorithme de boucle général fonctionne comme ceci :
```
Exécuter le début
→ (si condition → exécuter le corps et exécuter l'étape)
→ (si condition → exécuter le corps et exécuter l'étape)
→ (si condition → exécuter le corps et exécuter l'étape)
→ ...
```

C'est-à-dire que `begin` est exécuté une fois, puis itéré : après chaque test de `condition`, `body` et `step` sont exécutés.

Si vous débutez dans les boucles, il pourrait être utile de revenir à l'exemple et de reproduire comment elle s'exécute pas à pas sur une feuille de papier.

Voici ce qui se passe exactement dans notre cas :

```js
// for (let i = 0; i < 3; i++) alert(i)

// exécute début
let i = 0
// si condition → exécuter le corps et exécuter l'étape
if (i < 3) { alert(i); i++ }
// si condition → exécuter le corps et exécuter l'étape
if (i < 3) { alert(i); i++ }
// si condition → exécuter le corps et exécuter l'étape
if (i < 3) { alert(i); i++ }
// ... fini, parce que maintenant i == 3
```

````smart header="Déclaration de variable en ligne"
Ici, la variable "counter" `i` est déclarée directement dans la boucle. Cela s'appelle une déclaration de variable "en ligne". De telles variables ne sont visibles que dans la boucle.

```js run
for (*!*let*/!* i = 0; i < 3; i++) {
  alert(i); // 0, 1, 2
}
alert(i); // erreur, pas de variable
```

Au lieu de définir une variable, nous pouvons en utiliser une existante :

```js run
let i = 0;

for (i = 0; i < 3; i++) { // utiliser une variable existante
  alert(i); // 0, 1, 2
}

alert(i); // 3, visible, car déclaré en dehors de la boucle
```
````


### Sauter des parties

Toute partie de `for` peut être ignorée.

Par exemple, nous pouvons omettre `le début` si nous n'avons rien à faire au début de la boucle.

Comme ici :

```js run
let i = 0; // nous avons i déjà déclaré et assigné

for (; i < 3; i++) { // pas besoin de "début"
  alert( i ); // 0, 1, 2
}
```

Nous pouvons également supprimer la partie `étape` :

```js run
let i = 0;

for (; i < 3;) {
  alert( i++ );
}
```

La boucle est devenue identique à `while (i < 3)`.

Nous pouvons tout supprimer, créant ainsi une boucle infinie :

```js
for (;;) {
  // répète sans limites
}
```

Veuillez noter que les deux les points-virgules `;` de `for` doivent être présents, sinon ce serait une erreur de syntaxe.

## Briser la boucle

Normalement, la boucle sort quand la condition devient fausse.

Mais nous pouvons forcer la sortie à tout moment. Il y a une directive spéciale appelée `break` pour cela.

Par exemple, la boucle ci-dessous demande à l'utilisateur une série de chiffres, mais "se casse" quand aucun numéro n'est entré :

```js run
let sum = 0;

while (true) {

  let value = +prompt("Entrez un nombre", '');

*!*
  if (!value) break; // (*)
*/!*

  sum += value;

}
alert( 'Sum: ' + sum );
```

La directive `break` est activée sur la ligne `(*)` si l'utilisateur entre une ligne vide ou annule l'entrée. Il arrête la boucle immédiatement, en passant le contrôle à la première ligne après la boucle. À savoir, `alert`.

La combinaison "boucle infinie + `break` au besoin" est idéale pour les situations où la condition doit être vérifiée non pas au début / à la fin de la boucle, mais au milieu, voire à plusieurs endroits du corps.

## Continuer jusqu'à la prochaine itération [#continue]

La directive `continue` est une "version plus légère" de `break`. Cela n'arrête pas toute la boucle. Au lieu de cela, elle arrête l'itération en cours et force la boucle à en démarrer une nouvelle (si la condition le permet).

Nous pouvons l’utiliser si nous avons terminé l’itération en cours et aimerions passer à la suivante.

La boucle ci-dessous utilise `continue` pour ne produire que des valeurs impaires :

```js run no-beautify
for (let i = 0; i < 10; i++) {

  // si vrai, saute le reste du corps
  *!*if (i % 2 == 0) continue;*/!*

  alert(i); // 1, ensuite 3, 5, 7, 9
}
```

Pour les valeurs paires de `i`, la directive `continue` arrête l'exécution du corps en passant le contrôle à la prochaine itération de `for` (avec le nombre suivant). Donc, l'`alert` n'est appelée que pour les valeurs impaires.

````smart header="La directive `continue` aide à réduire le niveau d'imbrication"
Une boucle affichant des valeurs impaires pourrait ressembler à ceci :

```js run
for (let i = 0; i < 10; i++) {

  if (i % 2) {
    alert( i );
  }

}
```

D'un point de vue technique, c'est identique à l'exemple du dessus. Certes, nous pouvons simplement envelopper le code dans un bloc `if` au lieu de `continue`.

Mais comme effet secondaire, nous avons obtenu un niveau d'imbrication supplémentaire (l'appel de l'`alert` à l'intérieur des accolades). Si le code à l'intérieur du `if` est plus long que quelques lignes, la lisibilité globale peut en être réduite.
````

````warn header="Pas de `break/continue` à droite de '?'"
Veuillez noter que les constructions de syntaxe qui ne sont pas des expressions ne peuvent pas être utilisées avec l'opérateur ternaire `?`. Tout particulièrement les directives telles que `break/continue` ne sont pas autorisées.

Par exemple, si nous prenons ce code :

```js
if (i > 5) {
  alert(i);
} else {
  continue;
}
```

… Et le réécrivons à l'aide d'un point d'interrogation :

```js no-beautify
(i > 5) ? alert(i) : *!*continue*/!*; // continue n'est pas autorisé ici
```

… Ensuite cesse de fonctionner : il y a une erreur de syntaxe.


C’est une autre raison pour ne pas utiliser l'opérateur point d’interrogation `?` au lieu de `if`.
````

## Des labels pour break/continue

Parfois, nous devons sortir de plusieurs boucles imbriquées en même temps.

Par exemple, dans le code ci-dessous, nous bouclons sur `i` et `j` pour demander les coordonnées `(i, j)` de `(0,0)` à `(2,2)` :

```js run no-beautify
for (let i = 0; i < 3; i++) {

  for (let j = 0; j < 3; j++) {

    let input = prompt(`Value at coords (${i},${j})`, '');

    // Et si nous voulons sortir d'ici à Done (ci-dessous) ?
  }
}

alert('Done!');
```

Nous avons besoin d'un moyen d'arrêter le processus si l'utilisateur annule la saisie.

Le `break` ordinaire après `input` ne ferait que briser la boucle intérieure. Ce n’est pas suffisant -- les *labels* viennent à la rescousse.

Une *label* est un identifiant avec deux points avant une boucle :

```js
labelName: for (...) {
  ...
}
```

L'instruction `break <labelName>` dans la boucle interrompt tout le bloc de code relatif au label.

Comme ici :

```js run no-beautify
*!*outer:*/!* for (let i = 0; i < 3; i++) {

  for (let j = 0; j < 3; j++) {

    let input = prompt(`Value at coords (${i},${j})`, '');

    // si une chaîne est vide ou annulée, alors rompre les deux boucles
    if (!input) *!*break outer*/!*; // (*)

    // faire quelque chose avec la valeur …
  }
}

alert('Done!');
```

Dans le code ci-dessus, `break outer` regarde vers le haut le label `outer` et sort de cette boucle.

Donc, le contrôle va directement de `(*)` à `alert('Done!')`.

Nous pouvons également déplacer le label sur une ligne séparée :

```js no-beautify
outer:
for (let i = 0; i < 3; i++) { ... }
```

La directive `continue` peut également être utilisée avec un label. Dans ce cas, l'exécution passe à l'itération suivante de la boucle labellisée.

````warn header="Les labels ne permettent pas de \"sauter\" n'importe où"
Les labels ne nous permettent pas de sauter dans un endroit arbitraire du code.

Par exemple, il est impossible de faire ceci :

```js
break label;  // saute au label ci-dessous (ne fonctionne pas)

label: for (...)
```

Une directive `break` doit être à l'intérieur d'un bloc de code. Techniquement, tout bloc de code étiqueté fera l'affaire, par exemple :

```js
label: {
  // ...
  break label; // works
  // ...
}
```

... Bien que 99,9% du temps les `break` utilisés sont à l'intérieur de boucles, comme nous l'avons vu dans les exemples ci-dessus.

Un `continue` n'est possible que depuis l'intérieur d'une boucle.
````

## Résumé

Nous avons couvert 3 types de boucles :

- `while` -- La condition est vérifiée avant chaque itération.
- `do..while` -- La condition est vérifiée après chaque itération.
- `for (;;)` -- La condition est vérifiée avant chaque itération, des paramètres supplémentaires sont disponibles.

Pour créer une boucle "infinie", on utilise généralement la construction `while(true)`. Une telle boucle, comme toute autre, peut être stoppée avec la directive `break`.

Si nous ne voulons rien faire avec l’itération actuelle et que nous souhaitons avancer jusqu'à la suivante, la directive `continue` nous permet de faire cela.

`break/continue` accepte les labels précédents la boucle. Un label est le seul moyen de `break/continue` pour échapper à l'imbrication et accéder en dehors de la boucle.


================================================
FILE: 1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/solution.md
================================================
Pour correspondre précisément à la fonctionnalité du `switch`, le `if` doit utiliser une comparaison stricte `'==='`.

Cependant, pour des chaînes de caractères données, un simple `'=='` fonctionne également.

```js no-beautify
if(browser == 'Edge') {
  alert("You've got the Edge!");
} else if (browser == 'Chrome'
 || browser == 'Firefox'
 || browser == 'Safari'
 || browser == 'Opera') {
  alert( 'Okay we support these browsers too' );
} else {
  alert( 'We hope that this page looks ok!' );
}
```

Remarque: la construction `browser == 'Chrome' || navigateur == 'Firefox'…` est divisée en plusieurs lignes pour une meilleure lisibilité.

Mais la construction `switch` est toujours plus propre et plus descriptive.


================================================
FILE: 1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/task.md
================================================
importance: 5

---

# Réécrire le "switch" dans un "if"

Écrivez le code en utilisant `if..else` qui correspondrait au `switch` suivant :

```js
switch (browser) {
  case 'Edge':
    alert( "You've got the Edge!" );
    break;

  case 'Chrome':
  case 'Firefox':
  case 'Safari':
  case 'Opera':
    alert( 'Okay we support these browsers too' );
    break;

  default:
    alert( 'We hope that this page looks ok!' );
}
```



================================================
FILE: 1-js/02-first-steps/14-switch/2-rewrite-if-switch/solution.md
================================================
Les deux premiers contrôles se transforment en deux `case`. Le troisième contrôle est divisé en deux `case` :

```js run
let a = +prompt('a?', '');

switch (a) {
  case 0:
    alert( 0 );
    break;

  case 1:
    alert( 1 );
    break;

  case 2:
  case 3:
    alert( '2,3' );
*!*
    break;
*/!*
}
```

Remarque: le `break` en bas n'est pas requis. Mais nous le mettons pour rendre le code à l'épreuve du temps.

Dans le futur, il est possible que nous voulions ajouter un `case` supplémentaire, par exemple le `case 4`. Et si nous oublions d’ajouter un `break` avant, à la fin du `case 3`, il y aura une erreur. C’est donc une sorte d’assurance.


================================================
FILE: 1-js/02-first-steps/14-switch/2-rewrite-if-switch/task.md
================================================
importance: 4

---

# Réécrire le "if" dans un "switch"

Réécrivez le code ci-dessous en utilisant une seule instruction `switch` :

```js run
let a = +prompt('a?', '');

if (a == 0) {
  alert( 0 );
}
if (a == 1) {
  alert( 1 );
}

if (a == 2 || a == 3) {
  alert( '2,3' );
}
```



================================================
FILE: 1-js/02-first-steps/14-switch/article.md
================================================
# La déclaration "switch"

Une instruction `switch` peut remplacer plusieurs vérification `if`.

Cela donne un moyen plus descriptif de comparer une valeur avec plusieurs variantes.

## La syntaxe

Le `switch` a un ou plusieurs blocs `case` (cas) et une valeur par défaut facultative.

Cela ressemble à ceci :

```js no-beautify
switch(x) {
  case 'value1':  // si (x === 'value1')
    ...
    [break]

  case 'value2':  // si (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}
```

- La valeur de `x` est vérifiée pour une égalité stricte avec la valeur du premier `case` (c'est-à-dire, `value1`), puis du second (`value2`) et ainsi de suite.
- Si l'égalité est trouvée, `switch` commence à exécuter le code à partir du `case` correspondant, jusqu'au prochain `break` (ou jusqu'à la fin du switch).
- Si aucun cas ne correspond, le code par défaut (`default`) est exécuté (s'il existe).

## Un exemple

Un exemple de `switch` (le code exécuté est mis en évidence) :

```js run
let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
    break;
*!*
  case 4:
    alert( 'Exactly!' );
    break;
*/!*
  case 5:
    alert( 'Too big' );
    break;
  default:
    alert( "I don't know such values" );
}
```

Ici, le `switch` commence à comparer `a` avec le premier `case` dont la valeur est `3`. La correspondance échoue.

Ensuite `4`, c’est une correspondance. L’exécution commence donc à partir du `case 4` jusqu’au prochain `break`.

**S'il n'y a pas de `break`, l'exécution continue avec le `case` suivant sans aucun contrôle.**

Un exemple sans `break`:

```js run
let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
*!*
  case 4:
    alert( 'Exactly!' );
  case 5:
    alert( 'Too big' );
  default:
    alert( "I don't know such values" );
*/!*
}
```

Dans l'exemple ci-dessus, nous verrons l'exécution séquentielle de trois `alert` :

```js
alert( 'Exactly!' );
alert( 'Too big' );
alert( "I don't know such values" );
```

````smart header="Toute expression peut être un argument `switch/case`"
`Switch` et `case` permettent des expressions arbitraires.

Par exemple :

```js run
let a = "1";
let b = 0;

switch (+a) {
*!*
  case b + 1:
    alert("this runs, because +a is 1, exactly equals b+1");
    break;
*/!*

  default:
    alert("this doesn't run");
}
```

Ici `+a` donne `1`, qui est comparé à `b + 1` dans le `case`, et le code correspondant est exécuté.
````

## Groupement de "case"

Plusieurs variantes de `case` partageant le même code peuvent être regroupées.

Par exemple, si nous voulons que le même code soit exécuté pour les `case 3` et `case 5` :

```js run no-beautify
let a = 2 + 2;

switch (a) {
  case 4:
    alert('Right!');
    break;

*!*
  case 3: // (*) grouped two cases
  case 5:
    alert('Wrong!');
    alert("Why don't you take a math class?");
    break;
*/!*

  default:
    alert('The result is strange. Really.');
}
```

Maintenant, les `3` et `5` affichent le même message.

La possibilité de "grouper" les `case` est un effet secondaire de la façon dont le `switch/case` fonctionne sans `break`. Ici, l’exécution du `case 3` commence à partir de la ligne `(*)` et passe par le `case 5`, car il n’y a pas de `break`.

## Le type compte

Soulignons que le contrôle d’égalité est toujours strict. Les valeurs doivent être du même type pour correspondre.

Par exemple, considérons le code suivant :

```js run
let arg = prompt("Enter a value?");

switch (arg) {
  case '0':
  case '1':
    alert( 'One or zero' );
    break;

  case '2':
    alert( 'Two' );
    break;

  case 3:
    alert( 'Never executes!' );
    break;

  default:
    alert( 'An unknown value' );
}
```

1. Pour `0`, `1`, la première `alert` est exécutée.
2. Pour `2`, la deuxième `alert` est exécutée.
3. Mais pour `3`, le résultat du prompt est une chaîne de caractères `"3"`, ce qui n’est pas strictement égal `===` au chiffre `3`. Nous avons donc un code mort dans le `case 3` ! La variante par défaut sera donc exécutée.


================================================
FILE: 1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md
================================================
Aucune différence.

Dans les deux cas, `return confirm('Did parents allow you?')` s'exécute exactement lorsque la condition `if` est fausse.


================================================
FILE: 1-js/02-first-steps/15-function-basics/1-if-else-required/task.md
================================================
importance: 4

---

# Est-ce que "else" est requis ?

La fonction suivante renvoie `true` si le paramètre `age` est supérieur à `18`.

Sinon, il demande une confirmation et renvoie son résultat :

```js
function checkAge(age) {
  if (age > 18) {
    return true;
*!*
  } else {
    // ...
    return confirm('Did parents allow you?');
  }
*/!*
}
```

La fonction fonctionnera-t-elle différemment si `else` est supprimé ?

```js
function checkAge(age) {
  if (age > 18) {
    return true;
  }
*!*
  // ...
  return confirm('Did parents allow you?');
*/!*
}
```

Existe-t-il une différence dans le comportement de ces deux variantes ?


================================================
FILE: 1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/solution.md
================================================
En utilisant un opérateur point d’interrogation `'?'` :

```js
function checkAge(age) {
  return (age > 18) ? true : confirm('Did parents allow you?');
}
```

En utilisant OU `||` (la variante la plus courte) :

```js
function checkAge(age) {
  return (age > 18) || confirm('Did parents allow you?');
}
```

Notez que les parenthèses autour de `age > 18` ne sont pas obligatoires ici. Elles existent pour une meilleure lisibilité. 


================================================
FILE: 1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/task.md
================================================
importance: 4

---

# Réécrivez la fonction en utilisant '?' ou '||'

La fonction suivante renvoie `true` si le paramètre `age` est supérieur à `18`.

Sinon, il demande une confirmation et renvoie le résultat.

```js
function checkAge(age) {
  if (age > 18) {
    return true;
  } else {
    return confirm('Did parents allow you?');
  }
}
```

Réécrivez-le, pour effectuer la même chose, mais sans `if`, et en une seule ligne.

Faites deux variantes de `checkAge` :

1. En utilisant un opérateur point d'interrogation `?`
2. En utilisant OU `||`


================================================
FILE: 1-js/02-first-steps/15-function-basics/3-min/solution.md
================================================
Une solution utilisant `if` :

```js
function min(a, b) {
  if (a < b) {
    return a;
  } else {
    return b;
  }
}
```

Une solution utilisant l'opérateur point d'interrogation `'?'` :

```js
function min(a, b) {
  return a < b ? a : b;
}
```

P.S. Dans le cas d'une égalité `a == b`, peu importe ce qu'il faut retourner.


================================================
FILE: 1-js/02-first-steps/15-function-basics/3-min/task.md
================================================
importance: 1

---

# Fonction min(a, b)

Ecrivez une fonction `min(a, b)` qui renvoie le plus petit des deux nombres `a` et `b`.

Par exemple :

```js
min(2, 5) == 2
min(3, -1) == -1
min(1, 1) == 1
```



================================================
FILE: 1-js/02-first-steps/15-function-basics/4-pow/solution.md
================================================

```js run demo
function pow(x, n) {
  let result = x;

  for (let i = 1; i < n; i++) {
    result *= x;
  }

  return result;
}

let x = prompt("x?", '');
let n = prompt("n?", '');

if (n < 1) {
  alert(`Power ${n} is not supported, use a positive integer`);
} else {
  alert( pow(x, n) );
}
```


================================================
FILE: 1-js/02-first-steps/15-function-basics/4-pow/task.md
================================================
importance: 4

---

# Fonction pow(x,n)

Ecrivez une fonction `pow(x, n)` qui renvoie `x` à la puissance `n`. Ou, autrement dit, multiplie `x` par lui-même `n` fois et renvoie le résultat.

```js
pow(3, 2) = 3 * 3 = 9
pow(3, 3) = 3 * 3 * 3 = 27
pow(1, 100) = 1 * 1 * ...* 1 = 1
```

Créez une page Web qui demande (`prompt`)`x` et `n`, puis affiche le résultat de `pow(x, n)`.

[demo]

P.S. Dans cette tâche, la fonction ne doit prendre en charge que les valeurs naturelles de `n` : entiers supérieurs à `1`.


================================================
FILE: 1-js/02-first-steps/15-function-basics/article.md
================================================
# Fonctions

Très souvent, nous devons effectuer une action similaire à plusieurs endroits du script.

Par exemple, nous devons afficher un beau message lorsqu'un visiteur se connecte, se déconnecte et peut-être ailleurs.

Les fonctions sont les principales "composantes" du programme. Ils permettent au code d'être appelé plusieurs fois sans répétition.

Nous avons déjà vu des exemples de fonctions intégrées, telles que `alert(message)`, `prompt(message, default)` et `confirm(question)`. Mais nous pouvons aussi créer nos propres fonctions.

## Déclaration de fonction

Pour créer une fonction, nous pouvons utiliser une *déclaration de fonction*.

Cela ressemble à ceci :

```js
function showMessage() {
  alert( 'Hello everyone!' );
}
```

Le mot-clé `function` commence en premier, puis le *nom de la fonction*, puis une liste de *paramètres* entre les parenthèses (séparés par des virgules, vides dans l'exemple ci-dessus, nous verrons des exemples plus tard) et enfin le code de la fonction, également appelé "le corps de la fonction", entre des accolades.

```js
function name(parameter1, parameter2, ... parameterN) {
 // body
}
```

Notre nouvelle fonction peut être appelée par son nom : `showMessage()`.

Par exemple :

```js run
function showMessage() {
  alert( 'Hello everyone!' );
}

*!*
showMessage();
showMessage();
*/!*
```

L'appel `showMessage()` exécute le code de la fonction. Ici, nous verrons le message deux fois, parce qu'on l'appelle deux fois.

Cet exemple illustre clairement l’un des principaux objectifs des fonctions: éviter la duplication de code.

Si nous devons un jour modifier le message ou son affichage, il suffit de modifier le code à un endroit: la fonction qui le renvoie.

## Variables locales

Une variable déclarée à l'intérieur d'une fonction n'est visible qu'à l'intérieur de cette fonction.

Par exemple :

```js run
function showMessage() {
*!*
  let message = "Hello, I'm JavaScript!"; // variable locale
*/!*

  alert( message );
}

showMessage(); // Hello, I'm JavaScript!

alert( message ); // <-- Erreur! La variable est locale à la fonction
```

## Variables externes

Une fonction peut également accéder à une variable externe, par exemple :

```js run no-beautify
let *!*userName*/!* = 'John';

function showMessage() {
  let message = 'Hello, ' + *!*userName*/!*;
  alert(message);
}

showMessage(); // Hello, John
```

La fonction a un accès complet à la variable externe. Cela peut aussi la modifier.

Par exemple :

```js run
let *!*userName*/!* = 'John';

function showMessage() {
  *!*userName*/!* = "Bob"; // (1) changé la variable externe

  let message = 'Hello, ' + *!*userName*/!*;
  alert(message);
}

alert( userName ); // *!*John*/!* avant l'appel de fonction

showMessage();

alert( userName ); // *!*Bob*/!*, la valeur a été modifiée par la fonction
```

La variable externe n’est utilisée que s’il n’y a pas de variable locale.


Si une variable du même nom est déclarée à l'intérieur de la fonction, elle *eclipsera* la variable externe. Par exemple, dans le code ci-dessous, la fonction utilise le nom `userName` local. L'externe est ignoré :

```js run
let userName = 'John';

function showMessage() {
*!*
  let userName = "Bob"; // déclarer une variable locale
*/!*

  let message = 'Hello, ' + userName; // *!*Bob*/!*
  alert(message);
}

// la fonction créera et utilisera son propre userName
showMessage();

alert( userName ); // *!*John*/!*, inchangé, la fonction n'a pas accédé à la variable externe
```

```smart header="Variables globales"
Les variables déclarées en dehors de toute fonction, telle que `userName` externe dans le code ci-dessus, sont appelées *globales*.

Les variables globales sont visibles depuis n'importe quelle fonction (sauf si elles sont masquées par les variables locales).

C'est une bonne pratique de minimiser l'utilisation de variables globales. Le code moderne a peu ou pas de variable globales. La plupart des variables résident dans leurs fonctions. Parfois, cependant, ils peuvent être utiles pour stocker des données au niveau du projet.
```

## Arguments

Nous pouvons transmettre des données arbitraires à des fonctions à l'aide de paramètres.

Dans l'exemple ci-dessous, la fonction a deux paramètres: `from` et `text`.

```js run
function showMessage(*!*from, text*/!*) { // arguments : from, text
  alert(from + ': ' + text);
}

*!*showMessage('Ann', 'Hello!');*/!* // Ann: Hello! (*)
*!*showMessage('Ann', "What's up?");*/!* // Ann: What's up? (**)
```

Lorsque la fonction est appelée dans les lignes `(*)` et `(**)`, les valeurs données sont copiées dans les variables locales `from` et `text`. Ensuite, la fonction les utilise.

Voici un autre exemple: nous avons une variable `from` et la transmettons à la fonction. Remarque : la fonction change `from`, mais le changement n'est pas visible à l'extérieur, car une fonction obtient toujours une copie de la valeur :

```js run
function showMessage(from, text) {

*!*
  from = '*' + from + '*'; // améliore l'apparence de "from"
*/!*

  alert( from + ': ' + text );
}

let from = "Ann";

showMessage(from, "Hello"); // *Ann*: Hello

// la valeur de "from" est la même, la fonction a modifié une copie locale
alert( from ); // Ann
```

Lorsqu'une valeur est passée en tant que paramètre de fonction, elle est également appelée *argument*.

En d'autres termes, pour mettre ces termes au clair :

- Un paramètre est la variable répertoriée entre parenthèses dans la fonction déclaration (c'est un terme du temps de la déclaration).
- Un argument est la valeur qui est transmise à la fonction lorsqu'elle est appelée (c'est un terme du temps de l'appel).

Nous déclarons des fonctions en listant leurs paramètres, puis les appelons en passant des arguments.

Dans l'exemple ci-dessus, on pourrait dire : "la fonction `showMessage` est déclarée avec deux paramètres, puis appelée avec deux arguments : `from` et `"Hello"`.


## Les valeurs par défaut

Si une fonction est appelée, mais qu'aucun argument n'est fourni, alors la valeur correspondante devient `undefined`.

Par exemple, la fonction `showMessage(from, text)` mentionnée précédemment peut être appelée avec un seul argument :

```js
showMessage("Ann");
```

Ce n'est pas une erreur. Un tel appel produirait `"*Ann*: undefined"`. Comme la valeur de `text` n'est pas transmise, elle devient `undefined`.

Nous pouvons spécifier la valeur dite "par défaut" (à utiliser si omise) pour un paramètre dans la déclaration de fonction, en utilisant `=` :

```js run
function showMessage(from, *!*text = "no text given"*/!*) {
  alert( from + ": " + text );
}

showMessage("Ann"); // Ann: no text given
```

Maintenant, si le paramètre `text` n'est pas passé, il obtiendra la valeur `"no text given"`.

La valeur par défaut saute également si le paramètre existe, mais est strictement égal à `undefined`, comme ceci :

```js
showMessage("Ann", undefined); // Ann: no text given
```

Ici, `"no text given"` est une chaîne de caractères, mais il peut s'agir d'une expression plus complexe, qui n'est évaluée et affectée que si le paramètre est manquant. Donc, cela est également possible :

```js run
function showMessage(from, text = anotherFunction()) {
  // anotherFunction() est exécuté uniquement si aucun texte n'est fourni
  // son résultat devient la valeur de text
}
```

```smart header="Évaluation des paramètres par défaut"

En JavaScript, un paramètre par défaut est évalué chaque fois que la fonction est appelée sans le paramètre correspondant.

Dans l'exemple ci-dessus, `anotherFunction()` n'est pas du tout appelé, si le paramètre `text` est fourni.

D'un autre côté, il est appelé indépendamment à chaque fois que `text` est manquant.
```

````smart header="Paramètres par défaut dans l'ancien code JavaScript"
Il y a plusieurs années, JavaScript ne prenait pas en charge la syntaxe des paramètres par défaut. Les gens ont donc utilisé d'autres moyens pour les spécifier.

De nos jours, on peut les croiser dans d'anciens scripts.

Par exemple, une vérification explicite pour `undefined` :

```js
function showMessage(from, text) {
*!*
  if (text === undefined) {
    text = 'no text given';
  }
*/!*

  alert( from + ": " + text );
}
```

...Ou en utilisant l'opérateur `||` :

```js
function showMessage(from, text) {
  // Si la valeur du texte est fausse, attribuez la valeur par défaut
  // cela suppose que text == "" est identique à pas de texte du tout
  text = text || 'no text given';
  ...
}
```
````


### Paramètres par défaut alternatifs

Il est parfois judicieux de définir des valeurs par défaut pour les paramètres non pas dans la fonction déclaration, mais à un stade ultérieur, lors de son exécution.

Nous pouvons vérifier si le paramètre est passé lors de l'exécution de la fonction, en le comparant avec `undefined` :

```js run
function showMessage(text) {
  // ...

*!*
  if (text === undefined) { // si le paramètre est manquant
    text = 'empty message';
  }
*/!*

  alert(text);
}

showMessage(); // empty message
```

...Ou nous pourrions utiliser l'opérateur `||` :

```js
function showMessage(text) {
  // if text is undefined or otherwise falsy, set it to 'empty'
  text = text || 'empty';
  ...
}
```

Les moteurs JavaScript modernes prennent en charge [l'opérateur de coalescence des nuls](info:nullish-coalescing-operator) `??`, c'est mieux quand des valeurs fausses, telles que `0`, sont considérées comme "normales" :

```js run
function showCount(count) {
  // if count is undefined or null, show "unknown"
  alert(count ?? "unknown");
}

showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
```


## Renvoyer une valeur

Une fonction peut renvoyer une valeur dans le code appelant en tant que résultat.

L'exemple le plus simple serait une fonction qui additionne deux valeurs :

```js run no-beautify
function sum(a, b) {
  *!*return*/!* a + b;
}

let result = sum(1, 2);
alert( result ); // 3
```

La directive `return` peut être n'importe où dans la fonction. Lorsque l'exécution le permet, la fonction s'arrête et la valeur est renvoyée au code appelant (affecté à `result` ci-dessus).

Il peut y avoir plusieurs occurrences de `return` dans une seule fonction. Par exemple :

```js run
function checkAge(age) {
  if (age >= 18) {
*!*
    return true;
*/!*
  } else {
*!*
    return confirm('Do you have permission from your parents?');
*/!*
  }
}

let age = prompt('How old are you?', 18);

if ( checkAge(age) ) {
  alert( 'Access granted' );
} else {
  alert( 'Access denied' );
}
```

Il est possible d'utiliser `return` sans valeur. Cela entraîne la sortie immédiate de la fonction.

Par exemple :

```js
function showMovie(age) {
  if ( !checkAge(age) ) {
*!*
    return;
*/!*
  }

  alert( "Showing you the movie" ); // (*)
  // ...
}
```

Dans le code ci-dessus, si `checkAge(age)` renvoie `false`, alors `ShowMovie` n’effectuera pas l’`alert`.

````smart header="Une fonction avec un `return` vide ou rien dedans retourne `undefined`"

```js run
function doNothing() { /* vide */ }

alert( doNothing() === undefined ); // true
```

Un `return` vide est également identique à un `return undefined` :

```js run
function doNothing() {
  return;
}

alert( doNothing() === undefined ); // true
```
````

````warn header="N'ajoutez jamais de nouvelle ligne entre `return` et la valeur"
Pour une longue expression dans `return`, il pourrait être tentant de la mettre sur une ligne séparée, comme ceci :

```js
return
 (some + long + expression + or + whatever * f(a) + f(b))
```
Cela ne fonctionne pas, car JavaScript suppose un point-virgule après le `return`. Cela fonctionnera comme :

```js
return*!*;*/!*
 (some + long + expression + or + whatever * f(a) + f(b))
```

Donc, cela devient effectivement un retour vide.

Si nous voulons que l'expression renvoyée recouvre plusieurs lignes, nous devons la démarrer à la même ligne que `return`. Ou du moins mettre les parenthèses d'ouverture comme suit :

```js
return (
Download .txt
gitextract_jgp5_eg_/

├── .gitattributes
├── .gitignore
├── 1-js/
│   ├── 01-getting-started/
│   │   ├── 1-intro/
│   │   │   └── article.md
│   │   ├── 2-manuals-specifications/
│   │   │   └── article.md
│   │   ├── 3-code-editors/
│   │   │   └── article.md
│   │   ├── 4-devtools/
│   │   │   ├── article.md
│   │   │   └── bug.html
│   │   └── index.md
│   ├── 02-first-steps/
│   │   ├── 01-hello-world/
│   │   │   ├── 1-hello-alert/
│   │   │   │   ├── index.html
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-hello-alert-ext/
│   │   │   │   ├── alert.js
│   │   │   │   ├── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-structure/
│   │   │   └── article.md
│   │   ├── 03-strict-mode/
│   │   │   └── article.md
│   │   ├── 04-variables/
│   │   │   ├── 1-hello-variables/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-declare-variables/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-uppercast-constant/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-types/
│   │   │   ├── 1-string-quotes/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-alert-prompt-confirm/
│   │   │   ├── 1-simple-page/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-type-conversions/
│   │   │   └── article.md
│   │   ├── 08-operators/
│   │   │   ├── 1-increment-order/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-assignment-result/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-primitive-conversions-questions/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-fix-prompt/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-comparison/
│   │   │   ├── 1-comparison-questions/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 10-ifelse/
│   │   │   ├── 1-if-zero-string/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-check-standard/
│   │   │   │   ├── ifelse_task2/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-sign/
│   │   │   │   ├── if_sign/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-rewrite-if-question/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-rewrite-if-else-question/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 11-logical-operators/
│   │   │   ├── 1-alert-null-2-undefined/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-alert-or/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-alert-1-null-2/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-alert-and/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-alert-and-or/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-check-if-in-range/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-check-if-out-range/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-if-question/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-check-login/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 12-nullish-coalescing-operator/
│   │   │   └── article.md
│   │   ├── 13-while-for/
│   │   │   ├── 1-loop-last-value/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-which-value-while/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-which-value-for/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-for-even/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-replace-for-while/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-repeat-until-correct/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-list-primes/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 14-switch/
│   │   │   ├── 1-rewrite-switch-if-else/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-rewrite-if-switch/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 15-function-basics/
│   │   │   ├── 1-if-else-required/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-rewrite-function-question-or/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-min/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-pow/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 16-function-expressions/
│   │   │   └── article.md
│   │   ├── 17-arrow-functions-basics/
│   │   │   ├── 1-rewrite-arrow/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 18-javascript-specials/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 03-code-quality/
│   │   ├── 01-debugging-chrome/
│   │   │   ├── article.md
│   │   │   ├── debugging.view/
│   │   │   │   ├── hello.js
│   │   │   │   └── index.html
│   │   │   └── head.html
│   │   ├── 02-coding-style/
│   │   │   ├── 1-style-errors/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-comments/
│   │   │   └── article.md
│   │   ├── 04-ninja-code/
│   │   │   └── article.md
│   │   ├── 05-testing-mocha/
│   │   │   ├── 3-pow-test-wrong/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── beforeafter.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── index.html
│   │   │   ├── pow-1.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-2.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-3.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-4.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-full.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   ├── pow-min.view/
│   │   │   │   ├── index.html
│   │   │   │   └── test.js
│   │   │   └── pow-nan.view/
│   │   │       ├── index.html
│   │   │       └── test.js
│   │   ├── 06-polyfills/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 04-object-basics/
│   │   ├── 01-object/
│   │   │   ├── 2-hello-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-is-empty/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-const-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-sum-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-multiply-numeric/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-object-copy/
│   │   │   └── article.md
│   │   ├── 03-garbage-collection/
│   │   │   └── article.md
│   │   ├── 04-object-methods/
│   │   │   ├── 4-object-property-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-calculator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-chain-calls/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-constructor-new/
│   │   │   ├── 1-two-functions-one-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-calculator-constructor/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-accumulator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-optional-chaining/
│   │   │   └── article.md
│   │   ├── 08-symbol/
│   │   │   └── article.md
│   │   ├── 09-object-toprimitive/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 05-data-types/
│   │   ├── 01-primitives-methods/
│   │   │   ├── 1-string-new-property/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-number/
│   │   │   ├── 1-sum-interface/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-why-rounded-down/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-repeat-until-number/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-endless-loop-error/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-random-min-max/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-random-int-min-max/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-string/
│   │   │   ├── 1-ucfirst/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-check-spam/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-truncate/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-extract-currency/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-array/
│   │   │   ├── 1-item-value/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-maximal-subarray/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-create-array/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-call-array-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-array-input-sum/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-array-methods/
│   │   │   ├── 1-camelcase/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-average-age/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 11-array-unique/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 12-reduce-object/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-filter-range/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-filter-range-in-place/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-sort-back/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-copy-sort-array/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-array-get-names/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-calculator-extendable/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-map-objects/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-sort-objects/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-shuffle/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-iterable/
│   │   │   └── article.md
│   │   ├── 07-map-set/
│   │   │   ├── 01-array-unique-map/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-filter-anagrams/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-iterable-keys/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 08-weakmap-weakset/
│   │   │   ├── 01-recipients-read/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-recipients-when-read/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-keys-values-entries/
│   │   │   ├── 01-sum-salaries/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-count-properties/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 10-destructuring-assignment/
│   │   │   ├── 1-destruct-user/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-max-salary/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 11-date/
│   │   │   ├── 1-new-date/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-get-week-day/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-weekday/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-get-date-ago/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-last-day-of-month/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-get-seconds-today/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-get-seconds-to-tomorrow/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-format-date-relative/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 12-json/
│   │   │   ├── 1-serialize-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-serialize-event-circular/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 06-advanced-functions/
│   │   ├── 01-recursion/
│   │   │   ├── 01-sum-to/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-factorial/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-fibonacci-numbers/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 04-output-single-linked-list/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 05-output-single-linked-list-reverse/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 02-rest-parameters-spread/
│   │   │   └── article.md
│   │   ├── 03-closure/
│   │   │   ├── 1-closure-latest-changes/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-make-army/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-closure-variable-access/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-counter-independent/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-counter-object-independent/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-function-in-if/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-closure-sum/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 7-let-scope/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 8-filter-through-function/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 9-sort-by-field/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-var/
│   │   │   └── article.md
│   │   ├── 05-global-object/
│   │   │   └── article.md
│   │   ├── 06-function-object/
│   │   │   ├── 2-counter-inc-dec/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-sum-many-brackets/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-new-function/
│   │   │   └── article.md
│   │   ├── 08-settimeout-setinterval/
│   │   │   ├── 1-output-numbers-100ms/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-rewrite-settimeout/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-settimeout-result/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-call-apply-decorators/
│   │   │   ├── 01-spy-decorator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   ├── source.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-delay/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-debounce/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── debounce.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 04-throttle/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 10-bind/
│   │   │   ├── 2-write-to-object-after-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-second-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-function-property-after-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-question-use-bind/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-ask-partial/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 12-arrow-functions/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 07-object-properties/
│   │   ├── 01-property-descriptors/
│   │   │   └── article.md
│   │   ├── 02-property-accessors/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 08-prototypes/
│   │   ├── 01-prototype-inheritance/
│   │   │   ├── 1-property-after-delete/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-search-algorithm/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-proto-and-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-hamster-proto/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-function-prototype/
│   │   │   ├── 1-changing-prototype/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-new-object-same-constructor/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-native-prototypes/
│   │   │   ├── 1-defer-to-prototype/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-defer-to-prototype-extended/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-prototype-methods/
│   │   │   ├── 2-dictionary-tostring/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-compare-calls/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 09-classes/
│   │   ├── 01-class/
│   │   │   ├── 1-rewrite-to-class/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── source.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-class-inheritance/
│   │   │   ├── 1-class-constructor-error/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-clock-class-extended/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── clock.js
│   │   │   │   │   ├── extended-clock.js
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── clock.js
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-static-properties-methods/
│   │   │   ├── 3-class-extend-object/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 04-private-protected-properties-methods/
│   │   │   └── article.md
│   │   ├── 05-extend-natives/
│   │   │   └── article.md
│   │   ├── 06-instanceof/
│   │   │   ├── 1-strange-instanceof/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-mixins/
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 10-error-handling/
│   │   ├── 1-try-catch/
│   │   │   ├── 1-finally-or-code-after/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 2-custom-errors/
│   │   │   ├── 1-format-error/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 11-async/
│   │   ├── 01-callbacks/
│   │   │   ├── article.md
│   │   │   └── one.js
│   │   ├── 02-promise-basics/
│   │   │   ├── 01-re-resolve/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-delay-promise/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-animate-circle-promise/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 03-promise-chaining/
│   │   │   ├── 01-then-vs-catch/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── getMessage.js
│   │   │   ├── head.html
│   │   │   ├── one.js
│   │   │   ├── three.js
│   │   │   ├── two.js
│   │   │   └── user.json
│   │   ├── 04-promise-error-handling/
│   │   │   ├── 01-error-async/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── getMessage.js
│   │   │   ├── head.html
│   │   │   ├── one.js
│   │   │   ├── three.js
│   │   │   ├── two.js
│   │   │   └── user.json
│   │   ├── 05-promise-api/
│   │   │   ├── article.md
│   │   │   ├── head.html
│   │   │   ├── iliakan.json
│   │   │   ├── one.js
│   │   │   └── two.js
│   │   ├── 06-promisify/
│   │   │   └── article.md
│   │   ├── 07-microtask-queue/
│   │   │   └── article.md
│   │   ├── 08-async-await/
│   │   │   ├── 01-rewrite-async/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-rewrite-async-2/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-async-from-regular/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 12-generators-iterators/
│   │   ├── 1-generators/
│   │   │   ├── 01-pseudo-random-generator/
│   │   │   │   ├── _js.view/
│   │   │   │   │   ├── solution.js
│   │   │   │   │   └── test.js
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 2-async-iterators-generators/
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 13-modules/
│   │   ├── 01-modules-intro/
│   │   │   ├── article.md
│   │   │   ├── say.view/
│   │   │   │   ├── index.html
│   │   │   │   └── say.js
│   │   │   ├── scopes-working.view/
│   │   │   │   ├── hello.js
│   │   │   │   ├── index.html
│   │   │   │   └── user.js
│   │   │   └── scopes.view/
│   │   │       ├── hello.js
│   │   │       ├── index.html
│   │   │       └── user.js
│   │   ├── 02-import-export/
│   │   │   └── article.md
│   │   ├── 03-modules-dynamic-imports/
│   │   │   ├── article.md
│   │   │   └── say.view/
│   │   │       ├── index.html
│   │   │       └── say.js
│   │   └── index.md
│   ├── 99-js-misc/
│   │   ├── 01-proxy/
│   │   │   ├── 01-error-nonexisting/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 02-array-negative/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-observable/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 02-eval/
│   │   │   ├── 1-eval-calculator/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 03-currying-partials/
│   │   │   └── article.md
│   │   ├── 04-reference-type/
│   │   │   ├── 2-check-syntax/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-why-this/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-bigint/
│   │   │   └── article.md
│   │   ├── 06-unicode/
│   │   │   └── article.md
│   │   └── index.md
│   └── index.md
├── 2-ui/
│   ├── 1-document/
│   │   ├── 01-browser-environment/
│   │   │   └── article.md
│   │   ├── 02-dom-nodes/
│   │   │   ├── article.md
│   │   │   ├── elk.html
│   │   │   └── head.html
│   │   ├── 03-dom-navigation/
│   │   │   ├── 1-dom-children/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 3-navigation-links-which-null/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-select-diagonal-cells/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 04-searching-elements-dom/
│   │   │   ├── 1-find-elements/
│   │   │   │   ├── solution.md
│   │   │   │   ├── table.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 05-basic-dom-node-properties/
│   │   │   ├── 2-lastchild-nodetype-inline/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-tree-info/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-tag-in-comment/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-where-document-in-hierarchy/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 06-dom-attributes-and-properties/
│   │   │   ├── 1-get-user-attribute/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-yellow-links/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 07-modifying-document/
│   │   │   ├── 1-createtextnode-vs-innerhtml/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 10-clock-setinterval/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 11-append-to-list/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 12-sort-table/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 4-clear-elem/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 5-why-aaa/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 6-create-list/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 7-create-object-tree/
│   │   │   │   ├── build-tree-dom.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── innerhtml.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 8-tree-count/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 9-calendar-table/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 08-styles-and-classes/
│   │   │   ├── 2-create-notification/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 09-size-and-scroll/
│   │   │   ├── 1-get-scroll-height-bottom/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-scrollbar-width/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 4-put-ball-in-center/
│   │   │   │   ├── ball-half/
│   │   │   │   │   └── index.html
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 6-width-vs-clientwidth/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── cssWidthScroll.view/
│   │   │   │   └── index.html
│   │   │   └── metric.view/
│   │   │       └── index.html
│   │   ├── 10-size-and-scroll-window/
│   │   │   └── article.md
│   │   ├── 11-coordinates/
│   │   │   ├── 1-find-point-coordinates/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-position-at/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-position-at-absolute/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 4-position-inside-absolute/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   └── index.md
│   ├── 2-events/
│   │   ├── 01-introduction-browser-events/
│   │   │   ├── 01-hide-other/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 02-hide-self-onclick/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 03-which-handlers-run/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 04-move-ball-field/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 05-sliding-menu/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 06-hide-message/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   └── task.md
│   │   │   ├── 07-carousel/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 02-bubbling-and-capturing/
│   │   │   ├── article.md
│   │   │   ├── both.view/
│   │   │   │   ├── example.css
│   │   │   │   ├── index.html
│   │   │   │   └── script.js
│   │   │   ├── bubble-target.view/
│   │   │   │   ├── example.css
│   │   │   │   ├── index.html
│   │   │   │   └── script.js
│   │   │   └── capture.view/
│   │   │       ├── example.css
│   │   │       ├── index.html
│   │   │       └── script.js
│   │   ├── 03-event-delegation/
│   │   │   ├── 1-hide-message-delegate/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── messages.css
│   │   │   │   └── task.md
│   │   │   ├── 2-sliding-tree/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-sortable-table/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 4-behavior-tooltip/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── bagua.view/
│   │   │       ├── bagua.css
│   │   │       └── index.html
│   │   ├── 04-default-browser-action/
│   │   │   ├── 1-why-return-false-fails/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   ├── 2-catch-link-navigation/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-image-gallery/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── gallery.css
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── gallery.css
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── menu.view/
│   │   │       ├── index.html
│   │   │       ├── menu.css
│   │   │       └── menu.js
│   │   ├── 05-dispatch-events/
│   │   │   └── article.md
│   │   └── index.md
│   ├── 3-event-details/
│   │   ├── 1-mouse-events-basics/
│   │   │   ├── 01-selectable-list/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── head.html
│   │   ├── 3-mousemove-mouseover-mouseout-mouseenter-mouseleave/
│   │   │   ├── 1-behavior-nested-tooltip/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-hoverintent/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── hoverIntent.js
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── style.css
│   │   │   │   │   └── test.js
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── hoverIntent.js
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── style.css
│   │   │   │   │   └── test.js
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── mouseenter-mouseleave-delegation-2.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseenter-mouseleave-delegation.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseleave-table.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseleave.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseoverout-child.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   ├── mouseoverout-fast.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── script.js
│   │   │   │   └── style.css
│   │   │   └── mouseoverout.view/
│   │   │       ├── index.html
│   │   │       ├── script.js
│   │   │       └── style.css
│   │   ├── 4-mouse-drag-and-drop/
│   │   │   ├── 1-slider/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   └── task.md
│   │   │   ├── 2-drag-heroes/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── soccer.css
│   │   │   │   │   └── soccer.js
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── soccer.css
│   │   │   │   │   └── soccer.js
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   ├── ball.view/
│   │   │   │   └── index.html
│   │   │   ├── ball2.view/
│   │   │   │   └── index.html
│   │   │   ├── ball3.view/
│   │   │   │   └── index.html
│   │   │   └── ball4.view/
│   │   │       ├── index.html
│   │   │       └── style.css
│   │   ├── 6-pointer-events/
│   │   │   ├── article.md
│   │   │   ├── ball-2.view/
│   │   │   │   └── index.html
│   │   │   ├── ball.view/
│   │   │   │   └── index.html
│   │   │   ├── multitouch.view/
│   │   │   │   └── index.html
│   │   │   ├── slider-html.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   └── slider.view/
│   │   │       ├── index.html
│   │   │       └── style.css
│   │   ├── 7-keyboard-events/
│   │   │   ├── 2-check-sync-keydown/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── keyboard-dump.view/
│   │   │       ├── index.html
│   │   │       ├── script.js
│   │   │       └── style.css
│   │   ├── 8-onscroll/
│   │   │   ├── 1-endless-page/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 2-updown-button/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── 3-load-visible-img/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 4-forms-controls/
│   │   ├── 1-form-elements/
│   │   │   ├── 1-add-select-option/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 2-focus-blur/
│   │   │   ├── 3-editable-div/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── my.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── my.css
│   │   │   │   └── task.md
│   │   │   ├── 4-edit-td-click/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── bagua.css
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── my.css
│   │   │   │   │   └── script.js
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── bagua.css
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── my.css
│   │   │   │   │   └── script.js
│   │   │   │   └── task.md
│   │   │   ├── 5-keyboard-mouse/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 3-events-change-input/
│   │   │   ├── 1-deposit-calculator/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   ├── 4-forms-submit/
│   │   │   ├── 1-modal-dialog/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   ├── source.view/
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── style.css
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   ├── 5-loading/
│   │   ├── 01-onload-ondomcontentloaded/
│   │   │   ├── article.md
│   │   │   ├── readystate.view/
│   │   │   │   ├── iframe.html
│   │   │   │   └── index.html
│   │   │   └── window-onbeforeunload.view/
│   │   │       └── index.html
│   │   ├── 02-script-async-defer/
│   │   │   ├── article.md
│   │   │   ├── long.js
│   │   │   └── small.js
│   │   ├── 03-onload-onerror/
│   │   │   ├── 1-load-img-callback/
│   │   │   │   ├── solution.md
│   │   │   │   ├── solution.view/
│   │   │   │   │   └── index.html
│   │   │   │   ├── source.view/
│   │   │   │   │   └── index.html
│   │   │   │   └── task.md
│   │   │   ├── article.md
│   │   │   └── crossorigin.view/
│   │   │       └── error.js
│   │   └── index.md
│   ├── 99-ui-misc/
│   │   ├── 01-mutation-observer/
│   │   │   └── article.md
│   │   ├── 02-selection-range/
│   │   │   └── article.md
│   │   ├── 03-event-loop/
│   │   │   ├── 2-micro-macro-queue/
│   │   │   │   ├── solution.md
│   │   │   │   └── task.md
│   │   │   └── article.md
│   │   └── index.md
│   └── index.md
├── 3-frames-and-windows/
│   ├── 01-popup-windows/
│   │   └── article.md
│   ├── 03-cross-window-communication/
│   │   ├── article.md
│   │   ├── postmessage.view/
│   │   │   ├── iframe.html
│   │   │   └── index.html
│   │   └── sandbox.view/
│   │       ├── index.html
│   │       └── sandboxed.html
│   ├── 06-clickjacking/
│   │   ├── article.md
│   │   ├── clickjacking-visible.view/
│   │   │   ├── facebook.html
│   │   │   └── index.html
│   │   ├── clickjacking.view/
│   │   │   ├── facebook.html
│   │   │   └── index.html
│   │   ├── protector.view/
│   │   │   ├── iframe.html
│   │   │   └── index.html
│   │   └── top-location.view/
│   │       ├── iframe.html
│   │       └── index.html
│   └── index.md
├── 4-binary/
│   ├── 01-arraybuffer-binary-arrays/
│   │   ├── 01-concat/
│   │   │   ├── _js.view/
│   │   │   │   ├── solution.js
│   │   │   │   ├── source.js
│   │   │   │   └── test.js
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 02-text-decoder/
│   │   └── article.md
│   ├── 03-blob/
│   │   └── article.md
│   ├── 04-file/
│   │   └── article.md
│   └── index.md
├── 5-network/
│   ├── 01-fetch/
│   │   ├── 01-fetch-users/
│   │   │   ├── _js.view/
│   │   │   │   ├── solution.js
│   │   │   │   ├── source.js
│   │   │   │   └── test.js
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── article.md
│   │   └── post.view/
│   │       └── server.js
│   ├── 02-formdata/
│   │   ├── article.md
│   │   └── post.view/
│   │       └── server.js
│   ├── 03-fetch-progress/
│   │   ├── article.md
│   │   └── progress.view/
│   │       ├── index.html
│   │       └── long.txt
│   ├── 04-fetch-abort/
│   │   ├── article.md
│   │   └── demo.view/
│   │       └── server.js
│   ├── 05-fetch-crossorigin/
│   │   ├── 1-do-we-need-origin/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 06-fetch-api/
│   │   ├── article.md
│   │   └── post.view/
│   │       ├── index.html
│   │       └── server.js
│   ├── 07-url/
│   │   └── article.md
│   ├── 08-xmlhttprequest/
│   │   ├── article.md
│   │   ├── example.view/
│   │   │   ├── index.html
│   │   │   └── server.js
│   │   ├── hello.txt
│   │   ├── phones-async.view/
│   │   │   ├── index.html
│   │   │   ├── phones.json
│   │   │   └── server.js
│   │   ├── phones.json
│   │   ├── phones.view/
│   │   │   ├── index.html
│   │   │   ├── phones.json
│   │   │   └── server.js
│   │   └── post.view/
│   │       ├── index.html
│   │       └── server.js
│   ├── 09-resume-upload/
│   │   ├── article.md
│   │   └── upload-resume.view/
│   │       ├── index.html
│   │       ├── server.js
│   │       └── uploader.js
│   ├── 10-long-polling/
│   │   ├── article.md
│   │   └── longpoll.view/
│   │       ├── browser.js
│   │       ├── index.html
│   │       └── server.js
│   ├── 11-websocket/
│   │   ├── article.md
│   │   ├── chat.view/
│   │   │   ├── index.html
│   │   │   └── server.js
│   │   └── demo.view/
│   │       └── server.js
│   ├── 12-server-sent-events/
│   │   ├── article.md
│   │   └── eventsource.view/
│   │       ├── index.html
│   │       └── server.js
│   └── index.md
├── 6-data-storage/
│   ├── 01-cookie/
│   │   ├── article.md
│   │   └── cookie.js
│   ├── 02-localstorage/
│   │   ├── 1-form-autosave/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   ├── source.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── article.md
│   │   └── sessionstorage.view/
│   │       ├── iframe.html
│   │       └── index.html
│   ├── 03-indexeddb/
│   │   ├── article.md
│   │   └── books.view/
│   │       └── index.html
│   └── index.md
├── 7-animation/
│   ├── 1-bezier-curve/
│   │   └── article.md
│   ├── 2-css-animations/
│   │   ├── 1-animate-logo-css/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   ├── source.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── 2-animate-logo-bezier-css/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── 3-animate-circle/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   ├── source.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── 4-animate-circle-callback/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   └── index.html
│   │   │   └── task.md
│   │   ├── article.md
│   │   ├── boat.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── digits-negative-delay.view/
│   │   │   ├── index.html
│   │   │   ├── script.js
│   │   │   └── style.css
│   │   ├── digits.view/
│   │   │   ├── index.html
│   │   │   ├── script.js
│   │   │   └── style.css
│   │   ├── step-end.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── step-list.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── step.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── train-linear.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── train-over.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   └── train.view/
│   │       ├── index.html
│   │       └── style.css
│   ├── 3-js-animation/
│   │   ├── 1-animate-ball/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   ├── source.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   └── task.md
│   │   ├── 2-animate-ball-hops/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   ├── index.html
│   │   │   │   └── style.css
│   │   │   └── task.md
│   │   ├── article.md
│   │   ├── back.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── bounce-easeinout.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── bounce-easeout.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── bounce.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── circ.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── elastic.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── move-raf.view/
│   │   │   └── index.html
│   │   ├── move.view/
│   │   │   └── index.html
│   │   ├── quad.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── quint.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   ├── text.view/
│   │   │   ├── index.html
│   │   │   └── style.css
│   │   └── width.view/
│   │       ├── animate.js
│   │       └── index.html
│   └── index.md
├── 8-web-components/
│   ├── 1-webcomponents-intro/
│   │   ├── .vs/
│   │   │   ├── 1-webcomponents-intro/
│   │   │   │   └── v15/
│   │   │   │       └── .suo
│   │   │   └── VSWorkspaceState.json
│   │   └── article.md
│   ├── 2-custom-elements/
│   │   ├── 1-live-timer/
│   │   │   ├── solution.md
│   │   │   ├── solution.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── live-timer.js
│   │   │   │   └── time-formatted.js
│   │   │   ├── source.view/
│   │   │   │   ├── index.html
│   │   │   │   ├── live-timer.js
│   │   │   │   └── time-formatted.js
│   │   │   └── task.md
│   │   ├── article.md
│   │   └── head.html
│   ├── 3-shadow-dom/
│   │   └── article.md
│   ├── 4-template-element/
│   │   └── article.md
│   ├── 5-slots-composition/
│   │   ├── article.md
│   │   └── menu.view/
│   │       └── index.html
│   ├── 6-shadow-dom-style/
│   │   └── article.md
│   ├── 7-shadow-dom-events/
│   │   └── article.md
│   └── index.md
├── 9-regular-expressions/
│   ├── 01-regexp-introduction/
│   │   └── article.md
│   ├── 02-regexp-character-classes/
│   │   └── article.md
│   ├── 03-regexp-unicode/
│   │   └── article.md
│   ├── 04-regexp-anchors/
│   │   ├── 1-start-end/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 05-regexp-multiline-mode/
│   │   └── article.md
│   ├── 06-regexp-boundary/
│   │   ├── 1-find-time-hh-mm/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 07-regexp-escaping/
│   │   └── article.md
│   ├── 08-regexp-character-sets-and-ranges/
│   │   ├── 1-find-range-1/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 2-find-time-2-formats/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 09-regexp-quantifiers/
│   │   ├── 1-find-text-manydots/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 2-find-html-colors-6hex/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 10-regexp-greedy-and-lazy/
│   │   ├── 1-lazy-greedy/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 3-find-html-comments/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 4-find-html-tags-greedy-lazy/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 11-regexp-groups/
│   │   ├── 01-test-mac/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 02-find-webcolor-3-or-6/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 03-find-decimal-numbers/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 04-parse-expression/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 12-regexp-backreferences/
│   │   └── article.md
│   ├── 13-regexp-alternation/
│   │   ├── 01-find-programming-language/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 02-find-matching-bbtags/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 03-match-quoted-string/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 04-match-exact-tag/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 14-regexp-lookahead-lookbehind/
│   │   ├── 1-find-non-negative-integers/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   ├── 2-insert-after-head/
│   │   │   ├── solution.md
│   │   │   └── task.md
│   │   └── article.md
│   ├── 15-regexp-catastrophic-backtracking/
│   │   └── article.md
│   ├── 16-regexp-sticky/
│   │   └── article.md
│   ├── 17-regexp-methods/
│   │   └── article.md
│   └── index.md
├── AUTHORING.md
├── LICENSE.md
├── README.md
├── changes.sketch
├── css.md
├── figures.sketch
├── property-accessors.md
├── script/
│   └── clean-unused-png.php
└── todo.md
Download .txt
SYMBOL INDEX (176 symbols across 109 files)

FILE: 1-js/03-code-quality/01-debugging-chrome/debugging.view/hello.js
  function hello (line 1) | function hello(name) {
  function say (line 7) | function say(phrase) {

FILE: 1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js
  function makeTest (line 3) | function makeTest(x) {

FILE: 1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js
  function makeTest (line 5) | function makeTest(x) {

FILE: 1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js
  function makeTest (line 5) | function makeTest(x) {

FILE: 1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js
  function makeTest (line 5) | function makeTest(x) {

FILE: 1-js/04-object-basics/01-object/3-is-empty/_js.view/solution.js
  function isEmpty (line 1) | function isEmpty(obj) {

FILE: 1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/solution.js
  function multiplyNumeric (line 1) | function multiplyNumeric(obj) {

FILE: 1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/source.js
  function multiplyNumeric (line 8) | function multiplyNumeric(obj) {

FILE: 1-js/04-object-basics/04-object-methods/7-calculator/_js.view/solution.js
  method sum (line 2) | sum() {
  method mul (line 6) | mul() {
  method read (line 10) | read() {

FILE: 1-js/04-object-basics/06-constructor-new/2-calculator-constructor/_js.view/solution.js
  function Calculator (line 1) | function Calculator() {

FILE: 1-js/04-object-basics/06-constructor-new/3-accumulator/_js.view/solution.js
  function Accumulator (line 1) | function Accumulator(startingValue) {

FILE: 1-js/05-data-types/02-number/3-repeat-until-number/_js.view/solution.js
  function readNumber (line 2) | function readNumber() {

FILE: 1-js/05-data-types/03-string/1-ucfirst/_js.view/solution.js
  function ucFirst (line 1) | function ucFirst(str) {

FILE: 1-js/05-data-types/03-string/2-check-spam/_js.view/solution.js
  function checkSpam (line 1) | function checkSpam(str) {

FILE: 1-js/05-data-types/03-string/3-truncate/_js.view/solution.js
  function truncate (line 1) | function truncate(str, maxlength) {

FILE: 1-js/05-data-types/03-string/4-extract-currency/_js.view/solution.js
  function extractCurrencyValue (line 1) | function extractCurrencyValue(str) {

FILE: 1-js/05-data-types/04-array/10-maximal-subarray/_js.view/solution.js
  function getMaxSubSum (line 1) | function getMaxSubSum(arr) {

FILE: 1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js
  function camelize (line 1) | function camelize(str) {

FILE: 1-js/05-data-types/05-array-methods/11-array-unique/_js.view/solution.js
  function unique (line 1) | function unique(arr) {

FILE: 1-js/05-data-types/05-array-methods/12-reduce-object/_js.view/solution.js
  function groupById (line 1) | function groupById(array) {

FILE: 1-js/05-data-types/05-array-methods/2-filter-range/_js.view/solution.js
  function filterRange (line 2) | function filterRange(arr, a, b) {

FILE: 1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js
  function filterRangeInPlace (line 2) | function filterRangeInPlace(arr, a, b) {

FILE: 1-js/05-data-types/05-array-methods/6-calculator-extendable/_js.view/solution.js
  function Calculator (line 1) | function Calculator() {

FILE: 1-js/05-data-types/07-map-set/01-array-unique-map/_js.view/solution.js
  function unique (line 1) | function unique(arr) {

FILE: 1-js/05-data-types/07-map-set/02-filter-anagrams/_js.view/solution.js
  function aclean (line 2) | function aclean(arr) {

FILE: 1-js/05-data-types/07-map-set/02-filter-anagrams/_js.view/test.js
  function intersection (line 1) | function intersection(arr1, arr2) {

FILE: 1-js/05-data-types/09-keys-values-entries/01-sum-salaries/_js.view/solution.js
  function sumSalaries (line 1) | function sumSalaries(salaries) {

FILE: 1-js/05-data-types/09-keys-values-entries/02-count-properties/_js.view/solution.js
  function count (line 1) | function count(obj) {

FILE: 1-js/05-data-types/10-destructuring-assignment/6-max-salary/_js.view/solution.js
  function topSalary (line 1) | function topSalary(salaries) {

FILE: 1-js/05-data-types/11-date/2-get-week-day/_js.view/solution.js
  function getWeekDay (line 1) | function getWeekDay(date) {

FILE: 1-js/05-data-types/11-date/3-weekday/_js.view/solution.js
  function getLocalDay (line 1) | function getLocalDay(date) {

FILE: 1-js/05-data-types/11-date/4-get-date-ago/_js.view/solution.js
  function getDateAgo (line 1) | function getDateAgo(date, days) {

FILE: 1-js/05-data-types/11-date/5-last-day-of-month/_js.view/solution.js
  function getLastDayOfMonth (line 1) | function getLastDayOfMonth(year, month) {

FILE: 1-js/05-data-types/11-date/8-format-date-relative/_js.view/solution.js
  function formatDate (line 2) | function formatDate(date) {

FILE: 1-js/06-advanced-functions/03-closure/10-make-army/_js.view/solution.js
  function makeArmy (line 1) | function makeArmy() {

FILE: 1-js/06-advanced-functions/03-closure/10-make-army/_js.view/source.js
  function makeArmy (line 1) | function makeArmy() {

FILE: 1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/solution.js
  function inArray (line 2) | function inArray(arr) {
  function inBetween (line 6) | function inBetween(a, b) {

FILE: 1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/source.js
  function inBetween (line 4) | function inBetween(a, b) {
  function inArray (line 8) | function inArray(arr) {

FILE: 1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/solution.js
  function byField (line 1) | function byField(fieldName){

FILE: 1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/source.js
  function byField (line 1) | function byField(fieldName){

FILE: 1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/_js.view/solution.js
  function makeCounter (line 1) | function makeCounter() {

FILE: 1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/_js.view/source.js
  function makeCounter (line 1) | function makeCounter() {

FILE: 1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js
  function sum (line 1) | function sum(a) {

FILE: 1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js
  function sum (line 1) | function sum(a){

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
  function spy (line 1) | function spy(func) {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/source.js
  function spy (line 1) | function spy(func) {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
  function work (line 3) | function work() {}

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/02-delay/_js.view/solution.js
  function delay (line 1) | function delay(f, ms) {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/02-delay/_js.view/test.js
  function f (line 13) | function f(x) {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/solution.js
  function debounce (line 1) | function debounce(func, ms) {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
  method f (line 38) | f() {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
  function throttle (line 1) | function throttle(func, ms) {

FILE: 1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
  function f (line 5) | function f(a) {

FILE: 1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js
  class Clock (line 1) | class Clock {
    method constructor (line 2) | constructor({ template }) {
    method render (line 6) | render() {
    method stop (line 26) | stop() {
    method start (line 30) | start() {

FILE: 1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js
  function Clock (line 1) | function Clock({ template }) {

FILE: 1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/clock.js
  class Clock (line 1) | class Clock {
    method constructor (line 2) | constructor({ template }) {
    method render (line 6) | render() {
    method stop (line 26) | stop() {
    method start (line 30) | start() {

FILE: 1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js
  class ExtendedClock (line 1) | class ExtendedClock extends Clock {
    method constructor (line 2) | constructor(options) {
    method start (line 8) | start() {

FILE: 1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/clock.js
  class Clock (line 1) | class Clock {
    method constructor (line 2) | constructor({ template }) {
    method render (line 6) | render() {
    method stop (line 26) | stop() {
    method start (line 30) | start() {

FILE: 1-js/11-async/01-callbacks/one.js
  function one (line 1) | function one() {

FILE: 1-js/11-async/03-promise-chaining/getMessage.js
  function getMessage (line 1) | function getMessage() {

FILE: 1-js/11-async/03-promise-chaining/one.js
  function one (line 1) | function one() {

FILE: 1-js/11-async/03-promise-chaining/three.js
  function three (line 1) | function three() {

FILE: 1-js/11-async/03-promise-chaining/two.js
  function two (line 1) | function two() {

FILE: 1-js/11-async/04-promise-error-handling/getMessage.js
  function getMessage (line 1) | function getMessage() {

FILE: 1-js/11-async/04-promise-error-handling/one.js
  function one (line 1) | function one() {

FILE: 1-js/11-async/04-promise-error-handling/three.js
  function three (line 1) | function three() {

FILE: 1-js/11-async/04-promise-error-handling/two.js
  function two (line 1) | function two() {

FILE: 1-js/11-async/05-promise-api/one.js
  function one (line 1) | function one() {

FILE: 1-js/11-async/05-promise-api/two.js
  function two (line 1) | function two() {

FILE: 1-js/13-modules/01-modules-intro/say.view/say.js
  function sayHi (line 1) | function sayHi(user) {

FILE: 1-js/13-modules/03-modules-dynamic-imports/say.view/say.js
  function hi (line 1) | function hi() {
  function bye (line 5) | function bye() {

FILE: 2-ui/2-events/02-bubbling-and-capturing/both.view/script.js
  function highlightThis (line 8) | function highlightThis() {

FILE: 2-ui/2-events/02-bubbling-and-capturing/capture.view/script.js
  function highlightThis (line 7) | function highlightThis() {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/solution.view/hoverIntent.js
  class HoverIntent (line 3) | class HoverIntent {
    method constructor (line 5) | constructor({
    method onMouseOver (line 32) | onMouseOver(event) {
    method onMouseOut (line 53) | onMouseOut(event) {
    method onMouseMove (line 67) | onMouseMove(event) {
    method trackSpeed (line 73) | trackSpeed() {
    method destroy (line 99) | destroy() {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/solution.view/test.js
  function mouse (line 5) | function mouse(eventType, x, y, options) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/source.view/hoverIntent.js
  class HoverIntent (line 5) | class HoverIntent {
    method constructor (line 6) | constructor({
    method onMouseOver (line 31) | onMouseOver(event) {
    method onMouseOut (line 35) | onMouseOut(event) {
    method onMouseMove (line 39) | onMouseMove(event) {
    method destroy (line 43) | destroy() {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/2-hoverintent/source.view/test.js
  function mouse (line 5) | function mouse(eventType, x, y, options) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseenter-mouseleave-delegation-2.view/script.js
  function onEnter (line 47) | function onEnter(elem) {
  function onLeave (line 55) | function onLeave(elem) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseleave-table.view/script.js
  function log (line 3) | function log(event) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseleave.view/script.js
  function mouselog (line 1) | function mouselog(event) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-child.view/script.js
  function mouselog (line 1) | function mouselog(event) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js
  function handler (line 4) | function handler(event) {
  function clearText (line 13) | function clearText() {
  function log (line 22) | function log(message) {

FILE: 2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout.view/script.js
  function handler (line 3) | function handler(event) {

FILE: 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/soccer.js
  function onMouseUp (line 19) | function onMouseUp(event) {
  function onMouseMove (line 23) | function onMouseMove(event) {
  function startDrag (line 30) | function startDrag(element, clientX, clientY) {
  function finishDrag (line 49) | function finishDrag() {
  function moveAt (line 63) | function moveAt(clientX, clientY) {

FILE: 2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js
  function handle (line 5) | function handle(e) {

FILE: 2-ui/4-forms-controls/2-focus-blur/4-edit-td-click/solution.view/script.js
  function makeTdEditable (line 24) | function makeTdEditable(td) {
  function finishTdEdit (line 47) | function finishTdEdit(td, isOk) {

FILE: 4-binary/01-arraybuffer-binary-arrays/01-concat/_js.view/solution.js
  function concat (line 1) | function concat(arrays) {

FILE: 4-binary/01-arraybuffer-binary-arrays/01-concat/_js.view/source.js
  function concat (line 1) | function concat(arrays) {

FILE: 5-network/01-fetch/01-fetch-users/_js.view/solution.js
  function getUsers (line 2) | async function getUsers(names) {

FILE: 5-network/01-fetch/01-fetch-users/_js.view/source.js
  function getUsers (line 2) | async function getUsers(names) {

FILE: 5-network/02-formdata/post.view/server.js
  method onFile (line 20) | onFile(fieldname, file, filename, encoding, mimetype) {
  method onFile (line 46) | onFile(fieldname, file, filename, encoding, mimetype) {

FILE: 5-network/06-fetch-api/post.view/server.js
  function accept (line 10) | function accept(req, res) {

FILE: 5-network/08-xmlhttprequest/example.view/server.js
  function accept (line 7) | function accept(req, res) {

FILE: 5-network/08-xmlhttprequest/phones-async.view/server.js
  function accept (line 10) | function accept(req, res) {

FILE: 5-network/08-xmlhttprequest/phones.view/server.js
  function accept (line 10) | function accept(req, res) {

FILE: 5-network/08-xmlhttprequest/post.view/server.js
  function accept (line 10) | function accept(req, res) {

FILE: 5-network/09-resume-upload/upload-resume.view/server.js
  function onUpload (line 10) | function onUpload(req, res) {
  function onStatus (line 90) | function onStatus(req, res) {
  function accept (line 102) | function accept(req, res) {

FILE: 5-network/09-resume-upload/upload-resume.view/uploader.js
  class Uploader (line 1) | class Uploader {
    method constructor (line 3) | constructor({file, onProgress}) {
    method getUploadedBytes (line 12) | async getUploadedBytes() {
    method upload (line 28) | async upload() {
    method stop (line 69) | stop() {

FILE: 5-network/10-long-polling/longpoll.view/browser.js
  function PublishForm (line 2) | function PublishForm(form, url) {
  function SubscribePane (line 22) | function SubscribePane(elem, url) {

FILE: 5-network/10-long-polling/longpoll.view/server.js
  function onSubscribe (line 10) | function onSubscribe(req, res) {
  function publish (line 24) | function publish(message) {
  function accept (line 34) | function accept(req, res) {
  function close (line 63) | function close() {

FILE: 5-network/11-websocket/chat.view/server.js
  function accept (line 17) | function accept(req, res) {
  function onSocketConnect (line 32) | function onSocketConnect(ws) {

FILE: 5-network/11-websocket/demo.view/server.js
  function accept (line 6) | function accept(req, res) {
  function onConnect (line 22) | function onConnect(ws) {

FILE: 5-network/12-server-sent-events/eventsource.view/server.js
  function onDigits (line 7) | function onDigits(req, res) {
  function accept (line 33) | function accept(req, res) {

FILE: 6-data-storage/01-cookie/cookie.js
  function getCookie (line 1) | function getCookie(name) {
  function setCookie (line 8) | function setCookie(name, value, options = {}) {
  function deleteCookie (line 34) | function deleteCookie(name) {

FILE: 7-animation/3-js-animation/width.view/animate.js
  function animate (line 1) | function animate({duration, draw, timing}) {

FILE: 8-web-components/2-custom-elements/1-live-timer/solution.view/live-timer.js
  class LiveTimer (line 1) | class LiveTimer extends HTMLElement {
    method render (line 3) | render() {
    method connectedCallback (line 12) | connectedCallback() { // (2)
    method update (line 20) | update() {
    method disconnectedCallback (line 26) | disconnectedCallback() {

FILE: 8-web-components/2-custom-elements/1-live-timer/solution.view/time-formatted.js
  class TimeFormatted (line 1) | class TimeFormatted extends HTMLElement {
    method render (line 3) | render() {
    method connectedCallback (line 17) | connectedCallback() {
    method observedAttributes (line 24) | static get observedAttributes() {
    method attributeChangedCallback (line 28) | attributeChangedCallback(name, oldValue, newValue) {

FILE: 8-web-components/2-custom-elements/1-live-timer/source.view/live-timer.js
  class LiveTimer (line 1) | class LiveTimer extends HTMLElement {

FILE: 8-web-components/2-custom-elements/1-live-timer/source.view/time-formatted.js
  class TimeFormatted (line 1) | class TimeFormatted extends HTMLElement {
    method render (line 3) | render() {
    method connectedCallback (line 17) | connectedCallback() {
    method observedAttributes (line 24) | static get observedAttributes() {
    method attributeChangedCallback (line 28) | attributeChangedCallback(name, oldValue, newValue) {
Condensed preview — 1171 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,732K chars).
[
  {
    "path": ".gitattributes",
    "chars": 38,
    "preview": "* text=auto eol=lf\n*.svg       binary\n"
  },
  {
    "path": ".gitignore",
    "chars": 184,
    "preview": "*.diff\n*.err\n*.orig\n*.log\n*.rej\n*.swo\n*.swp\n*.vi\n*~\n*.sass-cache\n\n# OS or Editor folders\n.DS_Store\n.idea\n.cache\n.project"
  },
  {
    "path": "1-js/01-getting-started/1-intro/article.md",
    "chars": 10247,
    "preview": "# Une Introduction à JavaScript\n\nVoyons ce qui est spécial à propos de JavaScript, ce qu'il nous permet de faire et avec"
  },
  {
    "path": "1-js/01-getting-started/2-manuals-specifications/article.md",
    "chars": 2667,
    "preview": "\n# Manuels et spécifications\n\nCe livre est un *tutoriel*. Il vise à vous aider à apprendre progressivement le langage. M"
  },
  {
    "path": "1-js/01-getting-started/3-code-editors/article.md",
    "chars": 3932,
    "preview": "# Les éditeurs de code \n\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/KNs-GfVmt3A\" title=\"YouTube"
  },
  {
    "path": "1-js/01-getting-started/4-devtools/article.md",
    "chars": 4242,
    "preview": "# La console de développement\n\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/OFj8hFVS1KY\" title=\"Y"
  },
  {
    "path": "1-js/01-getting-started/4-devtools/bug.html",
    "chars": 172,
    "preview": "<!DOCTYPE HTML>\n<html>\n\n<head>\n  <meta charset=\"utf-8\">\n</head>\n\n<body>\n\n  There is an error in the script on this page."
  },
  {
    "path": "1-js/01-getting-started/index.md",
    "chars": 94,
    "preview": "# Une introduction\n\nA propos du langage JavaScript et de l'environnement pour le développeur.\n"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/1-hello-alert/index.html",
    "chars": 105,
    "preview": "<!DOCTYPE html>\n<html>\n\n<body>\n\n  <script>\n    alert( \"I'm JavaScript!\" );\n  </script>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/1-hello-alert/solution.md",
    "chars": 27,
    "preview": "\r\n[html src=\"index.html\"]\r\n"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/1-hello-alert/solution.view/index.html",
    "chars": 104,
    "preview": "<!DOCTYPE html>\n<html>\n\n<body>\n\n  <script>\n    alert( \"I'm JavaScript!\" );\n  </script>\n\n</body>\n\n</html>"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/1-hello-alert/task.md",
    "chars": 242,
    "preview": "importance: 5\n\n---\n\n# Afficher une alerte\n\nCréez une page qui affiche un message \"Je suis JavaScript!\".\n\nFaites-le dans "
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/2-hello-alert-ext/alert.js",
    "chars": 25,
    "preview": "alert(\"I'm JavaScript!\");"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/2-hello-alert-ext/index.html",
    "chars": 84,
    "preview": "<!DOCTYPE html>\n<html>\n\n<body>\n\n  <script src=\"alert.js\"></script>\n\n</body>\n\n</html>"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/2-hello-alert-ext/solution.md",
    "chars": 113,
    "preview": "The HTML code:\n\n[html src=\"index.html\"]\n\npour le fichier `alert.js` dans le même dossier :\n\n[js src=\"alert.js\"]\n\n"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/2-hello-alert-ext/task.md",
    "chars": 303,
    "preview": "importance: 5\n\n---\n\n# Afficher une alerte avec un script externe\n\nPrendre la solution de l'exercice précédent <info:task"
  },
  {
    "path": "1-js/02-first-steps/01-hello-world/article.md",
    "chars": 5722,
    "preview": "# Hello, world!\n\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/0WS0zqhT5fM\" title=\"YouTube video p"
  },
  {
    "path": "1-js/02-first-steps/02-structure/article.md",
    "chars": 6043,
    "preview": "# Structure du code\n\nLa première chose à apprendre est de construire des blocs de code.\n\n## Instructions\n\nLes instructio"
  },
  {
    "path": "1-js/02-first-steps/03-strict-mode/article.md",
    "chars": 4151,
    "preview": "# Le mode moderne, \"use strict\"\n\nJavaScript a longtemps évolué sans problèmes de compatibilité. De nouvelles fonctionnal"
  },
  {
    "path": "1-js/02-first-steps/04-variables/1-hello-variables/solution.md",
    "chars": 221,
    "preview": "Dans le code ci-dessous, chaque ligne correspond à l'élément de la liste des tâches.\n\n```js run\nlet admin, name; // on p"
  },
  {
    "path": "1-js/02-first-steps/04-variables/1-hello-variables/task.md",
    "chars": 265,
    "preview": "importance: 2\n\n---\n\n# Travailler avec des variables\n\n1. Déclarez deux variables : `admin` and `name`.\n2. Assignez la val"
  },
  {
    "path": "1-js/02-first-steps/04-variables/2-declare-variables/solution.md",
    "chars": 762,
    "preview": "## La variable pour notre planète\n\nC’est simple :\n\n```js\nlet notrePlanete = \"Terre\";\n```\n\nNotez que nous pourrions utili"
  },
  {
    "path": "1-js/02-first-steps/04-variables/2-declare-variables/task.md",
    "chars": 238,
    "preview": "importance: 3\n\n---\n\n# Assigner le bon nom\n\n1. Créez la variable avec le nom de notre planète. Comment nommeriez-vous une"
  },
  {
    "path": "1-js/02-first-steps/04-variables/3-uppercast-constant/solution.md",
    "chars": 607,
    "preview": "Nous utilisons généralement des majuscules pour les constantes \"codées en dur\". Ou, en d'autres termes, lorsque la valeu"
  },
  {
    "path": "1-js/02-first-steps/04-variables/3-uppercast-constant/task.md",
    "chars": 822,
    "preview": "importance: 4\n\n---\n\n# Constante en majuscule ?\n\nExaminez le code suivant :\n\n```js\nconst birthday = '18.04.1982';\n\nconst "
  },
  {
    "path": "1-js/02-first-steps/04-variables/article.md",
    "chars": 13858,
    "preview": "# Les variables\n\nLa plupart du temps, une application JavaScript doit utiliser des informations. Voici 2 exemples :\n1. U"
  },
  {
    "path": "1-js/02-first-steps/05-types/1-string-quotes/solution.md",
    "chars": 384,
    "preview": "\nBackticks incorpore l'expression à l'intérieur de `${...}` dans la chaîne de caractères.\n\n```js run\nlet name = \"Ilya\";\n"
  },
  {
    "path": "1-js/02-first-steps/05-types/1-string-quotes/task.md",
    "chars": 195,
    "preview": "importance: 5\n\n---\n\n# String quotes\n\nQuelle est la sortie du script ?\n\n```js\nlet name = \"Ilya\";\n\nalert( `hello ${1}` ); "
  },
  {
    "path": "1-js/02-first-steps/05-types/article.md",
    "chars": 12994,
    "preview": "# Les types de données\n\nUne valeur en JavaScript est toujours d'un certain type. Par exemple, une chaîne de caractères o"
  },
  {
    "path": "1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/solution.md",
    "chars": 284,
    "preview": "JavaScript-code:\n\n```js demo run\nlet name = prompt(\"What is your name?\", \"\");\nalert(name);\n```\n\nLa page complète :\n\n```h"
  },
  {
    "path": "1-js/02-first-steps/06-alert-prompt-confirm/1-simple-page/task.md",
    "chars": 98,
    "preview": "importance: 4\n\n---\n\n# Une simple page\n\nCréez une page Web qui demande un nom et l'affiche\n\n[demo]\n"
  },
  {
    "path": "1-js/02-first-steps/06-alert-prompt-confirm/article.md",
    "chars": 3694,
    "preview": "# Interaction: alert, prompt, confirm\n\nComme nous allons utiliser le navigateur comme environnement de démonstration, vo"
  },
  {
    "path": "1-js/02-first-steps/07-type-conversions/article.md",
    "chars": 6779,
    "preview": "# Les conversions de types\n\nLa plupart du temps, les opérateurs et les fonctions convertissent automatiquement les valeu"
  },
  {
    "path": "1-js/02-first-steps/08-operators/1-increment-order/solution.md",
    "chars": 311,
    "preview": "\nLa réponse est :\n\n- `a = 2`\n- `b = 2`\n- `c = 2`\n- `d = 1`\n\n```js run no-beautify\nlet a = 1, b = 1;\n\nalert( ++a ); // 2,"
  },
  {
    "path": "1-js/02-first-steps/08-operators/1-increment-order/task.md",
    "chars": 227,
    "preview": "importance: 5\n\n---\n\n# Les formes postfixes et préfixes\n\nQuelles sont les valeurs finales de toutes les variables `a`, `b"
  },
  {
    "path": "1-js/02-first-steps/08-operators/2-assignment-result/solution.md",
    "chars": 78,
    "preview": "La réponse est :\n\n- `a = 4` (multiplié par 2)\n- `x = 5` (calculé comme 1 + 4)\n"
  },
  {
    "path": "1-js/02-first-steps/08-operators/2-assignment-result/task.md",
    "chars": 157,
    "preview": "importance: 3\n\n---\n\n# Résultat d'affectation\n\nQuelles sont les valeurs de `a` et `x` après le code ci-dessous ?\n\n```js\nl"
  },
  {
    "path": "1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md",
    "chars": 1275,
    "preview": "\n```js no-beautify\n\"\" + 1 + 0 = \"10\" // (1)\n\"\" - 1 + 0 = -1 // (2)\ntrue + false = 1\n6 / \"3\" = 2\n\"2\" * \"3\" = 6\n4 + 5 + \"p"
  },
  {
    "path": "1-js/02-first-steps/08-operators/3-primitive-conversions-questions/task.md",
    "chars": 330,
    "preview": "importance: 5\n\n---\n\n# Les conversions de type \n\nQuels sont les résultats de ces expressions ?\n\n```js no-beautify\n\"\" + 1 "
  },
  {
    "path": "1-js/02-first-steps/08-operators/4-fix-prompt/solution.md",
    "chars": 817,
    "preview": "La raison en est que le prompt renvoie l'entrée utilisateur sous forme de chaîne de caractères.\n\nLes variables ont donc "
  },
  {
    "path": "1-js/02-first-steps/08-operators/4-fix-prompt/task.md",
    "chars": 404,
    "preview": "importance: 5\n\n---\n\n# Corrigez l'addition\n\nVoici un code qui demande à l'utilisateur deux nombres et affiche leur somme."
  },
  {
    "path": "1-js/02-first-steps/08-operators/article.md",
    "chars": 17641,
    "preview": "# Opérateurs de base, mathématiques\n\nDe nombreux opérateurs nous sont connus de l'école. Ce sont les additions `+`, mult"
  },
  {
    "path": "1-js/02-first-steps/09-comparison/1-comparison-questions/solution.md",
    "chars": 707,
    "preview": "\n\n```js no-beautify\n5 > 4 → true\n\"apple\" > \"pineapple\" → false\n\"2\" > \"12\" → true\nundefined == null → true\nundefined === "
  },
  {
    "path": "1-js/02-first-steps/09-comparison/1-comparison-questions/task.md",
    "chars": 225,
    "preview": "importance: 5\n\n---\n\n# Comparaisons\n\nQuel sera le résultat pour les expressions suivantes :\n\n```js no-beautify\n5 > 4\n\"app"
  },
  {
    "path": "1-js/02-first-steps/09-comparison/article.md",
    "chars": 9285,
    "preview": "# Comparaisons\n\nIl y a de nombreux opérateurs de comparaison que nous connaissons des mathématiques :\n\n- Plus grand/peti"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md",
    "chars": 237,
    "preview": "**Oui, il sera affiché.**\n\nToute chaîne de caractères à l'exception d'une chaîne vide (et `\"0\"` n'est pas vide) devient "
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md",
    "chars": 142,
    "preview": "importance: 5\n\n---\n\n# if (une chaîne de caractères avec zéro)\n\nEst-ce que `alert` sera affiché ?\n\n```js\nif (\"0\") {\n  ale"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2/index.html",
    "chars": 286,
    "preview": "<!DOCTYPE html>\n<html>\n\n<body>\n  <script>\n    'use strict';\n\n    let value = prompt('What is the \"official\" name of Java"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/2-check-standard/solution.md",
    "chars": 44,
    "preview": "\n\n[html run src=\"ifelse_task2/index.html\"]\n\n"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/2-check-standard/task.md",
    "chars": 334,
    "preview": "importance: 2\n\n---\n\n# Le nom de JavaScript\n\nEn utilisant la construction `if..else`, écrivez le code qui demande : 'Quel"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/3-sign/if_sign/index.html",
    "chars": 254,
    "preview": "<!DOCTYPE html>\n<html>\n\n<body>\n\n  <script>\n    'use strict';\n\n    let value = prompt('Type a number', 0);\n\n    if (value"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/3-sign/solution.md",
    "chars": 153,
    "preview": "\n\n```js run\nlet value = prompt('Type a number', 0);\n\nif (value > 0) {\n  alert( 1 );\n} else if (value < 0) {\n  alert( -1 "
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/3-sign/task.md",
    "chars": 343,
    "preview": "importance: 2\n\n---\n\n# Afficher le signe\n\nEn utilisant `if..else`, écrivez le code qui obtient un numéro via le `prompt`,"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/5-rewrite-if-question/solution.md",
    "chars": 58,
    "preview": "\n\n```js\nlet result = (a + b < 4) ? 'Below' : 'Over';\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md",
    "chars": 199,
    "preview": "importance: 5\n\n---\n\n# Réécrire 'if' en '?'\n\nRéécrivez ce `if` en utilisant l'opérateur conditionnel `'?'` :\n\n```js\nlet r"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/solution.md",
    "chars": 138,
    "preview": "\n\n```js\nlet message = (login == 'Employee') ? 'Hello' :\n  (login == 'Director') ? 'Greetings' :\n  (login == '') ? 'No lo"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/task.md",
    "chars": 417,
    "preview": "importance: 5\n\n---\n\n# Réécrire 'if..else' en '?'\n\nRéécrire ce `if..else` en utilisant plusieurs opérateurs ternaires `'?"
  },
  {
    "path": "1-js/02-first-steps/10-ifelse/article.md",
    "chars": 7124,
    "preview": "# Branche conditionnelle : if, '?'\n\nParfois, nous devons effectuer différentes actions en fonction d'une condition.\n\nPou"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/solution.md",
    "chars": 101,
    "preview": "La réponse est `2`, c'est la première valeur vraie.\n\n```js run\nalert( null || 2 || undefined );\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/task.md",
    "chars": 142,
    "preview": "importance: 5\n\n---\n\n# Quel est le résultat de OR ?\n\nQu'est-ce que le code ci-dessous va sortir ?\n\n```js\nalert( null || 2"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/2-alert-or/solution.md",
    "chars": 617,
    "preview": "La réponse : d'abord `1` puis `2`.\n\n```js run\nalert( alert(1) || 2 || alert(3) );\n```\n\nRègle importante à retenir : **L'"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/2-alert-or/task.md",
    "chars": 154,
    "preview": "importance: 3\n\n---\n\n# Quel est le résultat des alertes OR ?\n\nQu'est-ce que le code ci-dessous va sortir ?\n\n```js\nalert( "
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md",
    "chars": 110,
    "preview": "La réponse : `null`, car c'est la première valeur `false` de la liste.\n\n```js run\nalert(1 && null && 2);\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/task.md",
    "chars": 126,
    "preview": "importance: 5\n\n---\n\n# Quel est le résultat de AND ?\n\nQu'est-ce que ce code va afficher ?\n\n```js\nalert( 1 && null && 2 );"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/4-alert-and/solution.md",
    "chars": 428,
    "preview": "La réponse : `1`, et ensuite `undefined`.\n\n```js run\nalert( alert(1) && alert(2) );\n```\n\nL’appel de l'`alert` renvoie un"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/4-alert-and/task.md",
    "chars": 141,
    "preview": "importance: 3\n\n---\n\n# Quel est le résultat des alertes AND ?\n\nQu’est-ce que ce code va afficher ?\n\n```js\nalert( alert(1)"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/5-alert-and-or/solution.md",
    "chars": 290,
    "preview": "La réponse : `3`.\n\n```js run\nalert( null || 2 && 3 || 4 );\n```\n\nLa priorité de AND `&&` est supérieure à OR `||`, elle s"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/5-alert-and-or/task.md",
    "chars": 114,
    "preview": "importance: 5\n\n---\n\n# Le résultat de OR AND OR\n\nQuel sera le résultat ?\n\n```js\nalert( null || 2 && 3 || 4 );\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/6-check-if-in-range/solution.md",
    "chars": 41,
    "preview": "\n\n```js\nif (age >= 14 && age <= 90)\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/6-check-if-in-range/task.md",
    "chars": 213,
    "preview": "importance: 3\n\n---\n\n# Vérifiez la plage entre\n\nEcrivez une condition `\"if\"` pour vérifier que l’`age` est compris entre "
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/7-check-if-out-range/solution.md",
    "chars": 126,
    "preview": "La première variante :\n\n```js\nif (!(age >= 14 && age <= 90))\n```\n\nLa seconde variante :\n\n```js\nif (age < 14 || age > 90)"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/7-check-if-out-range/task.md",
    "chars": 244,
    "preview": "importance: 3\n\n---\n\n# Vérifiez à l'extérieur de la plage\n\nEcrivez une condition `if` pour vérifier que l’`age` n’est PAS"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/8-if-question/solution.md",
    "chars": 448,
    "preview": "La réponse: le premier et le troisième vont s'exécuter.\n\nDetails:\n\n```js run\n// S'éxécute\n// le résultat de -1 || 0 = -1"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/8-if-question/task.md",
    "chars": 289,
    "preview": "importance: 5\n\n---\n\n# Une question à propos de \"if\"\n\nLesquelles de ces `alert`es vont s'exécuter ?\n\nQuels seront les rés"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/9-check-login/solution.md",
    "chars": 559,
    "preview": "\n\n```js run demo\nlet userName = prompt(\"Who's there?\", '');\n\nif (userName === 'Admin') {\n\n  let pass = prompt('Password?"
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/9-check-login/task.md",
    "chars": 840,
    "preview": "importance: 3\n\n---\n\n# Check the login\n\nÉcrivez le code qui demande une connexion avec `prompt`.\n\nSi le visiteur entre `\""
  },
  {
    "path": "1-js/02-first-steps/11-logical-operators/article.md",
    "chars": 8948,
    "preview": "# Opérateurs logiques\n\nIl y a trois opérateurs logiques en JavaScript : `||` (OR), `&&` (AND), `!` (NOT), `??` (Coalesce"
  },
  {
    "path": "1-js/02-first-steps/12-nullish-coalescing-operator/article.md",
    "chars": 6452,
    "preview": "# L'opérateur de coalescence des nuls '??'\n\n[recent browser=\"new\"]\n\nL'opérateur de coalescence des nuls est écrit sous l"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/1-loop-last-value/solution.md",
    "chars": 477,
    "preview": "La réponse : `1`.\n\n```js run\nlet i = 3;\n\nwhile (i) {\n  alert( i-- );\n}\n```\n\nChaque itération de boucle diminue `i` de `1"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/1-loop-last-value/task.md",
    "chars": 166,
    "preview": "importance: 3\n\n---\n\n# Dernière valeur de boucle\n\nQuelle est la dernière valeur affichée par ce code ? Pourquoi ?\n\n```js\n"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/2-which-value-while/solution.md",
    "chars": 1574,
    "preview": "L'exercice montre comment les formes postfix/prefix peuvent conduire à des résultats différents lorsqu’ils sont utilisés"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/2-which-value-while/task.md",
    "chars": 453,
    "preview": "importance: 4\n\n---\n\n# Quelles valeurs affiche la boucle while ?\n\nA votre avis, quelles sont les valeurs affichées pour c"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/3-which-value-for/solution.md",
    "chars": 576,
    "preview": "**La réponse: de `0` à `4` dans les deux cas.**\n\n```js run\nfor (let i = 0; i < 5; ++i) alert( i );\n\nfor (let i = 0; i < "
  },
  {
    "path": "1-js/02-first-steps/13-while-for/3-which-value-for/task.md",
    "chars": 393,
    "preview": "importance: 4\n\n---\n\n# Quelles valeurs sont affichées par la boucle \"for\" ?\n\nPour chaque boucle, notez les valeurs qui vo"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/4-for-even/solution.md",
    "chars": 196,
    "preview": "\n\n```js run demo\nfor (let i = 2; i <= 10; i++) {\n  if (i % 2 == 0) {\n    alert( i );\n  }\n}\n```\n\nIci nous utilisons l'opé"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/4-for-even/task.md",
    "chars": 145,
    "preview": "importance: 5\n\n---\n\n# Extraire les nombres pairs dans la boucle\n\nUtilisez la boucle `for` pour afficher les nombres pair"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/5-replace-for-while/solution.md",
    "chars": 80,
    "preview": "\n\n```js run\nlet i = 0;\nwhile (i < 3) {\n  alert( `number ${i}!` );\n  i++;\n}\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/5-replace-for-while/task.md",
    "chars": 248,
    "preview": "importance: 5\n\n---\n\n# Remplacer \"for\" par \"while\"\n\nRéécrivez le code en modifiant la boucle `for` en `while` sans modifi"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/6-repeat-until-correct/solution.md",
    "chars": 653,
    "preview": "\n```js run demo\nlet num;\n\ndo {\n  num = prompt(\"Enter a number greater than 100?\", 0);\n} while (num <= 100 && num);\n```\n\n"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/6-repeat-until-correct/task.md",
    "chars": 538,
    "preview": "importance: 5\n\n---\n\n# Répéter jusqu'à ce que l'entrée soit correcte\n\nEcrivez une boucle qui demande un nombre supérieur "
  },
  {
    "path": "1-js/02-first-steps/13-while-for/7-list-primes/solution.md",
    "chars": 1056,
    "preview": "Il existe de nombreux algorithmes pour cette tâche.\n\nUtilisons une boucle imbriquée :\n\n```js\nPour chaque i dans l'interv"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/7-list-primes/task.md",
    "chars": 698,
    "preview": "importance: 3\n\n---\n\n# Extraire des nombres premiers\n\nUn nombre entier supérieur à 1 est appelé un [Nombre premier](https"
  },
  {
    "path": "1-js/02-first-steps/13-while-for/article.md",
    "chars": 12750,
    "preview": "# Boucles : while et for\n\nNous avons souvent besoin d'effectuer des actions similaires plusieurs fois de suite.\n\nPar exe"
  },
  {
    "path": "1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/solution.md",
    "chars": 719,
    "preview": "Pour correspondre précisément à la fonctionnalité du `switch`, le `if` doit utiliser une comparaison stricte `'==='`.\n\nC"
  },
  {
    "path": "1-js/02-first-steps/14-switch/1-rewrite-switch-if-else/task.md",
    "chars": 426,
    "preview": "importance: 5\n\n---\n\n# Réécrire le \"switch\" dans un \"if\"\n\nÉcrivez le code en utilisant `if..else` qui correspondrait au `"
  },
  {
    "path": "1-js/02-first-steps/14-switch/2-rewrite-if-switch/solution.md",
    "chars": 649,
    "preview": "Les deux premiers contrôles se transforment en deux `case`. Le troisième contrôle est divisé en deux `case` :\n\n```js run"
  },
  {
    "path": "1-js/02-first-steps/14-switch/2-rewrite-if-switch/task.md",
    "chars": 281,
    "preview": "importance: 4\n\n---\n\n# Réécrire le \"if\" dans un \"switch\"\n\nRéécrivez le code ci-dessous en utilisant une seule instruction"
  },
  {
    "path": "1-js/02-first-steps/14-switch/article.md",
    "chars": 3979,
    "preview": "# La déclaration \"switch\"\n\nUne instruction `switch` peut remplacer plusieurs vérification `if`.\n\nCela donne un moyen plu"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md",
    "chars": 141,
    "preview": "Aucune différence.\n\nDans les deux cas, `return confirm('Did parents allow you?')` s'exécute exactement lorsque la condit"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/1-if-else-required/task.md",
    "chars": 633,
    "preview": "importance: 4\n\n---\n\n# Est-ce que \"else\" est requis ?\n\nLa fonction suivante renvoie `true` si le paramètre `age` est supé"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/solution.md",
    "chars": 432,
    "preview": "En utilisant un opérateur point d’interrogation `'?'` :\n\n```js\nfunction checkAge(age) {\n  return (age > 18) ? true : con"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/2-rewrite-function-question-or/task.md",
    "chars": 547,
    "preview": "importance: 4\n\n---\n\n# Réécrivez la fonction en utilisant '?' ou '||'\n\nLa fonction suivante renvoie `true` si le paramètr"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/3-min/solution.md",
    "chars": 325,
    "preview": "Une solution utilisant `if` :\n\n```js\nfunction min(a, b) {\n  if (a < b) {\n    return a;\n  } else {\n    return b;\n  }\n}\n``"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/3-min/task.md",
    "chars": 204,
    "preview": "importance: 1\n\n---\n\n# Fonction min(a, b)\n\nEcrivez une fonction `min(a, b)` qui renvoie le plus petit des deux nombres `a"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/4-pow/solution.md",
    "chars": 297,
    "preview": "\n```js run demo\nfunction pow(x, n) {\n  let result = x;\n\n  for (let i = 1; i < n; i++) {\n    result *= x;\n  }\n\n  return r"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/4-pow/task.md",
    "chars": 509,
    "preview": "importance: 4\n\n---\n\n# Fonction pow(x,n)\n\nEcrivez une fonction `pow(x, n)` qui renvoie `x` à la puissance `n`. Ou, autrem"
  },
  {
    "path": "1-js/02-first-steps/15-function-basics/article.md",
    "chars": 18211,
    "preview": "# Fonctions\n\nTrès souvent, nous devons effectuer une action similaire à plusieurs endroits du script.\n\nPar exemple, nous"
  },
  {
    "path": "1-js/02-first-steps/16-function-expressions/article.md",
    "chars": 13526,
    "preview": "# Fonctions Expressions\n\nEn JavaScript, une fonction n'est pas une \"structure de langage magique\", mais un type de valeu"
  },
  {
    "path": "1-js/02-first-steps/17-arrow-functions-basics/1-rewrite-arrow/solution.md",
    "chars": 243,
    "preview": "\n```js run\nfunction ask(question, yes, no) {\n  if (confirm(question)) yes();\n  else no();\n}\n\nask(\n  \"Do you agree?\",\n*!*"
  },
  {
    "path": "1-js/02-first-steps/17-arrow-functions-basics/1-rewrite-arrow/task.md",
    "chars": 351,
    "preview": "\n# Réécrire avec les fonctions fléchées\n\nRemplacez les expressions de fonction par des fonctions fléchées dans le code c"
  },
  {
    "path": "1-js/02-first-steps/17-arrow-functions-basics/article.md",
    "chars": 3778,
    "preview": "# Fonctions fléchées, les bases\n\nIl existe une syntaxe plus simple et concise pour créer des fonctions, c'est souvent mi"
  },
  {
    "path": "1-js/02-first-steps/18-javascript-specials/article.md",
    "chars": 9427,
    "preview": "# JavaScript specials\n\nCe chapitre récapitule brièvement les fonctionnalités de JavaScript que nous avons apprises à ce "
  },
  {
    "path": "1-js/02-first-steps/index.md",
    "chars": 78,
    "preview": "# Fondamentaux JavaScript\n\nApprenons les bases de la construction de scripts.\n"
  },
  {
    "path": "1-js/03-code-quality/01-debugging-chrome/article.md",
    "chars": 11956,
    "preview": "# Débogage dans le navigateur\n\nAvant d’écrire un code plus complexe, parlons de débogage.\n\nLe [Debugging](https://en.wik"
  },
  {
    "path": "1-js/03-code-quality/01-debugging-chrome/debugging.view/hello.js",
    "chars": 129,
    "preview": "function hello(name) {\n  let phrase = `Hello, ${name}!`;\n\n  say(phrase);\n}\n\nfunction say(phrase) {\n  alert(`** ${phrase}"
  },
  {
    "path": "1-js/03-code-quality/01-debugging-chrome/debugging.view/index.html",
    "chars": 153,
    "preview": "<!DOCTYPE HTML>\n<html>\n<body>\n\n  <script src=\"hello.js\"></script>\n\n  An example for debugging.\n\n  <script>\n  hello(\"John"
  },
  {
    "path": "1-js/03-code-quality/01-debugging-chrome/head.html",
    "chars": 156,
    "preview": "<style>\nspan.devtools {\n  display: inline-block;\n  background-image: url(/article/debugging-chrome/largeIcons.svg);\n  he"
  },
  {
    "path": "1-js/03-code-quality/02-coding-style/1-style-errors/solution.md",
    "chars": 1281,
    "preview": "\nVous pouvez noter ce qui suit :\n\n```js no-beautify\nfunction pow(x,n)  // <- pas d'espace entre les arguments\n{  // <- a"
  },
  {
    "path": "1-js/03-code-quality/02-coding-style/1-style-errors/task.md",
    "chars": 393,
    "preview": "importance: 4\n\n---\n\n# Mauvais style\n\nQuel est le problème avec le style de code ci-dessous ?\n\n```js no-beautify\nfunction"
  },
  {
    "path": "1-js/03-code-quality/02-coding-style/article.md",
    "chars": 11621,
    "preview": "# Style de codage\n\nNotre code doit être aussi propre et lisible que possible.\n\nC’est en fait un art de la programmation "
  },
  {
    "path": "1-js/03-code-quality/03-comments/article.md",
    "chars": 6686,
    "preview": "# Commentaires\n\nComme nous le savons du chapitre <info:structure>, les commentaires peuvent être simples : à partir de `"
  },
  {
    "path": "1-js/03-code-quality/04-ninja-code/article.md",
    "chars": 12246,
    "preview": "# Ninja code\n\n\n```quote author=\"Confucius (Entretiens)\"\nApprendre sans réfléchir est vain. Réfléchir sans apprendre est "
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md",
    "chars": 1638,
    "preview": "Le test illustre l'une des tentations qu'un développeur rencontre lorsqu'il écrit des tests.\n\nCe que nous avons ici est "
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md",
    "chars": 398,
    "preview": "importance: 5\n\n---\n\n# Quel est le problème dans le test ?\n\nQu'est-ce qui ne va pas dans le test de `pow` ci-dessous ?\n\n`"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/article.md",
    "chars": 17340,
    "preview": "# Testing automatisé avec Mocha\n\nLes tests automatisés seront utilisés dans d'autres tâches. Ils sont également largemen"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/beforeafter.view/index.html",
    "chars": 854,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js",
    "chars": 646,
    "preview": "describe(\"test\", function() {\n  \n   // Mocha usually waits for the tests for 2 seconds before considering them wrong\n  \n"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/index.html",
    "chars": 948,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-1.view/index.html",
    "chars": 963,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js",
    "chars": 115,
    "preview": "describe(\"pow\", function() {\n\n  it(\"raises to n-th power\", function() {\n    assert.equal(pow(2, 3), 8);\n  });\n\n});\n"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-2.view/index.html",
    "chars": 941,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js",
    "chars": 206,
    "preview": "describe(\"pow\", function() {\n\n  it(\"2 raised to power 3 is 8\", function() {\n    assert.equal(pow(2, 3), 8);\n  });\n\n  it("
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-3.view/index.html",
    "chars": 1019,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js",
    "chars": 256,
    "preview": "describe(\"pow\", function() {\n\n  function makeTest(x) {\n    let expected = x * x * x;\n    it(`${x} in the power 3 is ${ex"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-4.view/index.html",
    "chars": 1019,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js",
    "chars": 399,
    "preview": "describe(\"pow\", function() {\n\n  describe(\"raises x to power 3\", function() {\n\n    function makeTest(x) {\n      let expec"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-full.view/index.html",
    "chars": 1089,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js",
    "chars": 521,
    "preview": "describe(\"pow\", function() {\n\n  describe(\"raises x to power 3\", function() {\n\n    function makeTest(x) {\n      let expec"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-min.view/index.html",
    "chars": 937,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js",
    "chars": 115,
    "preview": "describe(\"pow\", function() {\n\n  it(\"raises to n-th power\", function() {\n    assert.equal(pow(2, 3), 8);\n  });\n\n});\n"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-nan.view/index.html",
    "chars": 1017,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!-- add mocha css, to show results -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.clo"
  },
  {
    "path": "1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js",
    "chars": 521,
    "preview": "describe(\"pow\", function() {\n\n  describe(\"raises x to power 3\", function() {\n\n    function makeTest(x) {\n      let expec"
  },
  {
    "path": "1-js/03-code-quality/06-polyfills/article.md",
    "chars": 5780,
    "preview": "\n# Polyfills et transpilers\n\nLe langage JavaScript évolue régulièrement. De nouvelles propositions pour le langage appar"
  },
  {
    "path": "1-js/03-code-quality/index.md",
    "chars": 118,
    "preview": "# Qualité du code\n\nCe chapitre explique les pratiques de codage que nous utiliserons plus loin dans le développement.\n"
  },
  {
    "path": "1-js/04-object-basics/01-object/2-hello-object/solution.md",
    "chars": 110,
    "preview": "\n\n```js\nlet user = {};\nuser.name = \"John\";\nuser.surname = \"Smith\";\nuser.name = \"Pete\";\ndelete user.name;\n```\n\n"
  },
  {
    "path": "1-js/04-object-basics/01-object/2-hello-object/task.md",
    "chars": 319,
    "preview": "importance: 5\n\n---\n\n# Bonjour objet\n\nÉcrivez le code, une ligne pour chaque action :\n\n1. Créer un objet vide `user`.\n2. "
  },
  {
    "path": "1-js/04-object-basics/01-object/3-is-empty/_js.view/solution.js",
    "chars": 141,
    "preview": "function isEmpty(obj) {\n  for (let key in obj) {\n    // si la boucle a commencé, il y a une propriété\n    return false;\n"
  },
  {
    "path": "1-js/04-object-basics/01-object/3-is-empty/_js.view/test.js",
    "chars": 251,
    "preview": "describe(\"isEmpty\", function() {\n  it(\"returns true for an empty object\", function() {\n    assert.isTrue(isEmpty({}));\n "
  },
  {
    "path": "1-js/04-object-basics/01-object/3-is-empty/solution.md",
    "chars": 108,
    "preview": "Passez simplement une boucle sur l’objet et `return false` immédiatement s’il existe au moins une propriété."
  },
  {
    "path": "1-js/04-object-basics/01-object/3-is-empty/task.md",
    "chars": 311,
    "preview": "importance: 5\n\n---\n\n# Vérifier le vide\n\nEcrivez la fonction `isEmpty(obj)` qui renvoie `true` si l'objet n'a pas de prop"
  },
  {
    "path": "1-js/04-object-basics/01-object/4-const-object/solution.md",
    "chars": 347,
    "preview": "Bien sûr, ça fonctionne, pas de problème.\n\nLe `const` ne protège que la variable elle-même du changement.\n\nEn d'autres t"
  },
  {
    "path": "1-js/04-object-basics/01-object/4-const-object/task.md",
    "chars": 214,
    "preview": "importance: 5\n\n---\n\n# Objets constants ?\n\nEst-il possible de changer un objet déclaré avec `const`, comment ?\n\n```js\ncon"
  },
  {
    "path": "1-js/04-object-basics/01-object/5-sum-object/solution.md",
    "chars": 161,
    "preview": "\n```js run\nlet salaries = {\n  John: 100,\n  Ann: 160,\n  Pete: 130\n};\n\nlet sum = 0;\nfor (let key in salaries) {\n  sum += s"
  },
  {
    "path": "1-js/04-object-basics/01-object/5-sum-object/task.md",
    "chars": 382,
    "preview": "importance: 5\n\n---\n\n# Somme des propriétés de l'objet\n\nNous avons un objet stockant les salaires de notre équipe :\n\n```j"
  },
  {
    "path": "1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/solution.js",
    "chars": 128,
    "preview": "function multiplyNumeric(obj) {\n  for (let key in obj) {\n    if (typeof obj[key] == 'number') {\n      obj[key] *= 2;\n   "
  },
  {
    "path": "1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/source.js",
    "chars": 237,
    "preview": "let menu = {\n  width: 200,\n  height: 300,\n  title: \"My menu\"\n};\n\n\nfunction multiplyNumeric(obj) {\n  \n  /* your code */\n\n"
  },
  {
    "path": "1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/test.js",
    "chars": 439,
    "preview": "describe(\"multiplyNumeric\", function() {\n  it(\"multiplies all numeric properties by 2\", function() {\n    let menu = {\n  "
  },
  {
    "path": "1-js/04-object-basics/01-object/8-multiply-numeric/solution.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "1-js/04-object-basics/01-object/8-multiply-numeric/task.md",
    "chars": 588,
    "preview": "importance: 3\n\n---\n\n# Multipliez les valeurs de propriétés numériques par 2\n\nCréez une fonction `multiplyNumeric(obj)` q"
  },
  {
    "path": "1-js/04-object-basics/01-object/article.md",
    "chars": 16514,
    "preview": "\n# Objets\n\nComme nous le savons du chapitre <info:types>, il existe huit types de données dans le langage JavaScript. Se"
  },
  {
    "path": "1-js/04-object-basics/02-object-copy/article.md",
    "chars": 10752,
    "preview": "# Les références d'objet et leur copie\n\nUne des différences fondamentale des objets avec les primitives est que ceux-ci "
  },
  {
    "path": "1-js/04-object-basics/03-garbage-collection/article.md",
    "chars": 9888,
    "preview": "# Ramasse-miettes (garbage collection)\n\nLa gestion de la mémoire en JavaScript est effectuée automatiquement et de maniè"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/4-object-property-this/solution.md",
    "chars": 1486,
    "preview": "**Réponse : une erreur.**\n\nEssayez le :\n```js run\nfunction makeUser() {\n  return {\n    name: \"John\",\n    ref: this\n  };\n"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/4-object-property-this/task.md",
    "chars": 332,
    "preview": "importance: 5\n\n---\n\n# Utilisation de \"this\" dans le littéral d'objet\n\nIci, la fonction `makeUser` renvoie un objet.\n\nQue"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/7-calculator/_js.view/solution.js",
    "chars": 186,
    "preview": "let calculator = {\n  sum() {\n    return this.a + this.b;\n  },\n\n  mul() {\n    return this.a * this.b;\n  },\n\n  read() {\n  "
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/7-calculator/_js.view/test.js",
    "chars": 694,
    "preview": "\n\ndescribe(\"calculator\", function() {\n  \n  context(\"when 2 and 3 entered\", function() {\n    beforeEach(function() {\n    "
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/7-calculator/solution.md",
    "chars": 290,
    "preview": "\n```js run demo solution\nlet calculator = {\n  sum() {\n    return this.a + this.b;\n  },\n\n  mul() {\n    return this.a * th"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/7-calculator/task.md",
    "chars": 480,
    "preview": "importance: 5\n\n---\n\n# Créer une calculatrice\n\nCréez un objet `calculator` avec trois méthodes :\n\n- `read()` demande deux"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/solution.js",
    "chars": 218,
    "preview": "\nlet ladder = {\n  step: 0,\n  up: function() { \n    this.step++;\n    return this;\n  },\n  down: function() { \n    this.ste"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/test.js",
    "chars": 1094,
    "preview": "\ndescribe('Ladder', function() {\n  before(function() {\n    window.alert = sinon.stub(window, \"alert\");\n  });\n  \n  before"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md",
    "chars": 575,
    "preview": "La solution consiste à renvoyer l'objet lui-même à partir de chaque appel.\n\n```js run\nlet ladder = {\n  step: 0,\n  up() {"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/8-chain-calls/task.md",
    "chars": 735,
    "preview": "importance: 2\n\n---\n\n# Chaining\n\nIl y a un objet `ladder` qui permet de monter et descendre :\n\n```js\nlet ladder = {\n  ste"
  },
  {
    "path": "1-js/04-object-basics/04-object-methods/article.md",
    "chars": 8477,
    "preview": "# Méthodes d'objet, \"this\"\n\nLes objets sont généralement créés pour représenter des entités du monde réel, comme des uti"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/solution.md",
    "chars": 319,
    "preview": "Oui c'est possible.\n\nSi une fonction retourne un objet alors `new` le retourne au lieu de `this`.\n\nAinsi, ils peuvent, p"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md",
    "chars": 306,
    "preview": "importance: 2\n\n---\n\n# Deux fonctions - un objet\n\nEst-il possible de créer des fonctions `A` et `B` tel que `new A() == n"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/2-calculator-constructor/_js.view/solution.js",
    "chars": 240,
    "preview": "function Calculator() {\n\n  this.read = function() {\n    this.a = +prompt('a?', 0);\n    this.b = +prompt('b?', 0);\n  };\n\n"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/2-calculator-constructor/_js.view/test.js",
    "chars": 705,
    "preview": "\ndescribe(\"calculator\", function() {\n  let calculator;\n  before(function() {\n    sinon.stub(window, \"prompt\")\n\n    promp"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/2-calculator-constructor/solution.md",
    "chars": 388,
    "preview": "```js run demo\nfunction Calculator() {\n\n  this.read = function() {\n    this.a = +prompt('a?', 0);\n    this.b = +prompt('"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/2-calculator-constructor/task.md",
    "chars": 537,
    "preview": "importance: 5\n\n---\n\n# Créer une nouvelle calculatrice\n\nCréer une fonction constructeur `Calculator` qui crée des objets "
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/3-accumulator/_js.view/solution.js",
    "chars": 154,
    "preview": "function Accumulator(startingValue) {\n  this.value = startingValue;\n\n  this.read = function() {\n    this.value += +promp"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/3-accumulator/_js.view/test.js",
    "chars": 703,
    "preview": "describe(\"Accumulator\", function() {\n\n  beforeEach(function() {\n    sinon.stub(window, \"prompt\")\n  });\n\n  afterEach(func"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/3-accumulator/solution.md",
    "chars": 280,
    "preview": "\n\n```js run demo\nfunction Accumulator(startingValue) {\n  this.value = startingValue;\n\n  this.read = function() {\n    thi"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/3-accumulator/task.md",
    "chars": 823,
    "preview": "importance: 5\n\n---\n\n# Créer un nouvel accumulateur\n\nCréer une fonction constructeur `Accumulator(startingValue)`.\n\nL'obj"
  },
  {
    "path": "1-js/04-object-basics/06-constructor-new/article.md",
    "chars": 7777,
    "preview": "# Le constructeur, l'opérateur \"new\"\n\nLa syntaxe normale `{...}` permet de créer un seul objet. Mais souvent, nous devon"
  },
  {
    "path": "1-js/04-object-basics/07-optional-chaining/article.md",
    "chars": 9444,
    "preview": "# Chaînage optionnel '?.'\n\n[recent browser=\"new\"]\n\nLe chaînage optionnel `?.` est un moyen sécurisé d'accéder aux propri"
  },
  {
    "path": "1-js/04-object-basics/08-symbol/article.md",
    "chars": 11507,
    "preview": "\n# Type symbole\n\nPar spécification, seuls deux types primitifs peuvent servir de clés de propriété d'objet :\n\n- type str"
  },
  {
    "path": "1-js/04-object-basics/09-object-toprimitive/article.md",
    "chars": 13235,
    "preview": "# Conversion d'objet en primitive\n\nQue se passe-t-il lorsque des objets sont ajoutés `obj1 + obj2`, soustraits `obj1 - o"
  },
  {
    "path": "1-js/04-object-basics/index.md",
    "chars": 20,
    "preview": "# Objets: les bases\n"
  },
  {
    "path": "1-js/05-data-types/01-primitives-methods/1-string-new-property/solution.md",
    "chars": 790,
    "preview": "Essayez de lancer :\n\n```js run\nlet str = \"Hello\";\n\nstr.test = 5; // (*)\n\nalert(str.test);\n```\n\nSelon que vous utilisiez "
  },
  {
    "path": "1-js/05-data-types/01-primitives-methods/1-string-new-property/task.md",
    "chars": 233,
    "preview": "importance: 5\n\n---\n\n# Pouvons-nous ajouter une propiété à une primitive ?\n\nConsidérons le code suivant:\n\n```js\nlet str ="
  },
  {
    "path": "1-js/05-data-types/01-primitives-methods/article.md",
    "chars": 5894,
    "preview": "# Méthodes des primitives\n\nJavaScript nous permet de travailler avec des primitives (chaînes de caractères, nombres, etc"
  },
  {
    "path": "1-js/05-data-types/02-number/1-sum-interface/solution.md",
    "chars": 330,
    "preview": "```js run demo\nlet a = +prompt(\"Le premier numéro?\", \"\");\nlet b = +prompt(\"Le second numéro?\", \"\");\n\nalert( a + b );\n```"
  },
  {
    "path": "1-js/05-data-types/02-number/1-sum-interface/task.md",
    "chars": 196,
    "preview": "importance: 5\n\n---\n\n# Somme des nombres du visiteur\n\nCréez un script qui invite le visiteur à entrer deux nombres, puis "
  },
  {
    "path": "1-js/05-data-types/02-number/2-why-rounded-down/solution.md",
    "chars": 1213,
    "preview": "En interne, la fraction décimale `6.35` est un nombre binaire sans fin. Comme toujours dans de tels cas, il est stocké a"
  },
  {
    "path": "1-js/05-data-types/02-number/2-why-rounded-down/task.md",
    "chars": 511,
    "preview": "importance: 4\n\n---\n\n# Pourquoi 6.35.toFixed(1) == 6.3 ?\n\nSelon la documentation, `Math.round` et `toFixed` arrondissent "
  },
  {
    "path": "1-js/05-data-types/02-number/3-repeat-until-number/_js.view/solution.js",
    "chars": 188,
    "preview": "\nfunction readNumber() {\n  let num;\n\n  do {\n    num = prompt(\"Enter a number please?\", 0);\n  } while ( !isFinite(num) );"
  },
  {
    "path": "1-js/05-data-types/02-number/3-repeat-until-number/_js.view/test.js",
    "chars": 852,
    "preview": "beforeEach(function() {\n  sinon.stub(window, \"prompt\");\n});\n\nafterEach(function() {\n  prompt.restore();\n});\n\ndescribe(\"r"
  },
  {
    "path": "1-js/05-data-types/02-number/3-repeat-until-number/solution.md",
    "chars": 714,
    "preview": "```js run demo\nfunction readNumber() {\n  let num;\n\n  do {\n    num = prompt(\"Entrez un nombre s'il vous plaît\", 0);\n  } w"
  },
  {
    "path": "1-js/05-data-types/02-number/3-repeat-until-number/task.md",
    "chars": 429,
    "preview": "importance: 5\n\n---\n\n# Répéter jusqu'à ce que l'entrée soit un nombre\n\nCréez une fonction `readNumber` qui invite à entre"
  },
  {
    "path": "1-js/05-data-types/02-number/4-endless-loop-error/solution.md",
    "chars": 453,
    "preview": "C'est parce que `i` ne sera jamais exactement égal à 10.\n\nExécutez-le pour voir les valeurs *réelles* de i :\n\n```js run\n"
  }
]

// ... and 971 more files (download for full content)

About this extraction

This page contains the full source code of the javascript-tutorial/fr.javascript.info GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1171 files (3.9 MB), approximately 1.1M tokens, and a symbol index with 176 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!