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/04-object-basics/07-optional-chaining/article.md
+30-21Lines changed: 30 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,38 +9,42 @@ The optional chaining `?.` is a safe way to access nested object properties, eve
9
9
10
10
If you've just started to read the tutorial and learn JavaScript, maybe the problem hasn't touched you yet, but it's quite common.
11
11
12
-
As an example, consider objects for user data. Most of our users have addresses in `user.address` property, with the street `user.address.street`, but some did not provide them.
12
+
As an example, let's say we have `user` objects that hold the information about our users.
13
13
14
-
In such case, when we attempt to get `user.address.street`, we may get an error:
14
+
Most of our users have addresses in `user.address` property, with the street `user.address.street`, but some did not provide them.
15
+
16
+
In such case, when we attempt to get `user.address.street`, and the user happens to be without an address, we get an error:
15
17
16
18
```js run
17
19
let user = {}; // a user without "address" property
18
20
19
21
alert(user.address.street); // Error!
20
22
```
21
23
22
-
That's the expected result, JavaScript works like this. As `user.address` is `undefined`, the attempt to get `user.address.street` fails with an error. Although, in many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street").
24
+
That's the expected result. JavaScript works like this. As `user.address` is `undefined`, an attempt to get `user.address.street` fails with an error.
25
+
26
+
In many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street").
23
27
24
-
...And another example. In the web development, we may need the information about an element on the page. The element is returned by `document.querySelector('.elem')`, and the catch is again - that it sometimes doesn't exist:
28
+
...And another example. In the web development, we can get an object that corresponds to a web pageelement using a special method call, such as `document.querySelector('.elem')`, and it returns `null` when there's no such element.
25
29
26
30
```js run
27
-
//the result of the call document.querySelector('.elem') may be an object or null
31
+
// document.querySelector('.elem') is null if there's no element
28
32
let html =document.querySelector('.elem').innerHTML; // error if it's null
29
33
```
30
34
31
-
Once again, we may want to avoid the error in such case.
35
+
Once again, if the element doesn't exist, we'll get an error accessing `.innerHTML` of `null`. And in some cases, when the absence of the element is normal, we'd like to avoid the error and just accept `html = null` as the result.
32
36
33
37
How can we do this?
34
38
35
-
The obvious solution would be to check the value using `if` or the conditional operator `?`, before accessing it, like this:
39
+
The obvious solution would be to check the value using `if` or the conditional operator `?`, before accessing its property, like this:
...But that's quite inelegant. As you can see, the `user.address` is duplicated in the code. For more deeply nested properties, that becomes a problem.
47
+
It works, there's no error...But it's quite inelegant. As you can see, the `"user.address"` appears twice in the code. For more deeply nested properties, that becomes a problem as more repetitions are required.
44
48
45
49
E.g. let's try getting `user.address.street.name`.
46
50
@@ -52,9 +56,9 @@ let user = {}; // user has no address
Please note: the `?.` syntax makes optional the value before it, but not any further.
97
105
98
-
In the example above, `user?.address.street` allows only `user` to be `null/undefined`.
99
-
100
-
On the other hand, if `user` does exist, then it must have `user.address` property, otherwise `user?.address.street` gives an error at the second dot.
106
+
E.g. in `user?.address.street.name` the `?.` allows `user` to be `null/undefined`, but it's all it does. Further properties are accessed in a regular way. If we want some of them to be optional, then we'll need to replace more `.` with `?.`.
101
107
102
108
```warn header="Don't overuse the optional chaining"
103
109
We should use `?.` only where it's ok that something doesn't exist.
@@ -143,17 +149,20 @@ For example, `?.()` is used to call a function that may not exist.
143
149
In the code below, some of our users have `admin` method, and some don't:
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/04-var/article.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,7 +82,7 @@ function sayHi() {
82
82
}
83
83
84
84
sayHi();
85
-
alert(phrase); // Error: phrase is not defined (Check the Developer Console)
85
+
alert(phrase); // Error: phrase is not defined
86
86
```
87
87
88
88
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.
@@ -279,7 +279,7 @@ In all the above cases we declare a Function Expression and run it immediately.
279
279
280
280
There are two main differences of `var` compared to `let/const`:
281
281
282
-
1.`var` variables have no block scope; their visibility is scoped to current function, or global, if declared outside function.
282
+
1.`var` variables have no block scope, their visibility is scoped to current function, or global, if declared outside function.
283
283
2.`var` declarations are processed at function start (script start for globals).
284
284
285
285
There's one more very minor difference related to the global object, that we'll cover in the next chapter.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/05-global-object/article.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ The global object provides variables and functions that are available anywhere.
5
5
6
6
In a browser it is named `window`, for Node.js it is `global`, for other environments it may have another name.
7
7
8
-
Recently, `globalThis` was added to the language, as a standardized name for a global object, that should be supported across all environments. It's supported in all major browsers.
8
+
Recently, `globalThis` was added to the language, as a standardized name for a global object, that should be supported across all environments. It's supported in all major browsers.
9
9
10
10
We'll use `window` here, assuming that our environment is a browser. If your script may run in other environments, it's better to use `globalThis` instead.
11
11
@@ -25,6 +25,8 @@ var gVar = 5;
25
25
alert(window.gVar); // 5 (became a property of the global object)
26
26
```
27
27
28
+
The same effect have function declarations (statements with `function` keyword in the main code flow, not function expressions).
29
+
28
30
Please don't rely on that! This behavior exists for compatibility reasons. Modern scripts use [JavaScript modules](info:modules) where such thing doesn't happen.
29
31
30
32
If we used `let` instead, such thing wouldn't happen:
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/06-function-object/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -347,7 +347,7 @@ If the function is declared as a Function Expression (not in the main code flow)
347
347
348
348
Also, functions may carry additional properties. Many well-known JavaScript libraries make great use of this feature.
349
349
350
-
They create a "main" function and attach many other "helper" functions to it. For instance, the [jQuery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`, and then adds `_.clone`, `_.keyBy` and other properties to it (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts.
350
+
They create a "main" function and attach many other "helper" functions to it. For instance, the [jQuery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`, and then adds `_.clone`, `_.keyBy` and other properties to it (see the [docs](https://lodash.com/docs) when you want to learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts.
351
351
352
352
353
353
So, a function can do a useful job by itself and also carry a bunch of other functionality in properties.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/07-new-function/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -92,7 +92,7 @@ What if it could access the outer variables?
92
92
93
93
The problem is that before JavaScript is published to production, it's compressed using a *minifier* -- a special program that shrinks code by removing extra comments, spaces and -- what's important, renames local variables into shorter ones.
94
94
95
-
For instance, if a function has `let userName`, minifier replaces it `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function, minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, so they don't break anything. They're not just a dumb find-and-replace.
95
+
For instance, if a function has `let userName`, minifier replaces it with `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function, minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, so they don't break anything. They're not just a dumb find-and-replace.
96
96
97
97
So if `new Function` had access to outer variables, it would be unable to find renamed `userName`.
```smart header="Time goes on while `alert` is shown"
130
130
In most browsers, including Chrome and Firefox the internal timer continues "ticking" while showing `alert/confirm/prompt`.
131
131
132
-
So if you run the code above and don't dismiss the `alert` window for some time, then in the next `alert` will be shown immediately as you do it. The actual interval between alerts will be shorter than 2 seconds.
132
+
So if you run the code above and don't dismiss the `alert` window for some time, then the next `alert` will be shown immediately as you do it. The actual interval between alerts will be shorter than 2 seconds.
133
133
```
134
134
135
135
## Nested setTimeout
@@ -281,7 +281,7 @@ The similar thing happens if we use `setInterval` instead of `setTimeout`: `setI
281
281
282
282
That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons.
283
283
284
-
For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [setImmediate](https://nodejs.org/api/timers.html) for Node.js. So this note is browser-specific.
284
+
For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [setImmediate](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args) for Node.js. So this note is browser-specific.
285
285
````
286
286
287
287
## Summary
@@ -290,7 +290,7 @@ For server-side JavaScript, that limitation does not exist, and there exist othe
290
290
- To cancel the execution, we should call `clearTimeout/clearInterval` with the value returned by `setTimeout/setInterval`.
291
291
- Nested `setTimeout` calls are a more flexible alternative to `setInterval`, allowing us to set the time *between* executions more precisely.
292
292
- Zero delay scheduling with `setTimeout(func, 0)` (the same as `setTimeout(func)`) is used to schedule the call "as soon as possible, but after the current script is complete".
293
-
- The browser limits the minimal delay for five or more nested call of `setTimeout` or for `setInterval` (after 5th call) to 4ms. That's for historical reasons.
293
+
- The browser limits the minimal delay for five or more nested calls of `setTimeout` or for `setInterval` (after 5th call) to 4ms. That's for historical reasons.
294
294
295
295
Please note that all scheduling methods do not *guarantee* the exact delay.
Copy file name to clipboardExpand all lines: 1-js/08-prototypes/01-prototype-inheritance/article.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -198,8 +198,8 @@ alert(admin.fullName); // John Smith (*)
198
198
// setter triggers!
199
199
admin.fullName="Alice Cooper"; // (**)
200
200
201
-
alert(admin.fullName); // Alice Cooper, state of admin modified
202
-
alert(user.fullName); // John Smith, state of user protected
201
+
alert(admin.fullName); // Alice Cooper, state of admin modified
202
+
alert(user.fullName); // John Smith, state of user protected
203
203
```
204
204
205
205
Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called.
Copy file name to clipboardExpand all lines: 2-ui/2-events/02-bubbling-and-capturing/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -206,7 +206,7 @@ When an event happens -- the most nested element where it happens gets labeled a
206
206
207
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
208
- Then handlers are called on the target element itself.
209
-
- Then the event bubbles up from `event.target` to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false/{capture:false}`.
209
+
- Then the event bubbles up from `event.target` to the root, calling handlers assigned using `on<event>`, HTML attributes and `addEventListener` without the 3rd argument or with the 3rd argument `false/{capture:false}`.
210
210
211
211
Each handler can access `event` object properties:
Copy file name to clipboardExpand all lines: 2-ui/2-events/03-event-delegation/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ Capturing and bubbling allow us to implement one of most powerful event handling
5
5
6
6
The idea is that if we have a lot of elements handled in a similar way, then instead of assigning a handler to each of them -- we put a single handler on their common ancestor.
7
7
8
-
In the handler we get `event.target`, see where the event actually happened and handle it.
8
+
In the handler we get `event.target` to see where the event actually happened and handle it.
9
9
10
10
Let's see an example -- the [Ba-Gua diagram](http://en.wikipedia.org/wiki/Ba_gua) reflecting the ancient Chinese philosophy.
0 commit comments