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/01-getting-started/1-intro/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
@@ -68,7 +68,7 @@ Examples of such restrictions include:
68
68
Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain actions, like "dropping" a file into a browser window or selecting it via an `<input>` tag.
69
69
70
70
There are ways to interact with camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency).
71
-
- Different tabs/windows generally do not know about each other. Sometimes they do; for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port).
71
+
- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port).
72
72
73
73
This is called the "Same Origin Policy". To work around that, *both pages* must agree for data exchange and contain a special JavaScript code that handles it. We'll cover that in the tutorial.
Copy file name to clipboardExpand all lines: 1-js/01-getting-started/4-devtools/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
@@ -8,7 +8,7 @@ To see errors and get a lot of other useful information about scripts, "develope
8
8
9
9
Most developers lean towards Chrome or Firefox for development because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most developers have a "favorite" browser and switch to others if a problem is browser-specific.
10
10
11
-
Developer tools are potent; they have many features. To start, we'll learn how to open them, look at errors, and run JavaScript commands.
11
+
Developer tools are potent, they have many features. To start, we'll learn how to open them, look at errors, and run JavaScript commands.
Copy file name to clipboardExpand all lines: 1-js/03-code-quality/06-polyfills/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
@@ -23,7 +23,7 @@ Actually, there are two parts in Babel:
23
23
24
24
2. Second, the polyfill.
25
25
26
-
New language features may include new built-in functions and syntax constructs.
26
+
New language features may include not only syntax constructs, but also built-in functions.
27
27
The transpiler rewrites the code, transforming syntax constructs into older ones. But as for new built-in functions, we need to implement them. JavaScript is a highly dynamic language, scripts may add/modify any functions, so that they behave according to the modern standard.
28
28
29
29
A script that updates/adds new functions is called "polyfill". It "fills in" the gap and adds missing implementations.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/02-object-copy/article.md
+41-18Lines changed: 41 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,8 @@
1
1
# Object references and copying
2
2
3
-
One of the fundamental differences of objects versus primitives is that objects are stored and copied "by reference", as opposed to primitive values: strings, numbers, booleans, etc -- that are always copied "as a whole value".
3
+
One of the fundamental differences of objects versus primitives is that objects are stored and copied "by reference", whereas primitive values: strings, numbers, booleans, etc -- are always copied "as a whole value".
4
4
5
-
That's easy to understand if we look a bit "under a cover" of what happens when we copy a value.
5
+
That's easy to understand if we look a bit under the hood of what happens when we copy a value.
6
6
7
7
Let's start with a primitive, such as a string.
8
8
@@ -13,17 +13,17 @@ let message = "Hello!";
13
13
let phrase = message;
14
14
```
15
15
16
-
As a result we have two independent variables, each one is storing the string `"Hello!"`.
16
+
As a result we have two independent variables, each one storing the string `"Hello!"`.
17
17
18
18

19
19
20
20
Quite an obvious result, right?
21
21
22
22
Objects are not like that.
23
23
24
-
**A variable assigned to an object stores not the object itself, but its "address in memory", in other words "a reference" to it.**
24
+
**A variable assigned to an object stores not the object itself, but its "address in memory" -- in other words "a reference" to it.**
25
25
26
-
Let's look at an example of such variable:
26
+
Let's look at an example of such a variable:
27
27
28
28
```js
29
29
let user = {
@@ -37,13 +37,13 @@ And here's how it's actually stored in memory:
37
37
38
38
The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it.
39
39
40
-
We may think of an object variable, such as `user`, as of a sheet of paper with the address.
40
+
We may think of an object variable, such as `user`, as like a sheet of paper with the address of the object on it.
41
41
42
-
When we perform actions with the object, e.g. take a property `user.name`, JavaScript engine looks into that address and performs the operation on the actual object.
42
+
When we perform actions with the object, e.g. take a property `user.name`, the JavaScript engine looks at what's at that address and performs the operation on the actual object.
43
43
44
44
Now here's why it's important.
45
45
46
-
**When an object variable is copied -- the reference is copied, the object is not duplicated.**
46
+
**When an object variable is copied, the reference is copied, but the object itself is not duplicated.**
47
47
48
48
For instance:
49
49
@@ -53,13 +53,13 @@ let user = { name: "John" };
53
53
let admin = user; // copy the reference
54
54
```
55
55
56
-
Now we have two variables, each one with the reference to the same object:
56
+
Now we have two variables, each storing a reference to the same object:
57
57
58
58

59
59
60
-
As you can see, there's still one object, now with two variables that reference it.
60
+
As you can see, there's still one object, but now with two variables that reference it.
61
61
62
-
We can use any variable to access the object and modify its contents:
62
+
We can use either variable to access the object and modify its contents:
63
63
64
64
```js run
65
65
let user = { name:'John' };
@@ -73,8 +73,7 @@ admin.name = 'Pete'; // changed by the "admin" reference
73
73
alert(*!*user.name*/!*); //'Pete', changes are seen from the "user" reference
74
74
```
75
75
76
-
77
-
It's just as if we had a cabinet with two keys and used one of them (`admin`) to get into it. Then, if we later use another key (`user`) we can see changes.
76
+
It's as if we had a cabinet with two keys and used one of them (`admin`) to get into it and make changes. Then, if we later use another key (`user`), we are still opening the same cabinet and can access the changed contents.
78
77
79
78
## Comparison by reference
80
79
@@ -99,15 +98,15 @@ let b = {}; // two independent objects
99
98
alert( a == b ); // false
100
99
```
101
100
102
-
For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj ==5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely, usually they appear as a result of a programming mistake.
101
+
For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj ==5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely -- usually they appear as a result of a programming mistake.
103
102
104
103
## Cloning and merging, Object.assign
105
104
106
105
So, copying an object variable creates one more reference to the same object.
107
106
108
107
But what if we need to duplicate an object? Create an independent copy, a clone?
109
108
110
-
That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. Actually, that's rarely needed. Copying by reference is good most of the time.
109
+
That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. But there is rarely a need -- copying by reference is good most of the time.
111
110
112
111
But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level.
113
112
@@ -226,13 +225,37 @@ user.sizes.width++; // change a property from one place
226
225
alert(clone.sizes.width); // 51, see the result from the other one
227
226
```
228
227
229
-
To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning".
228
+
To fix that, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning".
229
+
230
+
We can use recursion to implement it. Or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).
231
+
232
+
````smart header="Const objects can be modified"
233
+
An important side effect of storing objects as references is that an object declared as `const` *can* bemodified.
234
+
235
+
For instance:
236
+
237
+
```js run
238
+
const user = {
239
+
name: "John"
240
+
};
241
+
242
+
*!*
243
+
user.name = "Pete"; // (*)
244
+
*/!*
245
+
246
+
alert(user.name); // Pete
247
+
```
248
+
249
+
It might seem that the line `(*)` would cause an error, but it does not. The value of`user` is constant, it must always reference the same object, but properties of that object are free to change.
250
+
251
+
In other words, the `const user` gives an error only if we try to set `user=...` as a whole.
230
252
231
-
We can use recursion to implement it. Or, not to reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).
253
+
That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter <info:property-descriptors>.
254
+
````
232
255
233
256
## Summary
234
257
235
-
Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object.
258
+
Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself.
236
259
237
260
All operations via copied references (likeadding/removingproperties) are performed on the same single object.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/03-garbage-collection/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
@@ -23,7 +23,7 @@ Simply put, "reachable" values are those that are accessible or usable somehow.
23
23
24
24
2. Any other value is considered reachable if it's reachable from a root by a reference or by a chain of references.
25
25
26
-
For instance, if there's an object in a global variable, and that object has a property referencing another object, that object is considered reachable. And those that it references are also reachable. Detailed examples to follow.
26
+
For instance, if there's an object in a global variable, and that object has a property referencing another object, *that* object is considered reachable. And those that it references are also reachable. Detailed examples to follow.
27
27
28
28
There's a background process in the JavaScript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that have become unreachable.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/07-optional-chaining/article.md
+62-23Lines changed: 62 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,51 +9,89 @@ 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, let's 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'll 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
-
let user = {}; //the user without "address" property
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, but many practical cases we'd prefer to get `undefined` instead of an error (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 to get an information about an element on the page, that sometimes doesn't exist:
28
+
...And another example. In the web development, we can get an object that corresponds to a web page element 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
-
//Error if the result of querySelector(...) is null
28
-
let html =document.querySelector('.my-element').innerHTML;
31
+
//document.querySelector('.elem') is null if there's no element
32
+
let html =document.querySelector('.elem').innerHTML;// error if it's null
29
33
```
30
34
31
-
Before `?.` appeared in the language, the `&&` operator was used to work around that.
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
-
For example:
37
+
How can we do this?
38
+
39
+
The obvious solution would be to check the value using `if` or the conditional operator `?`, before accessing its property, like this:
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.
48
+
49
+
E.g. let's try getting `user.address.street.name`.
50
+
51
+
We need to check both `user.address` and `user.address.street`:
Please note: the `?.` syntax makes optional the value before it, but not any further.
67
105
68
-
In the example above, `user?.` allows only `user` to be `null/undefined`.
69
-
70
-
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 `?.`.
71
107
72
108
```warn header="Don't overuse the optional chaining"
73
109
We should use `?.` only where it's ok that something doesn't exist.
74
110
75
-
For example, if according to our coding logic `user` object must be there, but `address` is optional, then `user.address?.street` would be better.
111
+
For example, if according to our coding logic `user` object must exist, but `address` is optional, then we should write `user.address?.street`, but not `user?.address?.street`.
76
112
77
113
So, if`user` happens to be undefined due to a mistake, we'll see a programming error about it and fix it. Otherwise, coding errors can be silenced where not appropriate, and become more difficult to debug.
78
114
```
@@ -84,7 +120,7 @@ If there's no variable `user` at all, then `user?.anything` triggers an error:
84
120
// ReferenceError: user is not defined
85
121
user?.address;
86
122
```
87
-
There must be a declaration(e.g. `let/const/var user`). The optional chaining works only for declared variables.
123
+
The variable must be declared(e.g. `let/const/var user` or as a function parameter). The optional chaining works only for declared variables.
88
124
````
89
125
90
126
## Short-circuiting
@@ -113,17 +149,20 @@ For example, `?.()` is used to call a function that may not exist.
113
149
In the code below, some of our users have `admin` method, and some don't:
0 commit comments