Skip to content

Commit 90943ec

Browse files
committed
� Conflicts: � 1-js/02-first-steps/04-variables/article.md � 1-js/06-advanced-functions/04-var/article.md � 2-ui/2-events/02-bubbling-and-capturing/article.md
2 parents cbdac88 + 17f2f44 commit 90943ec

2 files changed

Lines changed: 45 additions & 58 deletions

File tree

1-js/06-advanced-functions/04-var/article.md

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@ In the very first chapter about [variables](info:variables), we mentioned three
1313
2. `const`
1414
3. `var`
1515

16+
<<<<<<< HEAD
17+
`let` and `const` behave exactly the same way in terms of Lexical Environments.
18+
19+
But `var` is a very different beast, that originates from very old times. It's generally not used in modern scripts, but still lurks in the old ones.
20+
21+
If you don't plan meeting such scripts you may even skip this chapter or postpone it, but then there's a chance that it bites you later.
22+
23+
From the first sight, `var` behaves similar to `let`. That is, declares a variable:
24+
=======
1625
The `var` declaration is similar to `let`. Most of the time we can replace `let` by `var` or vice-versa and expect things to work:
26+
>>>>>>> d35baee32dcce127a69325c274799bb81db1afd8
1727
1828
```js run
1929
var message = "Hi";
@@ -28,11 +38,11 @@ On the other hand, it's important to understand differences when migrating old s
2838

2939
## "var" has no block scope
3040

31-
Variables, declared with `var`, are either function-wide or global. They are visible through blocks.
41+
`var` variables are either function-wide or global, they are visible through blocks.
3242

3343
For instance:
3444

35-
```js run
45+
```js
3646
if (true) {
3747
var test = true; // use "var" instead of "let"
3848
}
@@ -42,19 +52,7 @@ alert(test); // true, the variable lives after if
4252
*/!*
4353
```
4454

45-
As `var` ignores code blocks, we've got a global variable `test`.
46-
47-
If we used `let test` instead of `var test`, then the variable would only be visible inside `if`:
48-
49-
```js run
50-
if (true) {
51-
let test = true; // use "let"
52-
}
53-
54-
*!*
55-
alert(test); // Error: test is not defined
56-
*/!*
57-
```
55+
If we used `let test` on the 2nd line, then it wouldn't be visible to `alert`. But `var` ignores code blocks, so we've got a global `test`.
5856

5957
The same thing for loops: `var` cannot be block- or loop-local:
6058

@@ -70,7 +68,7 @@ alert(i); // 10, "i" is visible after loop, it's a global variable
7068

7169
If a code block is inside a function, then `var` becomes a function-level variable:
7270

73-
```js run
71+
```js
7472
function sayHi() {
7573
if (true) {
7674
var phrase = "Hello";
@@ -80,11 +78,14 @@ function sayHi() {
8078
}
8179

8280
sayHi();
83-
alert(phrase); // Error: phrase is not defined (Check the Developer Console)
81+
alert(phrase); // Error: phrase is not defined
8482
```
8583

8684
As we can see, `var` pierces through `if`, `for` or other code blocks. That's because a long time ago in JavaScript blocks had no Lexical Environments. And `var` is a remnant of that.
8785

86+
<<<<<<< HEAD
87+
## "var" are processed at the function start
88+
=======
8889
## "var" tolerates redeclarations
8990

9091
If we declare the same variable with `let` twice in the same scope, that's an error:
@@ -106,14 +107,15 @@ alert(user); // John
106107
```
107108

108109
## "var" variables can be declared below their use
110+
>>>>>>> d35baee32dcce127a69325c274799bb81db1afd8
109111
110112
`var` declarations are processed when the function starts (or script starts for globals).
111113

112114
In other words, `var` variables are defined from the beginning of the function, no matter where the definition is (assuming that the definition is not in the nested function).
113115

114116
So this code:
115117

116-
```js run
118+
```js
117119
function sayHi() {
118120
phrase = "Hello";
119121

@@ -123,12 +125,11 @@ function sayHi() {
123125
var phrase;
124126
*/!*
125127
}
126-
sayHi();
127128
```
128129

129130
...Is technically the same as this (moved `var phrase` above):
130131

131-
```js run
132+
```js
132133
function sayHi() {
133134
*!*
134135
var phrase;
@@ -138,12 +139,11 @@ function sayHi() {
138139

139140
alert(phrase);
140141
}
141-
sayHi();
142142
```
143143

144144
...Or even as this (remember, code blocks are ignored):
145145

146-
```js run
146+
```js
147147
function sayHi() {
148148
phrase = "Hello"; // (*)
149149

@@ -155,7 +155,6 @@ function sayHi() {
155155

156156
alert(phrase);
157157
}
158-
sayHi();
159158
```
160159

161160
People also call such behavior "hoisting" (raising), because all `var` are "hoisted" (raised) to the top of the function.
@@ -275,11 +274,11 @@ In all the above cases we declare a Function Expression and run it immediately.
275274

276275
## Summary
277276

278-
There are two main differences of `var` compared to `let/const`:
277+
There are two main differences of `var`:
279278

280-
1. `var` variables have no block scope, they are visible minimum at the function level.
281-
2. `var` declarations are processed at function start (script start for globals).
279+
1. Variables have no block scope, they are visible minimum at the function level.
280+
2. Variable declarations are processed at function start.
282281

283282
There's one more very minor difference related to the global object, that we'll cover in the next chapter.
284283

285-
These differences make `var` worse than `let` most of the time. Block-level variables is such a great thing. That's why `let` was introduced in the standard long ago, and is now a major way (along with `const`) to declare a variable.
284+
These differences are actually a bad thing most of the time. First, we can't create block-local variables. And hoisting just creates more space for errors. So, for new scripts `var` is used exceptionally rarely.

2-ui/2-events/02-bubbling-and-capturing/article.md

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ Sometimes `event.stopPropagation()` creates hidden pitfalls that later may becom
108108
109109
For instance:
110110
111-
1. We create a nested menu. Each submenu handles clicks on its elements and calls `stopPropagation` so that the outer menu won't trigger.
111+
1. We create a nested menu. Each submenu handles clicks on its elements and calls `stopPropagation` so that outer menu don't trigger.
112112
2. Later we decide to catch clicks on the whole window, to track users' behavior (where people click). Some analytic systems do that. Usually the code uses `document.addEventListener('click'…)` to catch all clicks.
113113
3. Our analytic won't work over the area where clicks are stopped by `stopPropagation`. Sadly, we've got a "dead zone".
114114
@@ -130,29 +130,24 @@ Here's the picture of a click on `<td>` inside a table, taken from the specifica
130130

131131
![](eventflow.svg)
132132

133-
That is: for a click on `<td>` the event first goes through the ancestors chain down to the element (capturing phase), then it reaches the target and triggers there (target phase), and then it goes up (bubbling phase), calling handlers on its way.
133+
That is: for a click on `<td>` the event first goes through the ancestors chain down to the element (capturing), then it reaches the target, and then it goes up (bubbles), calling handlers on its way.
134134

135135
**Before we only talked about bubbling, because the capturing phase is rarely used. Normally it is invisible to us.**
136136

137137
Handlers added using `on<event>`-property or using HTML attributes or using two-argument `addEventListener(event, handler)` don't know anything about capturing, they only run on the 2nd and 3rd phases.
138138

139-
To catch an event on the capturing phase, we need to set the handler `capture` option to `true`:
139+
To catch an event on the capturing phase, we need to set the 3rd argument of `addEventListener` to `true`.
140140

141-
```js
142-
elem.addEventListener(..., {capture: true})
143-
// or, just "true" is an alias to {capture: true}
144-
elem.addEventListener(..., true)
145-
```
146-
147-
There are two possible values of the `capture` option:
141+
There are two possible values for that optional last argument:
148142

149143
- If it's `false` (default), then the handler is set on the bubbling phase.
150144
- If it's `true`, then the handler is set on the capturing phase.
151145

152-
153146
Note that while formally there are 3 phases, the 2nd phase ("target phase": the event reached the element) is not handled separately: handlers on both capturing and bubbling phases trigger at that phase.
154147

155-
Let's see both capturing and bubbling in action:
148+
If one puts capturing and bubbling handlers on the target element, the capture handler triggers last in the capturing phase and the bubble handler triggers first in the bubbling phase.
149+
150+
Let's see it in action:
156151

157152
```html run autorun height=140 edit
158153
<style>
@@ -180,39 +175,32 @@ The code sets click handlers on *every* element in the document to see which one
180175

181176
If you click on `<p>`, then the sequence is:
182177

178+
<<<<<<< HEAD
179+
1. `HTML` -> `BODY` -> `FORM` -> `DIV` -> `P` (capturing phase, the first listener), and then:
180+
2. `P` -> `DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
181+
=======
183182
1. `HTML` -> `BODY` -> `FORM` -> `DIV` (capturing phase, the first listener):
184183
2. `P` (target phase, triggers two times, as we've set two listeners: capturing and bubbling)
185184
3. `DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
185+
>>>>>>> d35baee32dcce127a69325c274799bb81db1afd8
186186
187-
There's a property `event.eventPhase` that tells us the number of the phase on which the event was caught. But it's rarely used, because we usually know it in the handler.
188-
189-
```smart header="To remove the handler, `removeEventListener` needs the same phase"
190-
If we `addEventListener(..., true)`, then we should mention the same phase in `removeEventListener(..., true)` to correctly remove the handler.
191-
```
192-
193-
````smart header="Listeners on same element and same phase run in their set order"
194-
If we have multiple event handlers on the same phase, assigned to the same element with `addEventListener`, they run in the same order as they are created:
195-
196-
```js
197-
elem.addEventListener("click", e => alert(1)); // guaranteed to trigger first
198-
elem.addEventListener("click", e => alert(2));
199-
```
200-
````
187+
Please note that `P` shows up two times: at the end of capturing and at the start of bubbling.
201188

189+
There's a property `event.eventPhase` that tells us the number of the phase on which the event was caught. But it's rarely used, because we usually know it in the handler.
202190

203191
## Summary
204192

205-
When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
193+
The event handling process:
206194

207-
- Then the event moves down from the document root to `event.target`, calling handlers assigned with `addEventListener(..., true)` on the way (`true` is a shorthand for `{capture: true}`).
208-
- Then handlers are called on the target element itself.
209-
- Then the event bubbles up from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false/{capture:false}`.
195+
- When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
196+
- Then the event first moves from the document root down to the `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way.
197+
- Then the event moves from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false`.
210198

211199
Each handler can access `event` object properties:
212200

213201
- `event.target` -- the deepest element that originated the event.
214202
- `event.currentTarget` (=`this`) -- the current element that handles the event (the one that has the handler on it)
215-
- `event.eventPhase` -- the current phase (capturing=1, target=2, bubbling=3).
203+
- `event.eventPhase` -- the current phase (capturing=1, bubbling=3).
216204

217205
Any event handler can stop the event by calling `event.stopPropagation()`, but that's not recommended, because we can't really be sure we won't need it above, maybe for completely different things.
218206

0 commit comments

Comments
 (0)