diff --git a/1-js/02-first-steps/11-logical-ops/1-alert-null-2-undefined/solution.md b/1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/1-alert-null-2-undefined/solution.md rename to 1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/1-alert-null-2-undefined/task.md b/1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/1-alert-null-2-undefined/task.md rename to 1-js/02-first-steps/11-logical-operators/1-alert-null-2-undefined/task.md diff --git a/1-js/02-first-steps/11-logical-ops/2-alert-or/solution.md b/1-js/02-first-steps/11-logical-operators/2-alert-or/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/2-alert-or/solution.md rename to 1-js/02-first-steps/11-logical-operators/2-alert-or/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/2-alert-or/task.md b/1-js/02-first-steps/11-logical-operators/2-alert-or/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/2-alert-or/task.md rename to 1-js/02-first-steps/11-logical-operators/2-alert-or/task.md diff --git a/1-js/02-first-steps/11-logical-ops/3-alert-1-null-2/solution.md b/1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/3-alert-1-null-2/solution.md rename to 1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/3-alert-1-null-2/task.md b/1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/3-alert-1-null-2/task.md rename to 1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/task.md diff --git a/1-js/02-first-steps/11-logical-ops/4-alert-and/solution.md b/1-js/02-first-steps/11-logical-operators/4-alert-and/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/4-alert-and/solution.md rename to 1-js/02-first-steps/11-logical-operators/4-alert-and/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/4-alert-and/task.md b/1-js/02-first-steps/11-logical-operators/4-alert-and/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/4-alert-and/task.md rename to 1-js/02-first-steps/11-logical-operators/4-alert-and/task.md diff --git a/1-js/02-first-steps/11-logical-ops/5-alert-and-or/solution.md b/1-js/02-first-steps/11-logical-operators/5-alert-and-or/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/5-alert-and-or/solution.md rename to 1-js/02-first-steps/11-logical-operators/5-alert-and-or/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/5-alert-and-or/task.md b/1-js/02-first-steps/11-logical-operators/5-alert-and-or/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/5-alert-and-or/task.md rename to 1-js/02-first-steps/11-logical-operators/5-alert-and-or/task.md diff --git a/1-js/02-first-steps/11-logical-ops/6-check-if-in-range/solution.md b/1-js/02-first-steps/11-logical-operators/6-check-if-in-range/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/6-check-if-in-range/solution.md rename to 1-js/02-first-steps/11-logical-operators/6-check-if-in-range/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/6-check-if-in-range/task.md b/1-js/02-first-steps/11-logical-operators/6-check-if-in-range/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/6-check-if-in-range/task.md rename to 1-js/02-first-steps/11-logical-operators/6-check-if-in-range/task.md diff --git a/1-js/02-first-steps/11-logical-ops/7-check-if-out-range/solution.md b/1-js/02-first-steps/11-logical-operators/7-check-if-out-range/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/7-check-if-out-range/solution.md rename to 1-js/02-first-steps/11-logical-operators/7-check-if-out-range/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/7-check-if-out-range/task.md b/1-js/02-first-steps/11-logical-operators/7-check-if-out-range/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/7-check-if-out-range/task.md rename to 1-js/02-first-steps/11-logical-operators/7-check-if-out-range/task.md diff --git a/1-js/02-first-steps/11-logical-ops/8-if-question/solution.md b/1-js/02-first-steps/11-logical-operators/8-if-question/solution.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/8-if-question/solution.md rename to 1-js/02-first-steps/11-logical-operators/8-if-question/solution.md diff --git a/1-js/02-first-steps/11-logical-ops/8-if-question/task.md b/1-js/02-first-steps/11-logical-operators/8-if-question/task.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/8-if-question/task.md rename to 1-js/02-first-steps/11-logical-operators/8-if-question/task.md diff --git a/1-js/02-first-steps/11-logical-ops/article.md b/1-js/02-first-steps/11-logical-operators/article.md similarity index 100% rename from 1-js/02-first-steps/11-logical-ops/article.md rename to 1-js/02-first-steps/11-logical-operators/article.md diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index f9e9a106..4f803b13 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -212,7 +212,7 @@ If you are writing several "helper" functions and the code to use them, then the } // *!*the code which uses them*/!* - var elem = createElement(); + let elem = createElement(); setHandler(elem); walkAround(); ``` @@ -220,7 +220,7 @@ If you are writing several "helper" functions and the code to use them, then the ```js // *!*the code which uses the functions*/!* - var elem = createElement(); + let elem = createElement(); setHandler(elem); walkAround(); diff --git a/1-js/03-code-quality/05-testing/3-pow-test-wrong/solution.md b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md similarity index 100% rename from 1-js/03-code-quality/05-testing/3-pow-test-wrong/solution.md rename to 1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md diff --git a/1-js/03-code-quality/05-testing/3-pow-test-wrong/task.md b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md similarity index 100% rename from 1-js/03-code-quality/05-testing/3-pow-test-wrong/task.md rename to 1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md diff --git a/1-js/03-code-quality/05-testing/article.md b/1-js/03-code-quality/05-testing-mocha/article.md similarity index 100% rename from 1-js/03-code-quality/05-testing/article.md rename to 1-js/03-code-quality/05-testing-mocha/article.md diff --git a/1-js/03-code-quality/05-testing/beforeafter.view/index.html b/1-js/03-code-quality/05-testing-mocha/beforeafter.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/beforeafter.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/beforeafter.view/index.html diff --git a/1-js/03-code-quality/05-testing/beforeafter.view/test.js b/1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/beforeafter.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js diff --git a/1-js/03-code-quality/05-testing/index.html b/1-js/03-code-quality/05-testing-mocha/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/index.html rename to 1-js/03-code-quality/05-testing-mocha/index.html diff --git a/1-js/03-code-quality/05-testing/pow-1.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-1.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-1.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-1.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-1.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-1.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js diff --git a/1-js/03-code-quality/05-testing/pow-2.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-2.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-2.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-2.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-2.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-2.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js diff --git a/1-js/03-code-quality/05-testing/pow-3.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-3.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-3.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-3.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-3.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-3.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js diff --git a/1-js/03-code-quality/05-testing/pow-4.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-4.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-4.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-4.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-4.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-4.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js diff --git a/1-js/03-code-quality/05-testing/pow-full.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-full.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-full.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-full.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-full.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-full.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js diff --git a/1-js/03-code-quality/05-testing/pow-min.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-min.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-min.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-min.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-min.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-min.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js diff --git a/1-js/03-code-quality/05-testing/pow-nan.view/index.html b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/index.html similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-nan.view/index.html rename to 1-js/03-code-quality/05-testing-mocha/pow-nan.view/index.html diff --git a/1-js/03-code-quality/05-testing/pow-nan.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js similarity index 100% rename from 1-js/03-code-quality/05-testing/pow-nan.view/test.js rename to 1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js diff --git a/1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/test.js b/1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/test.js index 7a538ff8..064e5414 100644 --- a/1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/test.js +++ b/1-js/04-object-basics/01-object/8-multiply-numeric/_js.view/test.js @@ -1,6 +1,6 @@ describe("multiplyNumeric", function() { it("multiplies all numeric properties by 2", function() { - var menu = { + let menu = { width: 200, height: 300, title: "My menu" @@ -14,5 +14,5 @@ describe("multiplyNumeric", function() { it("returns nothing", function() { assert.isUndefined( multiplyNumeric({}) ); }); - -}); \ No newline at end of file + +}); diff --git a/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md b/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md index aacb6258..8380a646 100644 --- a/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md +++ b/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md @@ -10,8 +10,8 @@ Is it possible to create functions `A` and `B` such as `new A()==new B()`? function A() { ... } function B() { ... } -var a = new A; -var b = new B; +let a = new A; +let b = new B; alert( a == b ); // true ``` diff --git a/1-js/04-object-basics/06-constructor-new/article.md b/1-js/04-object-basics/06-constructor-new/article.md index ca701f2c..77843b49 100644 --- a/1-js/04-object-basics/06-constructor-new/article.md +++ b/1-js/04-object-basics/06-constructor-new/article.md @@ -1,4 +1,4 @@ -# Using "new" to create objects +# Constructor, operator "new" The regular `{...}` syntax allows to create one object. But often we need to create many similar objects. @@ -62,7 +62,7 @@ let user = { }; ``` -Now if we want to create other users, we can call `new User("Ann")`, `new User("Alice")` and so on. Much shorter than using literals every time, and also reads well. +Now if we want to create other users, we can call `new User("Ann")`, `new User("Alice")` and so on. Much shorter than using literals every time, and also reads well. That's the main purpose of constructors -- to implement reusable object creation code. @@ -85,7 +85,7 @@ let user = new function() { The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code for a single complex object only. ```` -## Dual-use constructors: new.target +## Dual-use constructors: new.target Inside a function, we can check how it is called with `new` or without it, using a special `new.target` property. @@ -131,7 +131,7 @@ In other words, `return` with an object returns that object, otherwise `this` is For instance, here `return` overrides `this` by returning an object: -```js run +```js run function BigUser() { this.name = "John"; @@ -144,7 +144,7 @@ alert( new BigUser().name ); // Godzilla, got that object And here's an example with an empty `return` (or we could place a primitive after it, doesn't matter): -```js run +```js run function SmallUser() { this.name = "John"; @@ -195,7 +195,7 @@ let john = new User("John"); john.sayHi(); // My name is: John */!* -/* +/* john = { name: "John", sayHi: function() { ... } @@ -208,9 +208,6 @@ john = { - Constructor functions or, shortly, constructors, are regular functions, but there's a common agreement to name them with capital letter first. - Constructor functions should only be called using `new`. Such call implies a creation of empty `this` at the start and returning the populated one at the end. -We can use constructor functions to make multiple similar objects. But the topic is much deeper than described here. So we'll return it later and cover more in-depth. +We can use constructor functions to make multiple similar objects. But the topic is much deeper than described here. So we'll return it later and cover more in-depth. As of now, it's important to understand what `new` is, because JavaScript provides constructor functions for many built-in language objects: like `Date` for dates, `Set` for sets and others that we plan to study. - - - diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md index 145dd8a2..e0b70a6a 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -22,7 +22,7 @@ How to delete an element from the array? The arrays are objects, so we can try to use `delete`: ```js run -var arr = ["I", "go", "home"]; +let arr = ["I", "go", "home"]; delete arr[1]; // remove "go" diff --git a/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md b/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md index 23e2635d..f95b41aa 100644 --- a/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md +++ b/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md @@ -20,7 +20,7 @@ function aclean(arr) { *!* let sorted = word.toLowerCase().split('').sort().join(''); // (*) */!* - map.set(sorted, word); + map.set(sorted, word); } return Array.from(map.values()); @@ -36,7 +36,7 @@ Letter-sorting is done by the chain of calls in the line `(*)`. For convenience let's split it into multiple lines: ```js -var sorted = arr[i] // PAN +let sorted = arr[i] // PAN .toLowerCase() // pan .split('') // ['p','a','n'] .sort() // ['a','n','p'] @@ -61,10 +61,10 @@ That's how the solution can look: ```js run function aclean(arr) { - var obj = {}; + let obj = {}; - for (var i = 0; i < arr.length; i++) { - var sorted = arr[i].toLowerCase().split("").sort().join(""); + for (let i = 0; i < arr.length; i++) { + let sorted = arr[i].toLowerCase().split("").sort().join(""); obj[sorted] = arr[i]; } @@ -75,7 +75,3 @@ let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"]; alert( aclean(arr) ); ``` - - - - diff --git a/1-js/05-data-types/10-date/2-get-week-day/_js.view/solution.js b/1-js/05-data-types/10-date/2-get-week-day/_js.view/solution.js index c7a18f09..642c376a 100644 --- a/1-js/05-data-types/10-date/2-get-week-day/_js.view/solution.js +++ b/1-js/05-data-types/10-date/2-get-week-day/_js.view/solution.js @@ -1,5 +1,5 @@ function getWeekDay(date) { - var days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; + let days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; return days[date.getDay()]; } diff --git a/1-js/05-data-types/10-date/3-weekday/_js.view/solution.js b/1-js/05-data-types/10-date/3-weekday/_js.view/solution.js index 6e496393..fb9e3d2a 100644 --- a/1-js/05-data-types/10-date/3-weekday/_js.view/solution.js +++ b/1-js/05-data-types/10-date/3-weekday/_js.view/solution.js @@ -1,6 +1,6 @@ function getLocalDay(date) { - var day = date.getDay(); + let day = date.getDay(); if (day == 0) { // weekday 0 (sunday) is 7 in european day = 7; diff --git a/1-js/05-data-types/10-date/3-weekday/solution.md b/1-js/05-data-types/10-date/3-weekday/solution.md index 7aca9327..bfe3f4ca 100644 --- a/1-js/05-data-types/10-date/3-weekday/solution.md +++ b/1-js/05-data-types/10-date/3-weekday/solution.md @@ -1,7 +1,7 @@ ```js run function getLocalDay(date) { - var day = date.getDay(); + let day = date.getDay(); if (day == 0) { // 0 becomes 7 day = 7; diff --git a/1-js/05-data-types/10-date/4-get-date-ago/_js.view/test.js b/1-js/05-data-types/10-date/4-get-date-ago/_js.view/test.js index 8c8a2af2..255acffe 100644 --- a/1-js/05-data-types/10-date/4-get-date-ago/_js.view/test.js +++ b/1-js/05-data-types/10-date/4-get-date-ago/_js.view/test.js @@ -18,8 +18,8 @@ describe("getDateAgo", function() { }); it("does not modify the given date", function() { - var date = new Date(2015, 0, 2); - var dateCopy = new Date(date); + let date = new Date(2015, 0, 2); + let dateCopy = new Date(date); getDateAgo(dateCopy, 100); assert.equal(date.getTime(), dateCopy.getTime()); }); diff --git a/1-js/05-data-types/10-date/8-format-date-relative/_js.view/solution.js b/1-js/05-data-types/10-date/8-format-date-relative/_js.view/solution.js index 80b1ef49..4695354a 100644 --- a/1-js/05-data-types/10-date/8-format-date-relative/_js.view/solution.js +++ b/1-js/05-data-types/10-date/8-format-date-relative/_js.view/solution.js @@ -12,7 +12,7 @@ function formatDate(date) { return sec + ' sec. ago'; } - var min = Math.floor(diff / 60000); // convert diff to minutes + let min = Math.floor(diff / 60000); // convert diff to minutes if (min < 60) { return min + ' min. ago'; } diff --git a/1-js/05-data-types/10-date/8-format-date-relative/solution.md b/1-js/05-data-types/10-date/8-format-date-relative/solution.md index 4505a002..87864be7 100644 --- a/1-js/05-data-types/10-date/8-format-date-relative/solution.md +++ b/1-js/05-data-types/10-date/8-format-date-relative/solution.md @@ -14,7 +14,7 @@ function formatDate(date) { return sec + ' sec. ago'; } - var min = Math.floor(diff / 60000); // convert diff to minutes + let min = Math.floor(diff / 60000); // convert diff to minutes if (min < 60) { return min + ' min. ago'; } diff --git a/1-js/06-more-functions/01-recursion/01-sum-to/solution.md b/1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/01-sum-to/solution.md rename to 1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md diff --git a/1-js/06-more-functions/01-recursion/01-sum-to/task.md b/1-js/06-advanced-functions/01-recursion/01-sum-to/task.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/01-sum-to/task.md rename to 1-js/06-advanced-functions/01-recursion/01-sum-to/task.md diff --git a/1-js/06-more-functions/01-recursion/02-factorial/solution.md b/1-js/06-advanced-functions/01-recursion/02-factorial/solution.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/02-factorial/solution.md rename to 1-js/06-advanced-functions/01-recursion/02-factorial/solution.md diff --git a/1-js/06-more-functions/01-recursion/02-factorial/task.md b/1-js/06-advanced-functions/01-recursion/02-factorial/task.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/02-factorial/task.md rename to 1-js/06-advanced-functions/01-recursion/02-factorial/task.md diff --git a/1-js/06-more-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png rename to 1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png diff --git a/1-js/06-more-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png rename to 1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png diff --git a/1-js/06-more-functions/01-recursion/03-fibonacci-numbers/solution.md b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/solution.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/03-fibonacci-numbers/solution.md rename to 1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/solution.md diff --git a/1-js/06-more-functions/01-recursion/03-fibonacci-numbers/task.md b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/task.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/03-fibonacci-numbers/task.md rename to 1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/task.md diff --git a/1-js/06-more-functions/01-recursion/04-output-single-linked-list/solution.md b/1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/solution.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/04-output-single-linked-list/solution.md rename to 1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/solution.md diff --git a/1-js/06-more-functions/01-recursion/04-output-single-linked-list/task.md b/1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/task.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/04-output-single-linked-list/task.md rename to 1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/task.md diff --git a/1-js/06-more-functions/01-recursion/05-output-single-linked-list-reverse/solution.md b/1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/05-output-single-linked-list-reverse/solution.md rename to 1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md diff --git a/1-js/06-more-functions/01-recursion/05-output-single-linked-list-reverse/task.md b/1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/task.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/05-output-single-linked-list-reverse/task.md rename to 1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/task.md diff --git a/1-js/06-more-functions/01-recursion/article.md b/1-js/06-advanced-functions/01-recursion/article.md similarity index 100% rename from 1-js/06-more-functions/01-recursion/article.md rename to 1-js/06-advanced-functions/01-recursion/article.md diff --git a/1-js/06-more-functions/01-recursion/head.html b/1-js/06-advanced-functions/01-recursion/head.html similarity index 100% rename from 1-js/06-more-functions/01-recursion/head.html rename to 1-js/06-advanced-functions/01-recursion/head.html diff --git a/1-js/06-more-functions/01-recursion/linked-list-0.png b/1-js/06-advanced-functions/01-recursion/linked-list-0.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list-0.png rename to 1-js/06-advanced-functions/01-recursion/linked-list-0.png diff --git a/1-js/06-more-functions/01-recursion/linked-list-0@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list-0@2x.png rename to 1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png diff --git a/1-js/06-more-functions/01-recursion/linked-list-remove-1.png b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list-remove-1.png rename to 1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png diff --git a/1-js/06-more-functions/01-recursion/linked-list-remove-1@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list-remove-1@2x.png rename to 1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png diff --git a/1-js/06-more-functions/01-recursion/linked-list-split.png b/1-js/06-advanced-functions/01-recursion/linked-list-split.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list-split.png rename to 1-js/06-advanced-functions/01-recursion/linked-list-split.png diff --git a/1-js/06-more-functions/01-recursion/linked-list-split@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list-split@2x.png rename to 1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png diff --git a/1-js/06-more-functions/01-recursion/linked-list.png b/1-js/06-advanced-functions/01-recursion/linked-list.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list.png rename to 1-js/06-advanced-functions/01-recursion/linked-list.png diff --git a/1-js/06-more-functions/01-recursion/linked-list@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/linked-list@2x.png rename to 1-js/06-advanced-functions/01-recursion/linked-list@2x.png diff --git a/1-js/06-more-functions/01-recursion/recursion-pow.png b/1-js/06-advanced-functions/01-recursion/recursion-pow.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/recursion-pow.png rename to 1-js/06-advanced-functions/01-recursion/recursion-pow.png diff --git a/1-js/06-more-functions/01-recursion/recursion-pow@2x.png b/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/recursion-pow@2x.png rename to 1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png diff --git a/1-js/06-more-functions/01-recursion/recursive-salaries.png b/1-js/06-advanced-functions/01-recursion/recursive-salaries.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/recursive-salaries.png rename to 1-js/06-advanced-functions/01-recursion/recursive-salaries.png diff --git a/1-js/06-more-functions/01-recursion/recursive-salaries@2x.png b/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png similarity index 100% rename from 1-js/06-more-functions/01-recursion/recursive-salaries@2x.png rename to 1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png diff --git a/1-js/06-more-functions/02-rest-parameters-spread-operator/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md similarity index 100% rename from 1-js/06-more-functions/02-rest-parameters-spread-operator/article.md rename to 1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md diff --git a/1-js/06-more-functions/03-closure/1-counter-independent/solution.md b/1-js/06-advanced-functions/03-closure/1-counter-independent/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/1-counter-independent/solution.md rename to 1-js/06-advanced-functions/03-closure/1-counter-independent/solution.md diff --git a/1-js/06-more-functions/03-closure/1-counter-independent/task.md b/1-js/06-advanced-functions/03-closure/1-counter-independent/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/1-counter-independent/task.md rename to 1-js/06-advanced-functions/03-closure/1-counter-independent/task.md diff --git a/1-js/06-more-functions/03-closure/2-counter-object-independent/solution.md b/1-js/06-advanced-functions/03-closure/2-counter-object-independent/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/2-counter-object-independent/solution.md rename to 1-js/06-advanced-functions/03-closure/2-counter-object-independent/solution.md diff --git a/1-js/06-more-functions/03-closure/2-counter-object-independent/task.md b/1-js/06-advanced-functions/03-closure/2-counter-object-independent/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/2-counter-object-independent/task.md rename to 1-js/06-advanced-functions/03-closure/2-counter-object-independent/task.md diff --git a/1-js/06-more-functions/03-closure/3-function-in-if/solution.md b/1-js/06-advanced-functions/03-closure/3-function-in-if/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/3-function-in-if/solution.md rename to 1-js/06-advanced-functions/03-closure/3-function-in-if/solution.md diff --git a/1-js/06-more-functions/03-closure/3-function-in-if/task.md b/1-js/06-advanced-functions/03-closure/3-function-in-if/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/3-function-in-if/task.md rename to 1-js/06-advanced-functions/03-closure/3-function-in-if/task.md diff --git a/1-js/06-more-functions/03-closure/4-closure-sum/solution.md b/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/4-closure-sum/solution.md rename to 1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md diff --git a/1-js/06-more-functions/03-closure/4-closure-sum/task.md b/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/4-closure-sum/task.md rename to 1-js/06-advanced-functions/03-closure/4-closure-sum/task.md diff --git a/1-js/06-more-functions/03-closure/6-filter-through-function/_js.view/solution.js b/1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/03-closure/6-filter-through-function/_js.view/solution.js rename to 1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/solution.js diff --git a/1-js/06-more-functions/03-closure/6-filter-through-function/_js.view/source.js b/1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/source.js similarity index 100% rename from 1-js/06-more-functions/03-closure/6-filter-through-function/_js.view/source.js rename to 1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/source.js diff --git a/1-js/06-more-functions/03-closure/6-filter-through-function/_js.view/test.js b/1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/03-closure/6-filter-through-function/_js.view/test.js rename to 1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/test.js diff --git a/1-js/06-more-functions/03-closure/6-filter-through-function/solution.md b/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/6-filter-through-function/solution.md rename to 1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md diff --git a/1-js/06-more-functions/03-closure/6-filter-through-function/task.md b/1-js/06-advanced-functions/03-closure/6-filter-through-function/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/6-filter-through-function/task.md rename to 1-js/06-advanced-functions/03-closure/6-filter-through-function/task.md diff --git a/1-js/06-more-functions/03-closure/7-sort-by-field/solution.md b/1-js/06-advanced-functions/03-closure/7-sort-by-field/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/7-sort-by-field/solution.md rename to 1-js/06-advanced-functions/03-closure/7-sort-by-field/solution.md diff --git a/1-js/06-more-functions/03-closure/7-sort-by-field/task.md b/1-js/06-advanced-functions/03-closure/7-sort-by-field/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/7-sort-by-field/task.md rename to 1-js/06-advanced-functions/03-closure/7-sort-by-field/task.md diff --git a/1-js/06-more-functions/03-closure/8-make-army/_js.view/solution.js b/1-js/06-advanced-functions/03-closure/8-make-army/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/_js.view/solution.js rename to 1-js/06-advanced-functions/03-closure/8-make-army/_js.view/solution.js diff --git a/1-js/06-more-functions/03-closure/8-make-army/_js.view/source.js b/1-js/06-advanced-functions/03-closure/8-make-army/_js.view/source.js similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/_js.view/source.js rename to 1-js/06-advanced-functions/03-closure/8-make-army/_js.view/source.js diff --git a/1-js/06-more-functions/03-closure/8-make-army/_js.view/test.js b/1-js/06-advanced-functions/03-closure/8-make-army/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/_js.view/test.js rename to 1-js/06-advanced-functions/03-closure/8-make-army/_js.view/test.js diff --git a/1-js/06-more-functions/03-closure/8-make-army/lexenv-makearmy.png b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/lexenv-makearmy.png rename to 1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png diff --git a/1-js/06-more-functions/03-closure/8-make-army/lexenv-makearmy@2x.png b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/lexenv-makearmy@2x.png rename to 1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png diff --git a/1-js/06-more-functions/03-closure/8-make-army/solution.md b/1-js/06-advanced-functions/03-closure/8-make-army/solution.md similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/solution.md rename to 1-js/06-advanced-functions/03-closure/8-make-army/solution.md diff --git a/1-js/06-more-functions/03-closure/8-make-army/task.md b/1-js/06-advanced-functions/03-closure/8-make-army/task.md similarity index 100% rename from 1-js/06-more-functions/03-closure/8-make-army/task.md rename to 1-js/06-advanced-functions/03-closure/8-make-army/task.md diff --git a/1-js/06-more-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md similarity index 98% rename from 1-js/06-more-functions/03-closure/article.md rename to 1-js/06-advanced-functions/03-closure/article.md index ed95f948..788849e9 100644 --- a/1-js/06-more-functions/03-closure/article.md +++ b/1-js/06-advanced-functions/03-closure/article.md @@ -524,7 +524,7 @@ Lexical Environment objects that we've been talking about are subjects to same m ```js function f() { - var value = Math.random(); + let value = Math.random(); return function() {}; } @@ -538,7 +538,7 @@ Lexical Environment objects that we've been talking about are subjects to same m ```js function f() { - var value = 123; + let value = 123; function g() {} @@ -565,7 +565,7 @@ When it pauses, in console type `alert(value)`. ```js run function f() { - var value = Math.random(); + let value = Math.random(); function g() { debugger; // in console: type alert( value ); No such variable! @@ -574,7 +574,7 @@ function f() { return g; } -var g = f(); +let g = f(); g(); ``` @@ -623,7 +623,7 @@ From the first sight, `var` behaves similar to `let`. That is, declares a variab ```js run function sayHi() { - var phrase = "Hello"; // local variable, "var" instead of "let" + let phrase = "Hello"; // local variable, "var" instead of "let" alert(phrase); // Hello } @@ -640,7 +640,7 @@ alert(phrase); // Error, phrase is not defined ```js if (true) { - var test = true; // use "var" instead of "let" + let test = true; // use "var" instead of "let" } *!* @@ -653,7 +653,7 @@ alert(phrase); // Error, phrase is not defined The same thing for loops: `var` can not be block or loop-local: ```js - for(var i = 0; i < 10; i++) { + for(let i = 0; i < 10; i++) { // ... } @@ -667,7 +667,7 @@ alert(phrase); // Error, phrase is not defined ```js function sayHi() { if (true) { - var phrase = "Hello"; + let phrase = "Hello"; } alert(phrase); // works @@ -691,7 +691,7 @@ alert(phrase); // Error, phrase is not defined alert(phrase); *!* - var phrase; + let phrase; */!* } ``` @@ -701,7 +701,7 @@ alert(phrase); // Error, phrase is not defined ```js function sayHi() { *!* - var phrase; + let phrase; */!* phrase = "Hello"; @@ -717,7 +717,7 @@ alert(phrase); // Error, phrase is not defined *!* if (false) { - var phrase; + let phrase; } */!* @@ -738,21 +738,21 @@ alert(phrase); // Error, phrase is not defined alert(phrase); *!* - var phrase = "Hello"; + let phrase = "Hello"; */!* } sayHi(); ``` - The line `var phrase = "Hello"` has two actions in it: variable declaration `var` and assignment `=`. + The line `let phrase = "Hello"` has two actions in it: variable declaration `var` and assignment `=`. The declaration is processed at the start of function execution (hoisted), but the assignment is not. So the code works essentially like this: ```js run function sayHi() { *!* - var phrase; // variable is declared from the top... + let phrase; // variable is declared from the top... */!* alert(phrase); // undefined diff --git a/1-js/06-more-functions/03-closure/lexenv-if.png b/1-js/06-advanced-functions/03-closure/lexenv-if.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-if.png rename to 1-js/06-advanced-functions/03-closure/lexenv-if.png diff --git a/1-js/06-more-functions/03-closure/lexenv-if@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-if@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-if@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-if@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-1.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-1.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-1.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-1.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-1@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-1@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-1@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-1@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-2.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-2.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-2.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-2.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-2@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-2@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-2@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-2@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-3.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-3.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-3.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-3.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-3@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-3@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-3@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-3@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-4.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-4.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-4.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-4.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-4@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-4@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-4@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-4@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-5.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-5.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-5.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-5.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-5@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-5@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-5@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-5@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-6.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-6.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-6.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-6.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-makecounter-6@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-6@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-makecounter-6@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-makecounter-6@2x.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-work.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-work.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-work.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-work.png diff --git a/1-js/06-more-functions/03-closure/lexenv-nested-work@2x.png b/1-js/06-advanced-functions/03-closure/lexenv-nested-work@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexenv-nested-work@2x.png rename to 1-js/06-advanced-functions/03-closure/lexenv-nested-work@2x.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-global-2.png b/1-js/06-advanced-functions/03-closure/lexical-environment-global-2.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-global-2.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-global-2.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-global-2@2x.png b/1-js/06-advanced-functions/03-closure/lexical-environment-global-2@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-global-2@2x.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-global-2@2x.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-global-3.png b/1-js/06-advanced-functions/03-closure/lexical-environment-global-3.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-global-3.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-global-3.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-global-3@2x.png b/1-js/06-advanced-functions/03-closure/lexical-environment-global-3@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-global-3@2x.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-global-3@2x.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-global.png b/1-js/06-advanced-functions/03-closure/lexical-environment-global.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-global.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-global.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-global@2x.png b/1-js/06-advanced-functions/03-closure/lexical-environment-global@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-global@2x.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-global@2x.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-simple-lookup.png b/1-js/06-advanced-functions/03-closure/lexical-environment-simple-lookup.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-simple-lookup.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-simple-lookup.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-simple-lookup@2x.png b/1-js/06-advanced-functions/03-closure/lexical-environment-simple-lookup@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-simple-lookup@2x.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-simple-lookup@2x.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-simple.png b/1-js/06-advanced-functions/03-closure/lexical-environment-simple.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-simple.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-simple.png diff --git a/1-js/06-more-functions/03-closure/lexical-environment-simple@2x.png b/1-js/06-advanced-functions/03-closure/lexical-environment-simple@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-environment-simple@2x.png rename to 1-js/06-advanced-functions/03-closure/lexical-environment-simple@2x.png diff --git a/1-js/06-more-functions/03-closure/lexical-search-order.png b/1-js/06-advanced-functions/03-closure/lexical-search-order.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-search-order.png rename to 1-js/06-advanced-functions/03-closure/lexical-search-order.png diff --git a/1-js/06-more-functions/03-closure/lexical-search-order@2x.png b/1-js/06-advanced-functions/03-closure/lexical-search-order@2x.png similarity index 100% rename from 1-js/06-more-functions/03-closure/lexical-search-order@2x.png rename to 1-js/06-advanced-functions/03-closure/lexical-search-order@2x.png diff --git a/1-js/06-more-functions/04-global-object/article.md b/1-js/06-advanced-functions/04-global-object/article.md similarity index 98% rename from 1-js/06-more-functions/04-global-object/article.md rename to 1-js/06-advanced-functions/04-global-object/article.md index 9388960b..09f293fd 100644 --- a/1-js/06-more-functions/04-global-object/article.md +++ b/1-js/06-advanced-functions/04-global-object/article.md @@ -28,7 +28,7 @@ It does two things: ```js untrusted run no-strict refresh - var phrase = "Hello"; + let phrase = "Hello"; function sayHi() { alert(phrase); @@ -75,10 +75,10 @@ Usually, it's not a good idea to use it, but here are some examples you can meet 1. To access exactly the global variable if the function has the local one with the same name. ```js untrusted run no-strict refresh - var user = "Global"; + let user = "Global"; function sayHi() { - var user = "Local"; + let user = "Local"; *!* alert(window.user); // Global diff --git a/1-js/06-more-functions/05-function-object/2-counter-inc-dec/_js.view/solution.js b/1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/05-function-object/2-counter-inc-dec/_js.view/solution.js rename to 1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/_js.view/solution.js diff --git a/1-js/06-more-functions/05-function-object/2-counter-inc-dec/_js.view/source.js b/1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/_js.view/source.js similarity index 100% rename from 1-js/06-more-functions/05-function-object/2-counter-inc-dec/_js.view/source.js rename to 1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/_js.view/source.js diff --git a/1-js/06-more-functions/05-function-object/2-counter-inc-dec/_js.view/test.js b/1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/05-function-object/2-counter-inc-dec/_js.view/test.js rename to 1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/_js.view/test.js diff --git a/1-js/06-more-functions/05-function-object/2-counter-inc-dec/solution.md b/1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/solution.md similarity index 100% rename from 1-js/06-more-functions/05-function-object/2-counter-inc-dec/solution.md rename to 1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/solution.md diff --git a/1-js/06-more-functions/05-function-object/2-counter-inc-dec/task.md b/1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/task.md similarity index 100% rename from 1-js/06-more-functions/05-function-object/2-counter-inc-dec/task.md rename to 1-js/06-advanced-functions/05-function-object/2-counter-inc-dec/task.md diff --git a/1-js/06-more-functions/05-function-object/5-sum-many-brackets/solution.md b/1-js/06-advanced-functions/05-function-object/5-sum-many-brackets/solution.md similarity index 100% rename from 1-js/06-more-functions/05-function-object/5-sum-many-brackets/solution.md rename to 1-js/06-advanced-functions/05-function-object/5-sum-many-brackets/solution.md diff --git a/1-js/06-more-functions/05-function-object/5-sum-many-brackets/task.md b/1-js/06-advanced-functions/05-function-object/5-sum-many-brackets/task.md similarity index 100% rename from 1-js/06-more-functions/05-function-object/5-sum-many-brackets/task.md rename to 1-js/06-advanced-functions/05-function-object/5-sum-many-brackets/task.md diff --git a/1-js/06-more-functions/05-function-object/article.md b/1-js/06-advanced-functions/05-function-object/article.md similarity index 100% rename from 1-js/06-more-functions/05-function-object/article.md rename to 1-js/06-advanced-functions/05-function-object/article.md diff --git a/1-js/06-more-functions/06-new-function/article.md b/1-js/06-advanced-functions/06-new-function/article.md similarity index 100% rename from 1-js/06-more-functions/06-new-function/article.md rename to 1-js/06-advanced-functions/06-new-function/article.md diff --git a/1-js/06-more-functions/07-settimeout-setinterval/1-output-numbers-100ms/solution.md b/1-js/06-advanced-functions/07-settimeout-setinterval/1-output-numbers-100ms/solution.md similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/1-output-numbers-100ms/solution.md rename to 1-js/06-advanced-functions/07-settimeout-setinterval/1-output-numbers-100ms/solution.md diff --git a/1-js/06-more-functions/07-settimeout-setinterval/1-output-numbers-100ms/task.md b/1-js/06-advanced-functions/07-settimeout-setinterval/1-output-numbers-100ms/task.md similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/1-output-numbers-100ms/task.md rename to 1-js/06-advanced-functions/07-settimeout-setinterval/1-output-numbers-100ms/task.md diff --git a/1-js/06-more-functions/07-settimeout-setinterval/3-rewrite-settimeout/solution.md b/1-js/06-advanced-functions/07-settimeout-setinterval/3-rewrite-settimeout/solution.md similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/3-rewrite-settimeout/solution.md rename to 1-js/06-advanced-functions/07-settimeout-setinterval/3-rewrite-settimeout/solution.md diff --git a/1-js/06-more-functions/07-settimeout-setinterval/3-rewrite-settimeout/task.md b/1-js/06-advanced-functions/07-settimeout-setinterval/3-rewrite-settimeout/task.md similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/3-rewrite-settimeout/task.md rename to 1-js/06-advanced-functions/07-settimeout-setinterval/3-rewrite-settimeout/task.md diff --git a/1-js/06-more-functions/07-settimeout-setinterval/4-settimeout-result/solution.md b/1-js/06-advanced-functions/07-settimeout-setinterval/4-settimeout-result/solution.md similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/4-settimeout-result/solution.md rename to 1-js/06-advanced-functions/07-settimeout-setinterval/4-settimeout-result/solution.md diff --git a/1-js/06-more-functions/07-settimeout-setinterval/4-settimeout-result/task.md b/1-js/06-advanced-functions/07-settimeout-setinterval/4-settimeout-result/task.md similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/4-settimeout-result/task.md rename to 1-js/06-advanced-functions/07-settimeout-setinterval/4-settimeout-result/task.md diff --git a/1-js/06-advanced-functions/07-settimeout-setinterval/article.md b/1-js/06-advanced-functions/07-settimeout-setinterval/article.md new file mode 100644 index 00000000..f3de0878 --- /dev/null +++ b/1-js/06-advanced-functions/07-settimeout-setinterval/article.md @@ -0,0 +1,463 @@ +# Scheduling: setTimeout and setInterval + +We may decide to execute a function not right now, but at a certain time later. That's called "scheduling a call". + +There are two methods for it: + +- `setTimeout` allows to run a function once after the given interval of time. +- `setInterval` allows to run a function regularly with the given interval between the runs. + +These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.JS. + + +[cut] + +## setTimeout + +The syntax: + +```js +let timerId = setTimeout(func|code, delay[, arg1, arg2...]) +``` + +Parameters: + +`func|code` +: Function or a string of code to execute. +Usually, that's a function. For historical reasons, a string of code can be passed, but that's not recommended. + +`delay` +: The delay before run, in milliseconds (1000 ms = 1 second). + +`arg1`, `arg2`... +: Arguments for the function (not supported in IE9-) + +For instance, this code calls `sayHi()` after one second: + +```js run +function sayHi() { + alert('Hello'); +} + +*!* +setTimeout(sayHi, 1000); +*/!* +``` + +With arguments: + +```js run +function sayHi(phrase, who) { + alert( phrase + ', ' + who ); +} + +*!* +setTimeout(sayHi, 1000, "John", "Hello"); // Hello, John +*/!* +``` + +If the first argument is a string, then JavaScript creates a function from it. + +So, this will also work: + +```js run no-beautify +setTimeout("alert('Hello')", 1000); +``` + +But using strings is not recommended, use functions instead of them, like this: + +```js run no-beautify +setTimeout(() => alert('Hello'), 1000); +``` + +````smart header="Pass a function, but don't run it" +Novice developers sometimes make a mistake by adding brackets `()` after the function: + +```js +// wrong! +setTimeout(sayHi(), 1000); +``` +That doesn't work, because `setTimeout` expects a reference to function. And here `sayHi()` runs the function, and the *result of its execution* is passed to `setTimeout`. In our case the result of `sayHi()` is `undefined` (the function returns nothing), so nothing is scheduled. +```` + +### Canceling with clearTimeout + +A call to `setTimeout` returns a "timer identifier" `timerId` that we can use to cancel the execution. + +The syntax to cancel: + +```js +let timerId = setTimeout(...); +clearTimeout(timerId); +``` + +In the code below we schedule the function and then cancel it (changed our mind). As a result, nothing happens: + +```js run no-beautify +let timerId = setTimeout(() => alert("never happens"), 1000); +alert(timerId); // timer identifier + +clearTimeout(timerId); +alert(timerId); // same identifier (doesn't become null after canceling) +``` + +As we can see from `alert` output, in a browser the timer identifier is a number. In other environments, that can be something else. For instance, Node.JS returns a timer object with additional methods. + +Again, there is no universal specification for these methods, so that's fine. + +For browsers, timers are described in the [timers section](https://www.w3.org/TR/html5/webappapis.html#timers) of HTML5 standard. + +## setInterval + +Method `setInterval` has the same syntax as `setTimeout`: + +```js +let timerId = setInterval(func|code, delay[, arg1, arg2...]) +``` + +All arguments have the same meaning. But unlike `setTimeout` it runs the function not only once, but regularly after the given interval of time. + +To stop further calls, we should call `clearInterval(timerId)`. + +The following example will show the message every 2 seconds. After 5 seconds, the output is stopped: + +```js run +// repeat with the interval of 2 seconds +let timerId = setInterval(() => alert('tick'), 2000); + +// after 5 seconds stop +setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000); +``` + +```smart header="Modal windows freeze time in Chrome/Opera/Safari" +In browsers IE and Firefox the internal timer continues "ticking" while showing `alert/confirm/prompt`, but in Chrome, Opera and Safari the internal timer becomes "frozen". + +So if you run the code above and don't dismiss the `alert` window for some time, then in Firefox/IE next `alert` will be shown immediately as you do it (2 seconds passed from the previous invocation), and in Chrome/Opera/Safari -- after 2 more seconds (timer did not tick during the `alert`). +``` + +## Recursive setTimeout + +There are two ways of running something regularly. + +One is `setInterval`. The other one is a recursive `setTimeout`, like this: + +```js +/** instead of: +let timerId = setInterval(() => alert('tick'), 2000); +*/ + +let timerId = setTimeout(function tick() { + alert('tick'); +*!* + timerId = setTimeout(tick, 2000); // (*) +*/!* +}, 2000); +``` + +The `setTimeout` above schedules next call right at the end of the current one `(*)`. + +Recursive `setTimeout` is more flexible method than `setInterval`. This way the next call may be scheduled differently, depending on the results of the current one. + +For instance, we need to write a service that each 5 seconds sends a request to server asking for data, but in case if the server is overloaded, it should increase the interval to 10, 20, 60 seconds... + +Here's the pseudocode: +```js +let delay = 5000; + +let timerId = setTimeout(function request() { + ...send request... + + if (request failed due to server overload) { + delay *= 2; + } + + timerId = setTimeout(tick, delay); + +}, delay); +``` + + +And if we regulary have CPU-hungry tasks, then we can measure the time taken by the execition and plan the next call sooner or later. + +**Recursive `setTimeout` guarantees a delay before the executions, `setInterval` -- does not.** + +Let's compare two code fragments. The first one uses `setInterval`: + +```js +let i = 1; +setInterval(function() { + func(i); +}, 100); +``` + +The second one uses recursive `setTimeout`: + +```js +let i = 1; +setTimeout(function run() { + func(i); + setTimeout(run, 100); +}, 100); +``` + +For `setInterval` the internal scheduler will run `func(i)` every 100ms: + +![](setinterval-interval.png) + +Did you notice?... + +**The real delay between `func` calls for `setInterval` is less than in the code!** + +That's natural, because the time taken by `func` execution "consumes" a part of the interval. + +It is possible that `func` execution turns out to be longer than we expected and takes more than 100ms. + +In this case the engine waits for `func` to complete, then checks the scheduler and if the time is up, then runs it again *immediately*. + +In the edge case, if the function always executes longer than `delay` ms, then the calls will happen without pause at all. + +And here is the picture for recursive `setTimeout`: + +![](settimeout-interval.png) + +**Recursive `setTimeout` guarantees the fixed delay (here 100ms).** + +That's because a new call is planned at the end of the previous one. + +````smart header="Garbage collection" +When a function is passed in `setInterval/setTimeout`, an internal reference is created to it and saved in the scheduler. It prevents the function form being garbage collected, even if there are no other references to it. + +```js +// the function stays in memory until the scheduler calls it +setTimeout(function() {...}, 100); +``` + +For `setInterval` the function stays in memory until `cancelInterval` is called. + +There's a side-effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don't need the scheduled function any more, it's better to cancel it, even if it's very small. +```` + +## setTimeout(...,0) + +There's a special use case: `setTimeout(func, 0)`. + +This schedules the execution of `func` as soon as possible. But scheduler will invoke it only after the current code is complete. + +So the function is scheduled to run "right after" the current code. In other words, *asynchronously*. + +For instance, this outputs "Hello", then immediately "World": + +```js run +setTimeout(() => alert("World"), 0); + +alert("Hello"); +``` + +The first line "puts the call into calendar after 0ms". But the scheduler will only "check the calendar" after the current code is complete, so `"Hello"` is first, and `"World"` -- after it. + +### Splitting CPU-hungry tasks + +There's a trick to split CPU-hungry task using `setTimeout`. + +For instance, syntax highlighting script (used to colorize code examples on this page) is quite CPU-heavy. To hightlight the code, it performs the analysis, creates many colored elements, adds them to the document -- for a big text that takes a lot. It may even cause the browser to "hang", that's unacceptable. + +So we can split the long text to pieces. First 100 lines, then plan another 100 lines using `setTimeout(...,0)`, and so on. + +For clarity, let's take a simpler example for consideration. We have a function to count from `1` to `1000000000`. + +If you run it, the CPU will hang. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to click other buttons on the page -- you'll see that whole JavaScript actually is paused, no other actions work until it finishes. + +```js run +let i = 0; + +let start = Date.now(); + +function count() { + + // do a heavy job + for(let j = 0; j < 1e9; j++) { + i++; + } + + alert("Done in " + (Date.now() - start) + 'ms'); +} + +count(); +``` + +The browser may even show "the script takes too long" warning (but hopefully won't, the number is not very big). + +Let's split the job using the nested `setTimeout`: + +```js run +let i = 0; + +let start = Date.now(); + +function count() { + + // do a piece of the heavy job (*) + do { + i++; + } while (i % 1e6 != 0); + + if (i == 1e9) { + alert("Done in " + (Date.now() - start) + 'ms'); + } else { + setTimeout(count, 0); // schedule the new call (**) + } + +} + +count(); +``` + +Now the browser UI is fully functional during the "counting" process. + +We do a part of the job `(*)`: + +1. First run: `i=1...1000000`. +2. Second run: `i=1000001..2000000`. +3. ...and so on, the `while` checks if `i` is evenly divided by `100000`. + +Then the next call is scheduled in `(*)` if we're not done yet. + +Pauses between `count` executions provide just enough "breath" for the JavaScript engine to do something else, to react on other user actions. + +The notable thing is that both variants: with and without splitting the job by `setInterval` -- are comparable in speed. There's no much difference in the overall counting time. + +To make them closer let's make an improvement. + +We'll move the scheduling in the beginning of the `count()`: + +```js run +let i = 0; + +let start = Date.now(); + +function count() { + + // move the scheduling at the beginning + if (i < 1e9 - 1e6) { + setTimeout(count, 0); // schedule the new call + } + + do { + i++; + } while (i % 1e6 != 0); + + if (i == 1e9) { + alert("Done in " + (Date.now() - start) + 'ms'); + } + +} + +count(); +``` + +Now when we start to `count()` and know that we'll need to `count()` more -- we schedule that immediately, before doing the job. + +If you run it, easy to notice that it takes significantly less time. + +````smart header="Minimal delay of nested timers in-browser" +In the browser, there's a limitation of how often nested timers can run. The [HTML5 standard](https://www.w3.org/TR/html5/webappapis.html#timers) says: "after five nested timers..., the interval is forced to be at least four milliseconds.". + +Let's demonstrate what it means by the example below. The `setTimeout` call in it re-schedules itself after `0ms`. Each call remembers the real time from the previous one in the `times` array. What the real delays look like? Let's see: + +```js run +let start = Date.now(); +let times = []; + +setTimeout(function run() { + times.push(Date.now() - start); // remember delay from the previous call + + if (start + 100 < Date.now()) alert(times); // show the delays after 100ms + else setTimeout(run, 0); // else re-schedule +}, 0); + +// an example of the output: +// 1,1,1,1,9,15,20,24,30,35,40,45,50,55,59,64,70,75,80,85,90,95,100 +``` + +First timers run immediately (just as written in the spec), and then the delay comes into play and we see `9, 15, 20, 24...`. + +That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons. + +For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [process.nextTick](https://nodejs.org/api/process.html) and [setImmediate](https://nodejs.org/api/timers.html) for Node.JS. So the notion is browser-specific only. +```` + +### Allowing the browser to render + +Another benefit for in-browser scripts is that they can show a progress bar or something to the user. That's because the browser usually does all "repainting" after the script is complete. + +So if we do a single huge function then even it changes something, the changes are not reflected in the document till it finishes. + +Here's the demo: +```html run +
+ + +``` + +If you run it, the changes to `i` will show up after the whole count finishes. + +And if we use `setTimeout` to split it into pieces then changes are applied in-between the runs, so this looks better: + +```html run +
+ + +``` + +Now the `
` shows increasing values of `i`. + +## Summary + +- Methods `setInterval(func, delay, ...args)` and `setTimeout(func, delay, ...args)` allow to run the `func` regularly/once after `delay` milliseconds. +- To cancel the execution, we should call `clearInterval/clearTimeout` with the value returned by `setInterval/setTimeout`. +- Nested `setTimeout` calls is a more flexible alternative to `setInterval`. Also they can guarantee the minimal time *between* the executions. +- Zero-timeout scheduling `setTimeout(...,0)` is used to schedule the call "as soon as possible, but after the current code is complete". + +Some use cases of `setTimeout(...,0)`: +- To split CPU-hungry tasks into pieces, so that the script doesn't "hang" +- To let the browser do something else while the process is going on (paint the progress bar). + +Please note that all scheduling methods do not *guarantee* the exact delay. We should not rely on that in the scheduled code. + +For example, the in-browser timer may slow down for a lot of reasons: +- The CPU is overloaded. +- The browser tab is in the background mode. +- The laptop is on battery. + +All that may decrease the minimal timer resolution (the minimal delay) to 300ms or even 1000ms depending on the browser and settings. diff --git a/1-js/06-more-functions/07-settimeout-setinterval/setinterval-interval.png b/1-js/06-advanced-functions/07-settimeout-setinterval/setinterval-interval.png similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/setinterval-interval.png rename to 1-js/06-advanced-functions/07-settimeout-setinterval/setinterval-interval.png diff --git a/1-js/06-more-functions/07-settimeout-setinterval/setinterval-interval@2x.png b/1-js/06-advanced-functions/07-settimeout-setinterval/setinterval-interval@2x.png similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/setinterval-interval@2x.png rename to 1-js/06-advanced-functions/07-settimeout-setinterval/setinterval-interval@2x.png diff --git a/1-js/06-more-functions/07-settimeout-setinterval/settimeout-interval.png b/1-js/06-advanced-functions/07-settimeout-setinterval/settimeout-interval.png similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/settimeout-interval.png rename to 1-js/06-advanced-functions/07-settimeout-setinterval/settimeout-interval.png diff --git a/1-js/06-more-functions/07-settimeout-setinterval/settimeout-interval@2x.png b/1-js/06-advanced-functions/07-settimeout-setinterval/settimeout-interval@2x.png similarity index 100% rename from 1-js/06-more-functions/07-settimeout-setinterval/settimeout-interval@2x.png rename to 1-js/06-advanced-functions/07-settimeout-setinterval/settimeout-interval@2x.png diff --git a/1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/_js.view/solution.js b/1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/_js.view/solution.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/_js.view/solution.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/_js.view/source.js b/1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/_js.view/source.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/_js.view/source.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/_js.view/source.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/_js.view/test.js b/1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/_js.view/test.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/_js.view/test.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/solution.md b/1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/solution.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/solution.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/solution.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/task.md b/1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/task.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/01-spy-decorator/task.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/01-spy-decorator/task.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/02-delay/_js.view/solution.js b/1-js/06-advanced-functions/08-call-apply-decorators/02-delay/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/02-delay/_js.view/solution.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/02-delay/_js.view/solution.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/02-delay/_js.view/test.js b/1-js/06-advanced-functions/08-call-apply-decorators/02-delay/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/02-delay/_js.view/test.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/02-delay/_js.view/test.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/02-delay/solution.md b/1-js/06-advanced-functions/08-call-apply-decorators/02-delay/solution.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/02-delay/solution.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/02-delay/solution.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/02-delay/task.md b/1-js/06-advanced-functions/08-call-apply-decorators/02-delay/task.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/02-delay/task.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/02-delay/task.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/03-debounce/_js.view/solution.js b/1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/03-debounce/_js.view/solution.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/_js.view/solution.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/03-debounce/_js.view/test.js b/1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/03-debounce/_js.view/test.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/_js.view/test.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/03-debounce/solution.md b/1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/solution.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/03-debounce/solution.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/solution.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/03-debounce/task.md b/1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/task.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/03-debounce/task.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/03-debounce/task.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/04-throttle/_js.view/solution.js b/1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/_js.view/solution.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/04-throttle/_js.view/solution.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/_js.view/solution.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/04-throttle/_js.view/test.js b/1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/_js.view/test.js similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/04-throttle/_js.view/test.js rename to 1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/_js.view/test.js diff --git a/1-js/06-more-functions/08-call-apply-decorators/04-throttle/solution.md b/1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/solution.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/04-throttle/solution.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/solution.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/04-throttle/task.md b/1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/task.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/04-throttle/task.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/04-throttle/task.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/article.md b/1-js/06-advanced-functions/08-call-apply-decorators/article.md similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/article.md rename to 1-js/06-advanced-functions/08-call-apply-decorators/article.md diff --git a/1-js/06-more-functions/08-call-apply-decorators/decorator-makecaching-wrapper.png b/1-js/06-advanced-functions/08-call-apply-decorators/decorator-makecaching-wrapper.png similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/decorator-makecaching-wrapper.png rename to 1-js/06-advanced-functions/08-call-apply-decorators/decorator-makecaching-wrapper.png diff --git a/1-js/06-more-functions/08-call-apply-decorators/decorator-makecaching-wrapper@2x.png b/1-js/06-advanced-functions/08-call-apply-decorators/decorator-makecaching-wrapper@2x.png similarity index 100% rename from 1-js/06-more-functions/08-call-apply-decorators/decorator-makecaching-wrapper@2x.png rename to 1-js/06-advanced-functions/08-call-apply-decorators/decorator-makecaching-wrapper@2x.png diff --git a/1-js/06-more-functions/09-bind/2-write-to-object-after-bind/solution.md b/1-js/06-advanced-functions/09-bind/2-write-to-object-after-bind/solution.md similarity index 95% rename from 1-js/06-more-functions/09-bind/2-write-to-object-after-bind/solution.md rename to 1-js/06-advanced-functions/09-bind/2-write-to-object-after-bind/solution.md index 7546f670..737a1448 100644 --- a/1-js/06-more-functions/09-bind/2-write-to-object-after-bind/solution.md +++ b/1-js/06-advanced-functions/09-bind/2-write-to-object-after-bind/solution.md @@ -6,7 +6,7 @@ function f() { alert( this ); // null } -var user = { +let user = { g: f.bind(null) }; diff --git a/1-js/06-more-functions/09-bind/2-write-to-object-after-bind/task.md b/1-js/06-advanced-functions/09-bind/2-write-to-object-after-bind/task.md similarity index 92% rename from 1-js/06-more-functions/09-bind/2-write-to-object-after-bind/task.md rename to 1-js/06-advanced-functions/09-bind/2-write-to-object-after-bind/task.md index 8023bcd4..6d7e1fb2 100644 --- a/1-js/06-more-functions/09-bind/2-write-to-object-after-bind/task.md +++ b/1-js/06-advanced-functions/09-bind/2-write-to-object-after-bind/task.md @@ -11,7 +11,7 @@ function f() { alert( this ); // ? } -var user = { +let user = { g: f.bind(null) }; diff --git a/1-js/06-more-functions/09-bind/3-second-bind/solution.md b/1-js/06-advanced-functions/09-bind/3-second-bind/solution.md similarity index 100% rename from 1-js/06-more-functions/09-bind/3-second-bind/solution.md rename to 1-js/06-advanced-functions/09-bind/3-second-bind/solution.md diff --git a/1-js/06-more-functions/09-bind/3-second-bind/task.md b/1-js/06-advanced-functions/09-bind/3-second-bind/task.md similarity index 100% rename from 1-js/06-more-functions/09-bind/3-second-bind/task.md rename to 1-js/06-advanced-functions/09-bind/3-second-bind/task.md diff --git a/1-js/06-more-functions/09-bind/4-function-property-after-bind/solution.md b/1-js/06-advanced-functions/09-bind/4-function-property-after-bind/solution.md similarity index 100% rename from 1-js/06-more-functions/09-bind/4-function-property-after-bind/solution.md rename to 1-js/06-advanced-functions/09-bind/4-function-property-after-bind/solution.md diff --git a/1-js/06-more-functions/09-bind/4-function-property-after-bind/task.md b/1-js/06-advanced-functions/09-bind/4-function-property-after-bind/task.md similarity index 100% rename from 1-js/06-more-functions/09-bind/4-function-property-after-bind/task.md rename to 1-js/06-advanced-functions/09-bind/4-function-property-after-bind/task.md diff --git a/1-js/06-more-functions/09-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/09-bind/5-question-use-bind/solution.md similarity index 100% rename from 1-js/06-more-functions/09-bind/5-question-use-bind/solution.md rename to 1-js/06-advanced-functions/09-bind/5-question-use-bind/solution.md diff --git a/1-js/06-more-functions/09-bind/5-question-use-bind/task.md b/1-js/06-advanced-functions/09-bind/5-question-use-bind/task.md similarity index 100% rename from 1-js/06-more-functions/09-bind/5-question-use-bind/task.md rename to 1-js/06-advanced-functions/09-bind/5-question-use-bind/task.md diff --git a/1-js/06-more-functions/09-bind/6-ask-currying/solution.md b/1-js/06-advanced-functions/09-bind/6-ask-currying/solution.md similarity index 100% rename from 1-js/06-more-functions/09-bind/6-ask-currying/solution.md rename to 1-js/06-advanced-functions/09-bind/6-ask-currying/solution.md diff --git a/1-js/06-more-functions/09-bind/6-ask-currying/task.md b/1-js/06-advanced-functions/09-bind/6-ask-currying/task.md similarity index 100% rename from 1-js/06-more-functions/09-bind/6-ask-currying/task.md rename to 1-js/06-advanced-functions/09-bind/6-ask-currying/task.md diff --git a/1-js/06-more-functions/09-bind/article.md b/1-js/06-advanced-functions/09-bind/article.md similarity index 100% rename from 1-js/06-more-functions/09-bind/article.md rename to 1-js/06-advanced-functions/09-bind/article.md diff --git a/1-js/06-more-functions/09-bind/head.html b/1-js/06-advanced-functions/09-bind/head.html similarity index 65% rename from 1-js/06-more-functions/09-bind/head.html rename to 1-js/06-advanced-functions/09-bind/head.html index dd262f3f..afdb888d 100644 --- a/1-js/06-more-functions/09-bind/head.html +++ b/1-js/06-advanced-functions/09-bind/head.html @@ -4,16 +4,16 @@ function mul(a, b) { }; function ask(question, answer, ok, fail) { - var result = prompt(question, ''); + let result = prompt(question, ''); if (result.toLowerCase() == answer.toLowerCase()) ok(); else fail(); } function bind(func, context /*, args*/) { - var bindArgs = [].slice.call(arguments, 2); // (1) + let bindArgs = [].slice.call(arguments, 2); // (1) function wrapper() { // (2) - var args = [].slice.call(arguments); - var unshiftArgs = bindArgs.concat(args); // (3) + let args = [].slice.call(arguments); + let unshiftArgs = bindArgs.concat(args); // (3) return func.apply(context, unshiftArgs); // (4) } return wrapper; diff --git a/1-js/06-more-functions/10-arrow-functions/article.md b/1-js/06-advanced-functions/10-arrow-functions/article.md similarity index 100% rename from 1-js/06-more-functions/10-arrow-functions/article.md rename to 1-js/06-advanced-functions/10-arrow-functions/article.md diff --git a/1-js/06-advanced-functions/index.md b/1-js/06-advanced-functions/index.md new file mode 100644 index 00000000..7800dcc4 --- /dev/null +++ b/1-js/06-advanced-functions/index.md @@ -0,0 +1 @@ +# Advanced working with functions diff --git a/1-js/06-more-functions/07-settimeout-setinterval/article.md b/1-js/06-more-functions/07-settimeout-setinterval/article.md deleted file mode 100644 index 1ed279f1..00000000 --- a/1-js/06-more-functions/07-settimeout-setinterval/article.md +++ /dev/null @@ -1,368 +0,0 @@ -# Scheduling: setTimeout and setInterval - -We may decide to execute a function not right now, but at a certain time later. That's called "scheduling a call". - -There are two methods for it: - -- `setTimeout` allows to run a function once after the given interval of time. -- `setInterval` allows to run of the function regularly with the given interval between the runs. - -These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.JS. - - -[cut] - -## setTimeout - -The syntax: - -```js -let timerId = setTimeout(func / code, delay[, arg1, arg2...]) -``` - -Parameters: - -`func/code` -: Function or a string of code to execute. -Usually, that's a function. For historical reasons, a string of code can be passed, but that's not recommended. - -`delay` -: The delay before run, in milliseconds (1000 ms = 1 second). - -`arg1`, `arg2`... -: Arguments to pass the function (not supported in IE9-) - - -For instance, this code calls `sayHi()` after one second: - -```js run -function sayHi() { - alert('Hello'); -} - -*!* -setTimeout(sayHi, 1000); -*/!* -``` - -With arguments: - -```js run -function sayHi(phrase, who) { - alert( phrase + ', ' + who ); -} - -*!* -setTimeout(sayHi, 1000, "John", "Hello"); // Hello, John -*/!* -``` - -If the first argument is a string, then JavaScript creates a function from it. - -So, this will also work: - -```js run no-beautify -setTimeout("alert('Hello')", 1000); -``` - -But using strings is not recommended, use functions instead of them, like this: - -```js run no-beautify -setTimeout(() => alert('Hello'), 1000); -``` - -````smart header="Pass a function, don't run it" -Novice developers sometimes make a mistake by adding brackets `()` after the function: - -```js -// wrong! -setTimeout(sayHi(), 1000); -``` -That doesn't work, because `setTimeout` expects a reference to function. And here `sayHi()` runs the function, and the *result of its execution* is passed as the first argument. In our case the result of `sayHi()` is `undefined` (the function returns nothing), so nothing is scheduled. -```` - -### Canceling with clearTimeout - -A call to `setTimeout` returns a "timer identifier" `timerId`, that we can use to cancel the execution. - -The syntax to cancel: - -```js -let timerId = setTimeout(...); -clearTimeout(timerId); -``` - -In the code below we schedule the function, and then cancel it (changed our mind). As a result, nothing happens: - -```js run no-beautify -let timerId = setTimeout(() => alert("never happens"), 1000); -alert(timerId); // timer identifier - -clearTimeout(timerId); -alert(timerId); // same identifier (doesn't become null after canceling) -``` - -As we can see from `alert` output, in browsers timer identifier is a number. In other environments, that can be something else. For instance, Node.JS returns a timer object, with additional methods. - -Again, there is no universal specification for these methods. - -For browsers, timers are described in the [timers section](https://www.w3.org/TR/html5/webappapis.html#timers) of HTML5 standard. - -## setInterval - -Method `setInterval` has the same syntax as `setTimeout`: - -```js -let timerId = setInterval(func / code, delay[, arg1, arg2...]) -``` - -All arguments have the same meaning. But, unlike `setTimeout`, it runs the function not only once, but regularly with the given interval of time. - -To stop the execution, we should call `clearInterval(timerId)`. - -The following example will show the message every 2 seconds. After 5 seconds, the output is stopped: - -```js run -// repeat with the interval of 2 seconds -let timerId = setInterval(() => alert('tick'), 2000); - -// after 5 seconds stop -setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000); -``` - -```smart header="Modal windows freeze time in Chrome/Opera/Safari" -In browsers Chrome, Opera and Safari the internal timer is "frozen" while showing `alert/confirm/prompt`. And in IE or Firefox it continues ticking. - -So if you run the code above and hold the `alert` window for a long time, then in Firefox/IE next `alert` will be shown at once (2 seconds passed from the previous run), and in Chrome/Opera/Safari -- after 2 seconds (timer does not tick during the `alert`). -``` - -## Recursive setTimeout - -There are two ways of running something regularly. - -One is `setInterval`. The other one is a recursive `setTimeout`: - -```js -/** instead of: -let timerId = setInterval(() => alert('tick'), 2000); -*/ - -let timerId = setTimeout(function tick() { - alert('tick'); -*!* - timerId = setTimeout(tick, 2000); -*/!* -}, 2000); -``` - -The `setTimeout` above schedules next call right at the end of the previous one. - -**Recursive `setTimeout` is more flexible method than `setInterval`: the next call may be planned differently, depending on the results of the current one.** - -For instance, we have a service that each 5 seconds sends a request to server asking for data. In case if the server is overloaded, we can increase the interval to 10, 20, 60 seconds... And then return it back when everything stabilizes. - -And if we regulary have CPU-hungry tasks, then we can measure the time taken by the execition and plan the next call sooner or later. - -**Recursive `setTimeout` guarantees a delay before the executions, `setInterval` -- does not.** - -Let's compare two code fragments. The first one uses `setInterval`: - -```js -let i = 1; -setInterval(function() { - func(i); -}, 100); -``` - -The second one uses recursive `setTimeout`: - -```js -let i = 1; -setTimeout(function run() { - func(i); - setTimeout(run, 100); -}, 100); -``` - -For `setInterval` the internal scheduler will run `func(i)` every 100ms: - -![](setinterval-interval.png) - -Did you notice?... - -**The real delay between `func` calls for `setInterval` is less than in the code!** - -That's natural, because the time taken by `func` execution "consumes" a part of the interval. - -It is possible that `func` execution turns out to be longer than we expected and takes more than 100ms. - -In this case the engine waits for `func` to complete, then checks the scheduler and if the time is up, then runs it again *immediately*. - -As an edge case, if the function always takes longer to execute than `delay` argument, then the calls will happen without pause at all. - -And this is the picture for recursive `setTimeout`: - -![](settimeout-interval.png) - -**Recursive `setTimeout` guarantees fixed delay (here 100ms).** - -That's because a new call is planned at the end of the previous one. - -````smart header="Garbage collection" -When a function is passed in `setInterval/setTimeout`, an internal reference is created to it and saved in the scheduler. It prevents the function form being garbage collected, even if there are no other references to it. - -```js -// the function will stay in memory until the scheduler calls it -setTimeout(function() {}, 100); -``` - -For `setInterval` the function stays in memory until `cancelInterval` is called. - -A function references outer lexical environment, so, while it lives, certain outer variables live too. They may take much more memory than the function itself. That's a good reason to keep an eye on scheduled functions` and cancel them once they are not needed. -```` - -## Zero timeout - -There's a special use case: `setTimeout(func, 0)`. - -This plans the execution of `func` as soon as possible. But scheduler will invoke it only after the current code is complete. - -So the function is planned to run "right after" the current code. In other words, *asynchronously*. - -For instance, this outputs "Hello", then immediately "World": - -```js run -setTimeout(() => alert("World"), 0); - -alert("Hello"); -``` - -The trick is also used to split a CPU-hungry task. - -For instance, syntax highlighting script, used to colorize code examples on this page, is quite CPU-heavy. To hightlight the code, it analyzes it, creates many colored highlighting elements, adds them to the document -- for a big text that takes a lot. It may even cause the browser to "hang", that's unacceptable. - -So we can split the long text to pieces. First 100 lines, then plan another 100 lines using `setTimeout(...,0)`, and so on. - -As a simpler example -- here's a counting function from `1` to `1000000000`. - -If you run it, the CPU will hang. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to scroll and click other buttons on the page -- you'll see that whole JavaScript actually is paused, no other actions work until it finishes. - -```js run -let i = 0; - -let start = Date.now(); - -function count() { - - // do a heavy job - for(let j = 0; j < 1000000000; j++) { - i++; - } - - alert("Done in " + (Date.now() - start) + 'ms'); -} - -count(); -``` - -Let's split the job using the nested `setTimeout`: - -```js run -let i = 0; - -let start = Date.now(); - -function count() { - - if (i == 100000000) { - alert("Done in " + (Date.now() - start) + 'ms'); - } else { - setTimeout(count, 0); // schedule the new call (*) - } - - // do a piece of the heavy job (**) - for(let j = 0; j < 1000000; j++) { - i++; - } - -} - -count(); -``` - -Now the browser UI is fully functional. Pauses between `count` executions provide just enough "breath" for the browser to do something else, to react on other user actions. - -The notable thing is that both variants are comparable in speed. There's no much difference in the overall counting time. - -Note that in the example above the next call is planned before the counting itself: line `(*)` goes before the loop `(**)`. That plans making the new call as early as possible. - -If we switch them, the overall time will be much slower. - -Here's the code with `setTimeout` at the end to compare: - -```js run -let i = 0; - -let start = Date.now(); - -function count() { - - for(let j = 0; j < 1000000; j++) { - i++; - } - - // moved re-scheduling to "after the job" -*!* - if (i == 100000000) { - alert("Done in " + (Date.now() - start) + 'ms'); - } else { - setTimeout(count, 0); - } -*/!* - -} - -count(); -``` - -If you run it, easy to notice that it takes significantly more time. - -````smart header="Minimal delay of nested timers in-browser" -In the browser, there's a limitation of how often nested timers can run. The [HTML5 standard](https://www.w3.org/TR/html5/webappapis.html#timers) says: "after five nested timers..., the interval is forced to be at least four milliseconds.". - -To see that, let's timers immediately and measure times between them: - -```js run -let start = Date.now(), times = []; - -setTimeout(function run() { - times.push(Date.now() - start); - - if (start + 100 > Date.now()) setTimeout(run, 0); - else alert(times); -}, 0); - -// an example of the output: -// 1,1,1,1,9,15,20,24,30,35,40,45,50,55,59,64,70,75,80,85,90,95,100 -``` - -First timers run immediately (just as written in the spec), and then the delay comes into play. That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons. - -For server-side JavaScript, that limitation does not exist. Also, there are other ways to schedule an immediate asynchronous job. In Node.JS that's [process.nextTick](https://nodejs.org/api/process.html) and [setImmediate](https://nodejs.org/api/timers.html). -```` - -## Summary - -- Methods `setInterval(func, delay, ...args)` and `setTimeout(func, delay, ...args)` allow to run the `func` regularly/once after `delay` milliseconds. -- To cancel execution, we should `clearInterval/clearTimeout` on the value returned by `setInterval/setTimeout`. -- Nested `setTimeout` calls give more flexible control over the execution than `setInterval`. They also can guarantee the minimal time *between* the execution. -- Zero-timeout is sometimes used to schedule the call "as soon as possible". - -Please note that these methods do not *guarantee* the accurate delay. We should not rely on that in the scheduled code. - -For example, the in-browser timer may slowdown for a lot of reasons: -- The CPU is overloaded. -- The browser tab is in the background mode. -- The visitor's laptop is on battery. - -All that may decrease the minimal timer resolution (the minimal delay) to 300ms or even 1000ms depending on the browser and settings. diff --git a/1-js/06-more-functions/index.md b/1-js/06-more-functions/index.md deleted file mode 100644 index c07ac0e5..00000000 --- a/1-js/06-more-functions/index.md +++ /dev/null @@ -1 +0,0 @@ -# More about functions \ No newline at end of file diff --git a/1-js/07-object-inheritance/03-prototype/1-property-after-delete/solution.md b/1-js/07-object-inheritance/03-prototype-inheritance/1-property-after-delete/solution.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/1-property-after-delete/solution.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/1-property-after-delete/solution.md diff --git a/1-js/07-object-inheritance/03-prototype/1-property-after-delete/task.md b/1-js/07-object-inheritance/03-prototype-inheritance/1-property-after-delete/task.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/1-property-after-delete/task.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/1-property-after-delete/task.md diff --git a/1-js/07-object-inheritance/03-prototype/2-search-algorithm/solution.md b/1-js/07-object-inheritance/03-prototype-inheritance/2-search-algorithm/solution.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/2-search-algorithm/solution.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/2-search-algorithm/solution.md diff --git a/1-js/07-object-inheritance/03-prototype/2-search-algorithm/task.md b/1-js/07-object-inheritance/03-prototype-inheritance/2-search-algorithm/task.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/2-search-algorithm/task.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/2-search-algorithm/task.md diff --git a/1-js/07-object-inheritance/03-prototype/3-proto-and-this/solution.md b/1-js/07-object-inheritance/03-prototype-inheritance/3-proto-and-this/solution.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/3-proto-and-this/solution.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/3-proto-and-this/solution.md diff --git a/1-js/07-object-inheritance/03-prototype/3-proto-and-this/task.md b/1-js/07-object-inheritance/03-prototype-inheritance/3-proto-and-this/task.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/3-proto-and-this/task.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/3-proto-and-this/task.md diff --git a/1-js/07-object-inheritance/03-prototype/4-hamster-proto/solution.md b/1-js/07-object-inheritance/03-prototype-inheritance/4-hamster-proto/solution.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/4-hamster-proto/solution.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/4-hamster-proto/solution.md diff --git a/1-js/07-object-inheritance/03-prototype/4-hamster-proto/task.md b/1-js/07-object-inheritance/03-prototype-inheritance/4-hamster-proto/task.md similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/4-hamster-proto/task.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/4-hamster-proto/task.md diff --git a/1-js/07-object-inheritance/03-prototype/article.md b/1-js/07-object-inheritance/03-prototype-inheritance/article.md similarity index 99% rename from 1-js/07-object-inheritance/03-prototype/article.md rename to 1-js/07-object-inheritance/03-prototype-inheritance/article.md index ab8f8d7a..cbc86107 100644 --- a/1-js/07-object-inheritance/03-prototype/article.md +++ b/1-js/07-object-inheritance/03-prototype-inheritance/article.md @@ -1,4 +1,4 @@ -# Object prototype +# Prototypal inheritance In programming, we often want to take something and extend it. diff --git a/1-js/07-object-inheritance/03-prototype/object-prototype-empty.png b/1-js/07-object-inheritance/03-prototype-inheritance/object-prototype-empty.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/object-prototype-empty.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/object-prototype-empty.png diff --git a/1-js/07-object-inheritance/03-prototype/object-prototype-empty@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/object-prototype-empty@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/object-prototype-empty@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/object-prototype-empty@2x.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-chain.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-chain.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-chain.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-chain.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-chain@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-chain@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-chain@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-chain@2x.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-2.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-2.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-2.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-2.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-2@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-2@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-2@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-2@2x.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-3.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-3.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-3.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-3.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-3@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-3@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk-3@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk-3@2x.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit-walk@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit-walk@2x.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-animal-rabbit@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-animal-rabbit@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-animal-rabbit@2x.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-user-admin.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-user-admin.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-user-admin.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-user-admin.png diff --git a/1-js/07-object-inheritance/03-prototype/proto-user-admin@2x.png b/1-js/07-object-inheritance/03-prototype-inheritance/proto-user-admin@2x.png similarity index 100% rename from 1-js/07-object-inheritance/03-prototype/proto-user-admin@2x.png rename to 1-js/07-object-inheritance/03-prototype-inheritance/proto-user-admin@2x.png diff --git a/1-js/07-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/solution.md b/1-js/07-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/solution.md index 0bb18b44..e3651683 100644 --- a/1-js/07-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/solution.md +++ b/1-js/07-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/solution.md @@ -2,7 +2,7 @@ ```js run Function.prototype.defer = function(ms) { - var f = this; + let f = this; return function(...args) { setTimeout(() => f.apply(this, args), ms); } diff --git a/1-js/07-object-inheritance/10-class-inheritance/2-clock-class-extended/source.view/index.html b/1-js/07-object-inheritance/10-class-inheritance/2-clock-class-extended/source.view/index.html index d13962e1..b48a2a00 100644 --- a/1-js/07-object-inheritance/10-class-inheritance/2-clock-class-extended/source.view/index.html +++ b/1-js/07-object-inheritance/10-class-inheritance/2-clock-class-extended/source.view/index.html @@ -10,7 +10,7 @@ @@ -69,7 +69,7 @@ Here are no space-only text nodes:
@@ -95,7 +95,7 @@ As an example, if the HTML file is a single word `"Hello"`, the browser will wra
@@ -116,7 +116,7 @@ Such an "invalid" document:
@@ -134,7 +134,7 @@ DOM-structure will be:
@@ -165,7 +165,7 @@ Let's add more tags and a comment to the page:
diff --git a/2-ui/1-document/03-dom-navigation/article.md b/2-ui/1-document/03-dom-navigation/article.md index d33e3197..ab96e5f7 100644 --- a/2-ui/1-document/03-dom-navigation/article.md +++ b/2-ui/1-document/03-dom-navigation/article.md @@ -5,7 +5,7 @@ libs: --- -# DOM Navigation +# Walking the DOM DOM allows to do anything with elements and their contents, but first we need to reach the corresponding DOM object, get it into a variable, and then we are able to modify it. diff --git a/2-ui/1-document/04-searching-elements-dom/article.md b/2-ui/1-document/04-searching-elements-dom/article.md index 9b3dcaf4..9f9e72da 100644 --- a/2-ui/1-document/04-searching-elements-dom/article.md +++ b/2-ui/1-document/04-searching-elements-dom/article.md @@ -1,4 +1,4 @@ -# Searching with getElement*, querySelector* and other methods +# Searching: getElement* and querySelector* DOM navigation properties are great when elements are close to each other. What if they are not? How to get an arbitrary element of the page? diff --git a/2-ui/1-document/06-attributes-and-properties/1-get-user-attribute/solution.md b/2-ui/1-document/06-dom-attributes-and-properties/1-get-user-attribute/solution.md similarity index 100% rename from 2-ui/1-document/06-attributes-and-properties/1-get-user-attribute/solution.md rename to 2-ui/1-document/06-dom-attributes-and-properties/1-get-user-attribute/solution.md diff --git a/2-ui/1-document/06-attributes-and-properties/1-get-user-attribute/task.md b/2-ui/1-document/06-dom-attributes-and-properties/1-get-user-attribute/task.md similarity index 100% rename from 2-ui/1-document/06-attributes-and-properties/1-get-user-attribute/task.md rename to 2-ui/1-document/06-dom-attributes-and-properties/1-get-user-attribute/task.md diff --git a/2-ui/1-document/06-attributes-and-properties/2-yellow-links/solution.md b/2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/solution.md similarity index 100% rename from 2-ui/1-document/06-attributes-and-properties/2-yellow-links/solution.md rename to 2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/solution.md diff --git a/2-ui/1-document/06-attributes-and-properties/2-yellow-links/solution.view/index.html b/2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/solution.view/index.html similarity index 100% rename from 2-ui/1-document/06-attributes-and-properties/2-yellow-links/solution.view/index.html rename to 2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/solution.view/index.html diff --git a/2-ui/1-document/06-attributes-and-properties/2-yellow-links/source.view/index.html b/2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/source.view/index.html similarity index 100% rename from 2-ui/1-document/06-attributes-and-properties/2-yellow-links/source.view/index.html rename to 2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/source.view/index.html diff --git a/2-ui/1-document/06-attributes-and-properties/2-yellow-links/task.md b/2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/task.md similarity index 100% rename from 2-ui/1-document/06-attributes-and-properties/2-yellow-links/task.md rename to 2-ui/1-document/06-dom-attributes-and-properties/2-yellow-links/task.md diff --git a/2-ui/1-document/06-attributes-and-properties/article.md b/2-ui/1-document/06-dom-attributes-and-properties/article.md similarity index 99% rename from 2-ui/1-document/06-attributes-and-properties/article.md rename to 2-ui/1-document/06-dom-attributes-and-properties/article.md index d2185fb8..54a253e6 100644 --- a/2-ui/1-document/06-attributes-and-properties/article.md +++ b/2-ui/1-document/06-dom-attributes-and-properties/article.md @@ -1,4 +1,4 @@ -# DOM: attributes and properties +# Attributes and properties When the browser loads the page, it "reads" (another word: "parses") HTML text and generates DOM objects from it. For element nodes most standard HTML attributes automatically become properties of DOM objects. diff --git a/2-ui/1-document/07-modifying-document/article.md b/2-ui/1-document/07-modifying-document/article.md index 47afb8f8..09d943ba 100644 --- a/2-ui/1-document/07-modifying-document/article.md +++ b/2-ui/1-document/07-modifying-document/article.md @@ -1,4 +1,4 @@ -# Modifying DOM +# Modifying the document DOM modifications is the key to create "live" pages. diff --git a/2-ui/1-document/09-size-and-scroll/4-put-ball-in-center/ball-half/index.html b/2-ui/1-document/09-size-and-scroll/4-put-ball-in-center/ball-half/index.html index 23b8d7b2..ca9c4d57 100755 --- a/2-ui/1-document/09-size-and-scroll/4-put-ball-in-center/ball-half/index.html +++ b/2-ui/1-document/09-size-and-scroll/4-put-ball-in-center/ball-half/index.html @@ -26,8 +26,8 @@ ``` -The `detail` property can have any data. +The `detail` property can have any data. Technically we could live without, because we can assign any properties into a regular `new Event` object after its creation. But `CustomEvent` provides the special `detail` field for it to evade conflicts with other event properties. -Once again, technically we can assign any properties into a regular `new Event` object after its creation. But `CustomEvent` provides the special `detail` field, so that we can write to it safely, without conflicts with standard event properties. - -Also using the right class tells something about "what kind of event" it is, and `CustomEvent` is better for that matter. So we should use it for our events. +The event class tells something about "what kind of event" it is, and if the event is custom, then we should use `CustomEvent` just to be clear about what it is. ## event.preventDefault() @@ -189,7 +186,7 @@ A handler set by `rabbit.addEventListener('hide',...)` will learn about that and ``` + +## Events-in-events are synchronous + +Usually events are processed asynchronously. That is: if the browser is processing `onclick` and in the process a new event occurs, then it awaits till `onclick` processing is finished. + +The exception is when one event is initiated from within another one. + +Then the control jumps to the nested event handler, and after it goes back. + +For instance, here the nested `menu-open` event is processed synchronously, during the `onclick`: + +```html run + + + +``` + +Please note that the nested event `menu-open` bubbles up and is handled on the `document`. The propagation of the nested event is fully finished before the processing gets back to the outer code (`onclick`). + +That's not only about `dispatchEvent`, there are other cases. JavaScript in an event handler can call methods that lead to other events -- they are too processed synchronously. + +If we don't like it, we can either put the `dispatchEvent` (or other event-triggering call) at the end of `onclick` or, if inconvenient, wrap it in `setTimeout(...,0)`: + +```html run + + + +``` + ## Summary To generate an event, we first need to create an event object. The generic `Event(name, options)` constructor accepts an arbitrary event name and the `options` object with two properties: - - `bubbles:true` if the event should bubble. - - `cancelable:true` is the `event.preventDefault()` should work. + - `bubbles: true` if the event should bubble. + - `cancelable: true` is the `event.preventDefault()` should work. Other constructors of native events like `MouseEvent`, `KeyboardEvent` and so on accept properties specific to that event type. For instance, `clientX` for mouse events. diff --git a/2-ui/3-event-details/1-mouse-clicks/01-selectable-list/solution.md b/2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/solution.md similarity index 100% rename from 2-ui/3-event-details/1-mouse-clicks/01-selectable-list/solution.md rename to 2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/solution.md diff --git a/2-ui/3-event-details/1-mouse-clicks/01-selectable-list/solution.view/index.html b/2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/solution.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 2-ui/3-event-details/1-mouse-clicks/01-selectable-list/solution.view/index.html rename to 2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/solution.view/index.html diff --git a/2-ui/3-event-details/1-mouse-clicks/01-selectable-list/source.view/index.html b/2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/source.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 2-ui/3-event-details/1-mouse-clicks/01-selectable-list/source.view/index.html rename to 2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/source.view/index.html diff --git a/2-ui/3-event-details/1-mouse-clicks/01-selectable-list/task.md b/2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/task.md similarity index 100% rename from 2-ui/3-event-details/1-mouse-clicks/01-selectable-list/task.md rename to 2-ui/3-event-details/1-mouse-events-basics/01-selectable-list/task.md diff --git a/2-ui/3-event-details/1-mouse-clicks/article.md b/2-ui/3-event-details/1-mouse-events-basics/article.md similarity index 99% rename from 2-ui/3-event-details/1-mouse-clicks/article.md rename to 2-ui/3-event-details/1-mouse-events-basics/article.md index c5d80ad6..daa26c56 100644 --- a/2-ui/3-event-details/1-mouse-clicks/article.md +++ b/2-ui/3-event-details/1-mouse-events-basics/article.md @@ -1,4 +1,4 @@ -# Mouse: clicks, coordinates +# Mouse events basics In this chapter we'll get into more details of mouse events and their properties. diff --git a/2-ui/3-event-details/1-mouse-clicks/head.html b/2-ui/3-event-details/1-mouse-events-basics/head.html similarity index 100% rename from 2-ui/3-event-details/1-mouse-clicks/head.html rename to 2-ui/3-event-details/1-mouse-events-basics/head.html diff --git a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html index bc7ff3c4..c1624d03 100644 --- a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html +++ b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/solution.view/index.html @@ -38,7 +38,7 @@ // let's create another img with the same src and check that we have its width immediately function testLoaded() { let widthSum = 0; - for (var i = 0; i < sources.length; i++) { + for (let i = 0; i < sources.length; i++) { let img = document.createElement('img'); img.src = sources[i]; widthSum += img.width; diff --git a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html index 6280adb4..79935023 100644 --- a/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html +++ b/2-ui/3-event-details/11-onload-onerror/1-load-img-callback/source.view/index.html @@ -27,7 +27,7 @@ // let's create another img with the same src and check that we have its width immediately function testLoaded() { let widthSum = 0; - for (var i = 0; i < sources.length; i++) { + for (let i = 0; i < sources.length; i++) { let img = document.createElement('img'); img.src = sources[i]; widthSum += img.width; diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/1-behavior-nested-tooltip/solution.view/index.html b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/1-behavior-nested-tooltip/solution.view/index.html index acc466f7..8fbae4c7 100644 --- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/1-behavior-nested-tooltip/solution.view/index.html +++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/1-behavior-nested-tooltip/solution.view/index.html @@ -104,7 +104,7 @@ let left = coords.left + (anchorElem.offsetWidth - tooltipElem.offsetWidth) / 2; if (left < 0) left = 0; - var top = coords.top - tooltipElem.offsetHeight - 5; + let top = coords.top - tooltipElem.offsetHeight - 5; if (top < 0) { top = coords.top + anchorElem.offsetHeight + 5; } diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseenter-mouseleave-delegation.view/script.js b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseenter-mouseleave-delegation.view/script.js index f0fa2d35..4700d686 100755 --- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseenter-mouseleave-delegation.view/script.js +++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseenter-mouseleave-delegation.view/script.js @@ -1,12 +1,12 @@ table.onmouseover = function(event) { - var target = event.target; + let target = event.target; target.style.background = 'pink'; text.value += "mouseover " + target.tagName + "\n"; text.scrollTop = text.scrollHeight; }; table.onmouseout = function(event) { - var target = event.target; + let target = event.target; target.style.background = ''; text.value += "mouseout " + target.tagName + "\n"; text.scrollTop = text.scrollHeight; diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js index 4a411513..63ec8cdc 100755 --- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js +++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/mouseoverout-fast.view/script.js @@ -1,7 +1,7 @@ green.onmouseover = green.onmouseout = green.onmousemove = handler; function handler(event) { - var type = event.type; + let type = event.type; while (type < 11) type += ' '; log(type + " target=" + event.target.id) @@ -14,14 +14,14 @@ lastMessage = ""; } - var lastMessageTime = 0; - var lastMessage = ""; - var repeatCounter = 1; + let lastMessageTime = 0; + let lastMessage = ""; + let repeatCounter = 1; function log(message) { if (lastMessageTime == 0) lastMessageTime = new Date(); - var time = new Date(); + let time = new Date(); if (time - lastMessageTime > 500) { message = '------------------------------\n' + message; diff --git a/2-ui/3-event-details/4-drag-and-drop/1-slider/solution.md b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.md similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/1-slider/solution.md rename to 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.md diff --git a/2-ui/3-event-details/4-drag-and-drop/1-slider/solution.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.view/index.html similarity index 95% rename from 2-ui/3-event-details/4-drag-and-drop/1-slider/solution.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.view/index.html index 6c980c51..c364b42d 100644 --- a/2-ui/3-event-details/4-drag-and-drop/1-slider/solution.view/index.html +++ b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.view/index.html @@ -31,7 +31,7 @@ if (newLeft < 0) { newLeft = 0; } - var rightEdge = slider.offsetWidth - thumb.offsetWidth; + let rightEdge = slider.offsetWidth - thumb.offsetWidth; if (newLeft > rightEdge) { newLeft = rightEdge; } diff --git a/2-ui/3-event-details/4-drag-and-drop/1-slider/solution.view/style.css b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.view/style.css similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/1-slider/solution.view/style.css rename to 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/solution.view/style.css diff --git a/2-ui/3-event-details/4-drag-and-drop/1-slider/source.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/source.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/1-slider/source.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/source.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/1-slider/source.view/style.css b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/source.view/style.css similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/1-slider/source.view/style.css rename to 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/source.view/style.css diff --git a/2-ui/3-event-details/4-drag-and-drop/1-slider/task.md b/2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/task.md similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/1-slider/task.md rename to 2-ui/3-event-details/4-mouse-drag-and-drop/1-slider/task.md diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.md b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.md similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.md rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.md diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/field.svg b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/field.svg similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/field.svg rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/field.svg diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/soccer.css b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/soccer.css similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/soccer.css rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/soccer.css diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/soccer.js b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/soccer.js similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/solution.view/soccer.js rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/solution.view/soccer.js diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/source.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/source.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/source.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/source.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/source.view/soccer.css b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/source.view/soccer.css similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/source.view/soccer.css rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/source.view/soccer.css diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/source.view/soccer.js b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/source.view/soccer.js similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/source.view/soccer.js rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/source.view/soccer.js diff --git a/2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/task.md b/2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/task.md similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/2-drag-heroes/task.md rename to 2-ui/3-event-details/4-mouse-drag-and-drop/2-drag-heroes/task.md diff --git a/2-ui/3-event-details/4-drag-and-drop/article.md b/2-ui/3-event-details/4-mouse-drag-and-drop/article.md similarity index 99% rename from 2-ui/3-event-details/4-drag-and-drop/article.md rename to 2-ui/3-event-details/4-mouse-drag-and-drop/article.md index 4c573c42..7c110de1 100644 --- a/2-ui/3-event-details/4-drag-and-drop/article.md +++ b/2-ui/3-event-details/4-mouse-drag-and-drop/article.md @@ -1,4 +1,4 @@ -# Mouse: Drag'n'Drop [TODO] +# Drag'n'Drop with mouse events Drag'n'Drop is a great interface solution. Taking something, dragging and dropping is a clear and simple way to do many things, from copying and moving (see file managers) to ordering (drop into cart). diff --git a/2-ui/3-event-details/4-drag-and-drop/ball.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/ball.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/ball2.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/ball2.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball2.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball2.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/ball3.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/ball3.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball3.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball3.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/ball4.view/index.html b/2-ui/3-event-details/4-mouse-drag-and-drop/ball4.view/index.html similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball4.view/index.html rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball4.view/index.html diff --git a/2-ui/3-event-details/4-drag-and-drop/ball4.view/style.css b/2-ui/3-event-details/4-mouse-drag-and-drop/ball4.view/style.css similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball4.view/style.css rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball4.view/style.css diff --git a/2-ui/3-event-details/4-drag-and-drop/ball_shift.png b/2-ui/3-event-details/4-mouse-drag-and-drop/ball_shift.png similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball_shift.png rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball_shift.png diff --git a/2-ui/3-event-details/4-drag-and-drop/ball_shift@2x.png b/2-ui/3-event-details/4-mouse-drag-and-drop/ball_shift@2x.png similarity index 100% rename from 2-ui/3-event-details/4-drag-and-drop/ball_shift@2x.png rename to 2-ui/3-event-details/4-mouse-drag-and-drop/ball_shift@2x.png diff --git a/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js index ba644fa2..5eba24c7 100644 --- a/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js +++ b/2-ui/3-event-details/5-keyboard-events/keyboard-dump.view/script.js @@ -1,11 +1,11 @@ kinput.onkeydown = kinput.onkeyup = kinput.onkeypress = handle; -var lastTime = Date.now(); +let lastTime = Date.now(); function handle(e) { if (form.elements[e.type + 'Ignore'].checked) return; - var text = e.type + + let text = e.type + ' key=' + e.key + ' code=' + e.code + (e.shiftKey ? ' shiftKey' : '') + diff --git a/2-ui/3-event-details/8-onscroll/3-load-visible-img/source.view/index.html b/2-ui/3-event-details/8-onscroll/3-load-visible-img/source.view/index.html index ce76c588..5c6027a6 100644 --- a/2-ui/3-event-details/8-onscroll/3-load-visible-img/source.view/index.html +++ b/2-ui/3-event-details/8-onscroll/3-load-visible-img/source.view/index.html @@ -170,13 +170,13 @@ */ function isVisible(elem) { - var coords = elem.getBoundingClientRect(); + let coords = elem.getBoundingClientRect(); - var windowHeight = document.documentElement.clientHeight; + let windowHeight = document.documentElement.clientHeight; // top elem edge is visible OR bottom elem edge is visible - var topVisible = coords.top > 0 && coords.top < windowHeight; - var bottomVisible = coords.bottom < windowHeight && coords.bottom > 0; + let topVisible = coords.top > 0 && coords.top < windowHeight; + let bottomVisible = coords.bottom < windowHeight && coords.bottom > 0; return topVisible || bottomVisible; } @@ -187,16 +187,16 @@ function isVisible(elem) { - var coords = elem.getBoundingClientRect(); + let coords = elem.getBoundingClientRect(); - var windowHeight = document.documentElement.clientHeight; + let windowHeight = document.documentElement.clientHeight; - var extendedTop = -windowHeight; - var extendedBottom = 2 * windowHeight; + let extendedTop = -windowHeight; + let extendedBottom = 2 * windowHeight; // top visible || bottom visible - var topVisible = coords.top > extendedTop && coords.top < extendedBottom; - var bottomVisible = coords.bottom < extendedBottom && coords.bottom > extendedTop; + let topVisible = coords.top > extendedTop && coords.top < extendedBottom; + let bottomVisible = coords.bottom < extendedBottom && coords.bottom > extendedTop; return topVisible || bottomVisible; } diff --git a/2-ui/4-forms-controls/2-focus-blur/article.md b/2-ui/4-forms-controls/2-focus-blur/article.md index d8ed3235..4ac1993e 100644 --- a/2-ui/4-forms-controls/2-focus-blur/article.md +++ b/2-ui/4-forms-controls/2-focus-blur/article.md @@ -91,9 +91,21 @@ If we enter something into the input and then try to use `key:Tab` or click away Please note that we can't "prevent loosing focus" by calling `event.preventDefault()` in `onblur`, because `onblur` works *after* the element lost the focus. +```warn header="JavaScript-initiated focus loss" +A focus loss can occur for many reasons. + +One of them is when the visitor clicks somewhere else. But also JavaScript itself may cause it, for instance: + +- An `alert` moves focus to itself, so it causes the focus loss at the element (`blur` event), and when the `alert` is dismissed, the focus comes back (`focus` event). +- If an element is removed from DOM, then it also causes the focus loss. If it is reinserted later, then the focus doesn't return. + +These features sometimes cause `focus/blur` handlers to misbehave -- to trigger when they are not needed. + +The best recipe is to be careful when using these events. If we want to track user-initiated focus-loss, then we should evade causing it by ourselves. +``` ## Allow focusing on any element: tabindex -By default many element do not support focusing. +By default many elements do not support focusing. The list varies between browsers, but one thing is always correct: `focus/blur` support is guaranteed for elements that a visitor can interact with: ` + + + + + + + \ No newline at end of file diff --git a/5-animation/3-js-animation/text.view/style.css b/5-animation/3-js-animation/text.view/style.css new file mode 100644 index 00000000..a89789e6 --- /dev/null +++ b/5-animation/3-js-animation/text.view/style.css @@ -0,0 +1,10 @@ +textarea { + display: block; + border: 1px solid #BBB; + color: #444; + font-size: 110%; +} + +button { + margin-top: 10px; +} \ No newline at end of file diff --git a/5-animation/3-js-animation/width.view/animate.js b/5-animation/3-js-animation/width.view/animate.js new file mode 100644 index 00000000..9d028c0a --- /dev/null +++ b/5-animation/3-js-animation/width.view/animate.js @@ -0,0 +1,20 @@ +function animate(options) { + + let start = performance.now(); + + requestAnimationFrame(function animate(time) { + // timeFraction от 0 до 1 + let timeFraction = (time - start) / options.duration; + if (timeFraction > 1) timeFraction = 1; + + // текущее состояние анимации + let progress = options.timing(timeFraction) + + options.draw(progress); + + if (timeFraction < 1) { + requestAnimationFrame(animate); + } + + }); +} \ No newline at end of file diff --git a/5-animation/3-js-animation/width.view/index.html b/5-animation/3-js-animation/width.view/index.html new file mode 100644 index 00000000..afbf49de --- /dev/null +++ b/5-animation/3-js-animation/width.view/index.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/5-animation/index.md b/5-animation/index.md new file mode 100644 index 00000000..72043f5d --- /dev/null +++ b/5-animation/index.md @@ -0,0 +1,3 @@ +# Анимация + +CSS анимации. Контроль над ними из JavaScript. Анимации на чистом JavaScript. \ No newline at end of file diff --git a/archive/06-events-and-timing-in-depth/article.md b/archive/06-events-and-timing-in-depth/article.md new file mode 100644 index 00000000..f7068803 --- /dev/null +++ b/archive/06-events-and-timing-in-depth/article.md @@ -0,0 +1,306 @@ + +# Sync and async events + +JavaScript is a single-threaded language: only one script may execute at a given moment of time. + +Other activities like rendering, downloading etc may be managed by separate threads. For instance, JavaScript may execute while the browser is downloading a file, that's normal. But it is impossible that two event handlers or two `setTimeout`-scheduled function execute simultaneously. + +There is a [Web Workers](http://www.w3.org/TR/workers) standard which defines the support for multiple JavaScript *workers* -- subprocesses that may execute in parallel with the main code, but their abilities are limited. In the browser workers don't have access to DOM, so again we come to a single "main" JavaScript thread. + +## Asynchronous events + +Most events are asynchronous. + +When an asynchronous event occurs, it gets into the *Event queue*. + +The browser has inner loop, called *Event Loop*, which checks the queue and processes events, executes functions etc. + +For example, if the browser is busy processing your `onclick`, and another event happens in the background, it is appended to the queue. When the `onclick` handler is complete, the queue is checked and the script is executed. + +Calls scheduled by `setTimeout/setInterval` are also passed through the event queue, so that they wait until the JavaScript engine gets free. + + +## Synchronous events + +There are events which don't use the event queue. They are called *synchronous events* and work immediately even when inside other handlers. + + +### DOM mutation events are synchronous. + +In the example below, the `onclick` handler changes an attribute of the link, which has a `DOMAttrModified(onpropertychange for IE)` listener. + +[summary] +Synchronous mutation events are processed immediately during `onclick`. +[/summary] + +Click the link to see: +[html autorun height=auto] +Click me! + + +[/html] + +The `click` processing order: +
    +
  1. `alert('in onclick')` works.
  2. +
  3. The attribute is changed and the DOM mutation event is processed synchronously, immediately triggering `onchange`. It outputs `alert('onpropchange')`.
  4. +
  5. The rest of `onclick` executes, leading to `alert('out onclick')`.
  6. +
+ + +### Nested DOM events are synchronous. + +[summary] +There are methods which trigger an immediate event, like `elem.focus()`. These events are also processed in a synchronous manner. +[/summary] + +Run the example below and click on the button. Notice that `onfocus` +doesn't wait `onclick` to complete, it works immediately. + +[html autorun height=auto] + + + + +[/html] + +In the example above, the alert order is in onclick->focus->out onclick, that clearly demonstrates the synchronous behavior. + +[smart] +The line labelled (*) is required, because `alert(message)` focuses on the message window. When it is disposed, the browser refocuses back. + +So without (*) the `focus` would be triggered one extra time after the alert. +[/smart] + +[summary] +Events are also processed immediately when triggered from JavaScript by `dispatchEvent/fireEvent`. +[/summary] + +Usually event handlers are executed one by one. So we assume that one handler finishes before the other starts. + +**Synchronous events break this one-by-one rule, that may can cause side-effects.** + +For example, the `onfocus` handler may assume that `onclick` has completed the job. + +There are two ways to fix it: +
    +
  1. Move `text.focus()` to the end of the `onclick` code.
  2. +
  3. Wrap `text.focus()` into `setTimeout(.., 0)`: +[js] +button.onclick = function() { + alert(1) + setTimeout(function() { text.focus() }, 0) + alert(2) +} +[/js] +
  4. +
+ +The concrete way is chosen according to your architecture. + + +## JavaScript execution and rendering + +[summary]In most browsers, rendering and JavaScript use single event queue. It means that while JavaScript is running, no rendering occurs.[/summary] + +Check it on the demo below. **When you press `run`, the browser may halt for some time**, because it changes `div.style.backgroundColor` from #A00000 to #FFFFFF. + +In most browsers, you see nothing until the script finishes, or until the browser pauses it with a message that 'a script is running too long'. + +The exception is Opera. + +[html run] +
+ + + + +[/html] + +In Opera, you may notice `div` is redrawn. Not every change causes a repaint, probably because of Opera internal scheduling. That's because event queues for rendering and JavaScript are different in this browser. + +In other browsers the repaint is postponed until the JavaScript finishes. + +Again, the implementation may be different, but generally **the nodes are marked as "dirty" (want to be recalculated and redrawn), and repaint is queued**. Or, the browser may just look for dirty nodes after every script and process them. + +[smart header="Immediate reflow"] +The browser contains many optimizations to speedup rendering and painting. Generally, it tries to postpone them until the script is finished, but some actions require nodes to be rerendered immediately. + +For example: +[js] +elem.innerHTML = 'new content' +alert(elem.offsetHeight) // <-- rerenders elem to get offsetHeight +[/js] + +In the case above, the browser has to perform relayouting to get the height. +But it doesn't have to repaint `elem` on the screen. + +Sometimes other dependant nodes may get involved into calculations. This process is called *reflow* and may consume lots of resources if script causes it often. + +Surely, there's much more to talk about rendering. It will be covered by a separate article [todo]. +[/smart] + + +## Modal and synchronous calls + +[summary]Modal and synchronous calls like `alert` pause the JavaScript thread. + +That causes related activities to freeze. +[/summary] + +The example below demonstrates it. + +
    +
  1. Press "Run". The `setInterval`-based animation will start and and `alert` button will appear.
  2. +
  3. Press the button, note that the animation stops.
  4. +
+ + +[html run height=60] +
+ + + +[/html] + +When you press `alert('Hello!')`, the `alert` blocks JavaScript execution and blocks the whole UI thread. That's how `alert`, `confirm` and `prompt` work. And there is only one thread. So, **`setTimeout/setInterval` can't execute while the thread is blocked.** + + +### Opera: `iframes` exception. + +[summary]Usually, `iframes` run in the same thread with the page. [/summary] + +But there is an exception called Opera. **Run the example above in Opera** and press alert in the main window. The iframe animation will continue! +That's because the example is actually running in an iframe. + +Other browsers use single thread for whole tab, so the iframe animation is paused there. + + + +## Script taking too long and heavy jobs + +JavaScript can be heavy. + +In this case, the browser may hangup for a moment or come with a warning "Script is taking too long". + +We'd want to evade that. It can be done by split the job into parts which get scheduled after each other. + +Then there is a "free time" for the browser to respond between parts. It is can render and react on other events. Both the visitor and the browser are happy. + +The background color in the example below is changed once per tick. So the browser has the time to render it, and there are no hangups. Changes are applied incrementally. + +Press the run button on the example to start. +[html run] +
+ + + + + +[/html] + +The internal order: +
    +
  1. `setTimeout` appends the `func` call to the event queue.
  2. +
  3. The new call is scheduled on the next tick.
  4. +
  5. The func executes and changes the `div` which appends a repaint request to the queue.
  6. +
  7. The function finishes. The browser takes the next event from the queue which is repaint and executes it. Then it waits the next tick to execute one more `func` call (see step 2).
  8. +
  9. Repeated until `stop()`
  10. +
+ +A delay may be increased from 0 to 100 ms, depending on your needs. The longer delay leads to less CPU load. + +[smart header="Evade the 'script is running for too long' warning"] +As an important side-effect, splitting the long job into parts which are executed by `setTimeout` helps to fix browser hangups and evade warnings. + +For example, modern syntax highlighters employ such technique. When a visitor opens a large text, they highlight a part of it then call something like `setTimeout(highlightNext, 50)` which highlights the next part etc. + +It would hangup otherwise, because the syntax highlighting takes time. +[/smart] + + + +## Summary + +Most browsers use single thread for UI and JavaScript, which is blocked by synchronous calls. So, JavaScript execution blocks the rendering. + +Events are processed asynchronously with the exception of DOM events. + +The `setTimeout(..,0)` trick is very useful. It allows to: + + +Opera is special in many places when it comes to timeouts and threading. diff --git a/archive/2-eval-calculator-errors/solution.md b/archive/2-eval-calculator-errors/solution.md index 4241d417..c564d3ee 100644 --- a/archive/2-eval-calculator-errors/solution.md +++ b/archive/2-eval-calculator-errors/solution.md @@ -11,7 +11,7 @@ alert( eval("2+2") ); // 4 Код решения: ```js run demo -var expr, res; +let expr, res; while (true) { expr = prompt("Введите выражение?", '2-'); diff --git a/archive/5-drag-and-drop-objects/article.md b/archive/5-drag-and-drop-objects/article.md index cee2a4f6..74c58d1d 100644 --- a/archive/5-drag-and-drop-objects/article.md +++ b/archive/5-drag-and-drop-objects/article.md @@ -56,7 +56,7 @@ Код обработчика `mousedown`: ```js -var dragObject = {}; +let dragObject = {}; document.onmousedown = function(e) { @@ -64,7 +64,7 @@ document.onmousedown = function(e) { return; // то он не запускает перенос } - var elem = e.target.closest('.draggable'); + let elem = e.target.closest('.draggable'); if (!elem) return; // не нашли, клик вне draggable-объекта @@ -169,8 +169,8 @@ document.onmousemove = function(e) { if ( !dragObject.avatar ) { // если перенос не начат... // посчитать дистанцию, на которую переместился курсор мыши - var moveX = e.pageX - dragObject.downX; - var moveY = e.pageY - dragObject.downY; + let moveX = e.pageX - dragObject.downX; + let moveY = e.pageY - dragObject.downY; if ( Math.abs(moveX) < 3 && Math.abs(moveY) < 3 ) { return; // ничего не делать, мышь не передвинулась достаточно далеко } @@ -183,7 +183,7 @@ document.onmousemove = function(e) { // аватар создан успешно // создать вспомогательные свойства shiftX/shiftY - var coords = getCoords(dragObject.avatar); + let coords = getCoords(dragObject.avatar); dragObject.shiftX = dragObject.downX - coords.left; dragObject.shiftY = dragObject.downY - coords.top; @@ -210,8 +210,8 @@ document.onmousemove = function(e) { function createAvatar(e) { // запомнить старые свойства, чтобы вернуться к ним при отмене переноса - var avatar = dragObject.elem; - var old = { + let avatar = dragObject.elem; + let old = { parent: avatar.parentNode, nextSibling: avatar.nextSibling, position: avatar.position || '', @@ -237,7 +237,7 @@ function createAvatar(e) { ```js function startDrag(e) { - var avatar = dragObject.avatar; + let avatar = dragObject.avatar; document.body.appendChild(avatar); avatar.style.zIndex = 9999; @@ -275,7 +275,7 @@ document.onmouseup = function(e) { ```js function finishDrag(e) { - var dropElem = *!*findDroppable(e)*/!*; + let dropElem = *!*findDroppable(e)*/!*; if (dropElem) { ... успешный перенос ... @@ -299,7 +299,7 @@ function finishDrag(e) { function findDroppable(event) { // взять элемент на данных координатах - var elem = document.elementFromPoint(event.clientX, event.clientY); + let elem = document.elementFromPoint(event.clientX, event.clientY); // найти ближайший сверху droppable return elem.closest('.droppable'); @@ -328,7 +328,7 @@ function findDroppable(event) { dragObject.avatar.hidden = true; // получить самый вложенный элемент под курсором мыши - var elem = document.elementFromPoint(event.clientX, event.clientY); + let elem = document.elementFromPoint(event.clientX, event.clientY); // показать переносимый элемент обратно dragObject.avatar.hidden = false; @@ -351,11 +351,11 @@ function findDroppable(event) { Для его создания используем не обычный синтаксис `{...}`, а вызов `new function`. Это позволит прямо при создании объявить дополнительные переменные и функции в замыкании, которыми могут пользоваться методы объекта, а также назначить обработчики: ```js no-beautify -var DragManager = new function() { +let DragManager = new function() { - var dragObject = {}; + let dragObject = {}; - var self = this; // для доступа к себе из обработчиков + let self = this; // для доступа к себе из обработчиков function onMouseDown(e) { ... } function onMouseMove(e) { ... } diff --git a/archive/5-drag-and-drop-objects/dragDemo.view/DragManager.js b/archive/5-drag-and-drop-objects/dragDemo.view/DragManager.js index 4f0625b8..24a208db 100644 --- a/archive/5-drag-and-drop-objects/dragDemo.view/DragManager.js +++ b/archive/5-drag-and-drop-objects/dragDemo.view/DragManager.js @@ -1,4 +1,4 @@ -var DragManager = new function() { +let DragManager = new function() { /** * составной объект для хранения информации о переносе: @@ -9,15 +9,15 @@ var DragManager = new function() { * shiftX/shiftY - относительный сдвиг курсора от угла элемента * } */ - var dragObject = {}; + let dragObject = {}; - var self = this; + let self = this; function onMouseDown(e) { if (e.which != 1) return; - var elem = e.target.closest('.draggable'); + let elem = e.target.closest('.draggable'); if (!elem) return; dragObject.elem = elem; @@ -33,8 +33,8 @@ var DragManager = new function() { if (!dragObject.elem) return; // элемент не зажат if (!dragObject.avatar) { // если перенос не начат... - var moveX = e.pageX - dragObject.downX; - var moveY = e.pageY - dragObject.downY; + let moveX = e.pageX - dragObject.downX; + let moveY = e.pageY - dragObject.downY; // если мышь передвинулась в нажатом состоянии недостаточно далеко if (Math.abs(moveX) < 3 && Math.abs(moveY) < 3) { @@ -50,7 +50,7 @@ var DragManager = new function() { // аватар создан успешно // создать вспомогательные свойства shiftX/shiftY - var coords = getCoords(dragObject.avatar); + let coords = getCoords(dragObject.avatar); dragObject.shiftX = dragObject.downX - coords.left; dragObject.shiftY = dragObject.downY - coords.top; @@ -75,7 +75,7 @@ var DragManager = new function() { } function finishDrag(e) { - var dropElem = findDroppable(e); + let dropElem = findDroppable(e); if (!dropElem) { self.onDragCancel(dragObject); @@ -87,8 +87,8 @@ var DragManager = new function() { function createAvatar(e) { // запомнить старые свойства, чтобы вернуться к ним при отмене переноса - var avatar = dragObject.elem; - var old = { + let avatar = dragObject.elem; + let old = { parent: avatar.parentNode, nextSibling: avatar.nextSibling, position: avatar.position || '', @@ -110,7 +110,7 @@ var DragManager = new function() { } function startDrag(e) { - var avatar = dragObject.avatar; + let avatar = dragObject.avatar; // инициировать начало переноса document.body.appendChild(avatar); @@ -123,7 +123,7 @@ var DragManager = new function() { dragObject.avatar.hidden = true; // получить самый вложенный элемент под курсором мыши - var elem = document.elementFromPoint(event.clientX, event.clientY); + let elem = document.elementFromPoint(event.clientX, event.clientY); // показать переносимый элемент обратно dragObject.avatar.hidden = false; @@ -147,7 +147,7 @@ var DragManager = new function() { function getCoords(elem) { // кроме IE8- - var box = elem.getBoundingClientRect(); + let box = elem.getBoundingClientRect(); return { top: box.top + pageYOffset, diff --git a/archive/proto/wrong/javascript-prototype-confusion-and.html b/archive/proto/wrong/javascript-prototype-confusion-and.html index b6a8cf84..abc8f71a 100644 --- a/archive/proto/wrong/javascript-prototype-confusion-and.html +++ b/archive/proto/wrong/javascript-prototype-confusion-and.html @@ -17,7 +17,7 @@ - + Nowhere Near Ithaca: Javascript "Prototype" Confusion, and the Dubiously Useful "instanceof" @@ -574,7 +574,7 @@ width: auto; linebreaks: { automatic: true } } }); -