You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/04-var/article.md
+26-27Lines changed: 26 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,17 @@ In the very first chapter about [variables](info:variables), we mentioned three
13
13
2.`const`
14
14
3.`var`
15
15
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
+
=======
16
25
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
17
27
18
28
```js run
19
29
var message ="Hi";
@@ -28,11 +38,11 @@ On the other hand, it's important to understand differences when migrating old s
28
38
29
39
## "var" has no block scope
30
40
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.
32
42
33
43
For instance:
34
44
35
-
```js run
45
+
```js
36
46
if (true) {
37
47
var test =true; // use "var" instead of "let"
38
48
}
@@ -42,19 +52,7 @@ alert(test); // true, the variable lives after if
42
52
*/!*
43
53
```
44
54
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`.
58
56
59
57
The same thing for loops: `var` cannot be block- or loop-local:
60
58
@@ -70,7 +68,7 @@ alert(i); // 10, "i" is visible after loop, it's a global variable
70
68
71
69
If a code block is inside a function, then `var` becomes a function-level variable:
72
70
73
-
```js run
71
+
```js
74
72
functionsayHi() {
75
73
if (true) {
76
74
var phrase ="Hello";
@@ -80,11 +78,14 @@ function sayHi() {
80
78
}
81
79
82
80
sayHi();
83
-
alert(phrase); // Error: phrase is not defined (Check the Developer Console)
81
+
alert(phrase); // Error: phrase is not defined
84
82
```
85
83
86
84
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.
87
85
86
+
<<<<<<< HEAD
87
+
## "var" are processed at the function start
88
+
=======
88
89
## "var" tolerates redeclarations
89
90
90
91
If we declare the same variable with `let` twice in the same scope, that's an error:
@@ -106,14 +107,15 @@ alert(user); // John
106
107
```
107
108
108
109
## "var" variables can be declared below their use
110
+
>>>>>>> d35baee32dcce127a69325c274799bb81db1afd8
109
111
110
112
`var` declarations are processed when the function starts (or script starts for globals).
111
113
112
114
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).
113
115
114
116
So this code:
115
117
116
-
```js run
118
+
```js
117
119
functionsayHi() {
118
120
phrase ="Hello";
119
121
@@ -123,12 +125,11 @@ function sayHi() {
123
125
var phrase;
124
126
*/!*
125
127
}
126
-
sayHi();
127
128
```
128
129
129
130
...Is technically the same as this (moved `var phrase` above):
130
131
131
-
```js run
132
+
```js
132
133
functionsayHi() {
133
134
*!*
134
135
var phrase;
@@ -138,12 +139,11 @@ function sayHi() {
138
139
139
140
alert(phrase);
140
141
}
141
-
sayHi();
142
142
```
143
143
144
144
...Or even as this (remember, code blocks are ignored):
145
145
146
-
```js run
146
+
```js
147
147
functionsayHi() {
148
148
phrase ="Hello"; // (*)
149
149
@@ -155,7 +155,6 @@ function sayHi() {
155
155
156
156
alert(phrase);
157
157
}
158
-
sayHi();
159
158
```
160
159
161
160
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.
275
274
276
275
## Summary
277
276
278
-
There are two main differences of `var` compared to `let/const`:
277
+
There are two main differences of `var`:
279
278
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.
282
281
283
282
There's one more very minor difference related to the global object, that we'll cover in the next chapter.
284
283
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.
Copy file name to clipboardExpand all lines: 2-ui/2-events/02-bubbling-and-capturing/article.md
+19-31Lines changed: 19 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -108,7 +108,7 @@ Sometimes `event.stopPropagation()` creates hidden pitfalls that later may becom
108
108
109
109
For instance:
110
110
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.
112
112
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.
113
113
3. Our analytic won't work over the area where clicks are stopped by `stopPropagation`. Sadly, we've got a "dead zone".
114
114
@@ -130,29 +130,24 @@ Here's the picture of a click on `<td>` inside a table, taken from the specifica
130
130
131
131

132
132
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.
134
134
135
135
**Before we only talked about bubbling, because the capturing phase is rarely used. Normally it is invisible to us.**
136
136
137
137
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.
138
138
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`.
140
140
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:
148
142
149
143
- If it's `false` (default), then the handler is set on the bubbling phase.
150
144
- If it's `true`, then the handler is set on the capturing phase.
151
145
152
-
153
146
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.
154
147
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:
156
151
157
152
```html run autorun height=140 edit
158
153
<style>
@@ -180,39 +175,32 @@ The code sets click handlers on *every* element in the document to see which one
180
175
181
176
If you click on `<p>`, then the sequence is:
182
177
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
+
=======
183
182
1.`HTML` -> `BODY` -> `FORM` -> `DIV` (capturing phase, the first listener):
184
183
2.`P` (target phase, triggers two times, as we've set two listeners: capturing and bubbling)
185
184
3.`DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
185
+
>>>>>>> d35baee32dcce127a69325c274799bb81db1afd8
186
186
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.
201
188
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.
202
190
203
191
## Summary
204
192
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:
206
194
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`.
210
198
211
199
Each handler can access `event` object properties:
212
200
213
201
-`event.target` -- the deepest element that originated the event.
214
202
-`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).
216
204
217
205
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.
0 commit comments