Skip to content

Commit 74d6397

Browse files
authored
Merge pull request #132 from longo-andrea/master
sync with upstream
2 parents 1f21c91 + b190357 commit 74d6397

File tree

40 files changed

+255
-310
lines changed

40 files changed

+255
-310
lines changed

1-js/01-getting-started/4-devtools/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Per poter visualizzare gli errori e ricevere altre informazioni utili riguardo g
99
Molto spesso gli sviluppatori tendono ad utilizzare Chrome o Firefox poichè questi browser forniscono i migliori strumenti per lo sviluppo. Anche gli altri browser contengono gli strumenti per lo sviluppo, talvolta con caratteristiche speciali, ma più che altro giocano ad "avvicinarsi" a Chrome e Firefox.
1010
Quindi molte perone hanno un browser "preferito" e utilizzano gli altri solo quando un problema è specifico di quel browser.
1111

12-
Gli strumenti da sviluppatore sono potenti; hanno molte caratteristiche. Prima di tutto, dobbiamo capire come ottenerli, come cercare errori e come eseguire comandi JavaScript.
12+
Gli strumenti da sviluppatore sono molto potenti; possiedono molte caratteristiche. Prima di tutto, dobbiamo capire come accedervi, come cercare errori e come eseguire comandi JavaScript.
1313

1414
## Google Chrome
1515

1-js/03-code-quality/02-coding-style/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ Qui un esempio di di un file `.eslintrc`:
310310
},
311311
"rules": {
312312
"no-console": 0,
313-
"indent": ["warning", 2]
313+
"indent": 2
314314
}
315315
}
316316
```

1-js/04-object-basics/01-object/article.md

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,30 +87,6 @@ let user = {
8787
```
8888
Questa viene chiamata virgola di "trailing" ("trascinamento") o "hanging" ("sospensione"). Rende più facile l'aggiunzione/rimozione/spostamento delle proprietà, poiché tutte le righe risultano essere uguali.
8989

90-
````smart header="Gli oggetti const possono essere modificati"
91-
Da notare: un oggetto dichiarato come `const` *può* essere modificato.
92-
93-
Ad esempio:
94-
95-
```js run
96-
const user = {
97-
name: "John"
98-
};
99-
100-
*!*
101-
user.name = "Pete"; // (*)
102-
*/!*
103-
104-
alert(user.name); // Pete
105-
```
106-
107-
Potrebbe sembrare che la riga `(*)` causi un errore, ma non è cosi. Il `const` blocca il valore di `user`, ma non il suo contenuto.
108-
109-
Il `const` darà un errore solo se proviamo a riassegnare `user=...`.
110-
111-
C'è un altro modo per rendere costanti tutte le proprietà di un oggetto, andremo ad analizzarlo nel capitolo <info:property-descriptors>.
112-
````
113-
11490
## Parentesi quadre
11591

11692
Per le proprietà con nomi "multi-parola", l'accesso con notazione puntata non funziona:

1-js/04-object-basics/02-object-copy/article.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ admin.name = 'Pete'; // changed by the "admin" reference
7373
alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference
7474
```
7575
76-
7776
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.
7877
7978
## Comparison by reference
@@ -230,6 +229,30 @@ To fix that, we should use the cloning loop that examines each value of `user[ke
230229
231230
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).
232231
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* be modified.
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 no. 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, and that's all.
252+
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+
```
255+
233256
## Summary
234257
235258
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.

1-js/04-object-basics/07-optional-chaining/article.md

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,51 +9,89 @@ The optional chaining `?.` is a safe way to access nested object properties, eve
99

1010
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.
1111

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.
1313

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:
1517

1618
```js run
17-
let user = {}; // the user without "address" property
19+
let user = {}; // a user without "address" property
1820

1921
alert(user.address.street); // Error!
2022
```
2123

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").
2327

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.
2529

2630
```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
2933
```
3034

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.
3236

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:
40+
41+
```js
42+
let user = {};
43+
44+
alert(user.address ? user.address.street : undefined);
45+
```
46+
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.
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`:
52+
53+
```js
54+
let user = {}; // user has no address
55+
56+
alert(user.address ? user.address.street ? user.address.street.name : null : null);
57+
```
58+
59+
That's just awful, one may even have problems understanding such code.
60+
61+
Don't even care to, as there's a better way to write it, using the `&&` operator:
3462

3563
```js run
3664
let user = {}; // user has no address
3765

38-
alert( user && user.address && user.address.street ); // undefined (no error)
66+
alert( user.address && user.address.street && user.address.street.name ); // undefined (no error)
3967
```
4068

41-
AND'ing the whole path to the property ensures that all components exist (if not, the evaluation stops), but is cumbersome to write.
69+
AND'ing the whole path to the property ensures that all components exist (if not, the evaluation stops), but also isn't ideal.
70+
71+
As you can see, property names are still duplicated in the code. E.g. in the code above, `user.address` appears three times.
72+
73+
That's why the optional chaining `?.` was added to the language. To solve this problem once and for all!
4274

4375
## Optional chaining
4476

45-
The optional chaining `?.` stops the evaluation and returns `undefined` if the part before `?.` is `undefined` or `null`.
77+
The optional chaining `?.` stops the evaluation if the part before `?.` is `undefined` or `null` and returns that part.
4678

4779
**Further in this article, for brevity, we'll be saying that something "exists" if it's not `null` and not `undefined`.**
4880

49-
Here's the safe way to access `user.address.street`:
81+
In other words, `value?.prop`:
82+
- is the same as `value.prop` if `value` exists,
83+
- otherwise (when `value` is `undefined/null`) it returns `undefined`.
84+
85+
Here's the safe way to access `user.address.street` using `?.`:
5086

5187
```js run
5288
let user = {}; // user has no address
5389

5490
alert( user?.address?.street ); // undefined (no error)
5591
```
5692
93+
The code is short and clean, there's no duplication at all.
94+
5795
Reading the address with `user?.address` works even if `user` object doesn't exist:
5896
5997
```js run
@@ -65,14 +103,12 @@ alert( user?.address.street ); // undefined
65103
66104
Please note: the `?.` syntax makes optional the value before it, but not any further.
67105
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 `?.`.
71107
72108
```warn header="Don't overuse the optional chaining"
73109
We should use `?.` only where it's ok that something doesn't exist.
74110

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`.
76112

77113
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.
78114
```
@@ -84,7 +120,7 @@ If there's no variable `user` at all, then `user?.anything` triggers an error:
84120
// ReferenceError: user is not defined
85121
user?.address;
86122
```
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.
88124
````
89125

90126
## Short-circuiting
@@ -113,17 +149,20 @@ For example, `?.()` is used to call a function that may not exist.
113149
In the code below, some of our users have `admin` method, and some don't:
114150

115151
```js run
116-
let user1 = {
152+
let userAdmin = {
117153
admin() {
118154
alert("I am admin");
119155
}
120-
}
156+
};
121157

122-
let user2 = {};
158+
let userGuest = {};
159+
160+
*!*
161+
userAdmin.admin?.(); // I am admin
162+
*/!*
123163

124164
*!*
125-
user1.admin?.(); // I am admin
126-
user2.admin?.();
165+
userGuest.admin?.(); // nothing (no such method)
127166
*/!*
128167
```
129168

1-js/05-data-types/08-weakmap-weakset/article.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ let array = [ john ];
3030
john = null; // overwrite the reference
3131

3232
*!*
33-
// john is stored inside the array, so it won't be garbage-collected
33+
// the object previously referenced by john is stored inside the array
34+
// therefore it won't be garbage-collected
3435
// we can get it as array[0]
3536
*/!*
3637
```

1-js/06-advanced-functions/05-global-object/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var gVar = 5;
2424
alert(window.gVar); // 5 (diventa una proprietà dell'oggetto globale)
2525
```
2626

27-
Non affidatevi a questo! Questo comportamento esiste solamente per retrocompatibilità. Gli script moderni utilizzano i moduli JavaScript, che si comportano in maniera differente. Li studieremo più avanti nel capitolo [](info:modules).
27+
Non affidatevi a questo! Questo comportamento esiste solamente per retrocompatibilità. Gli script moderni utilizzano i moduli JavaScript, che si comportano in maniera differente. Li studieremo più avanti nel capitolo [moduli JavaScript](info:modules).
2828

2929
Inoltre, la dichiarazione di variabili in stile moderno, tramite `let` e `const` non hanno questo tipo di comportamento:
3030

1-js/06-advanced-functions/07-new-function/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ What if it could access the outer variables?
9292

9393
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.
9494

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.
9696

9797
So if `new Function` had access to outer variables, it would be unable to find renamed `userName`.
9898

1-js/08-prototypes/01-prototype-inheritance/article.md

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ In JavaScript, objects have a special hidden property `[[Prototype]]` (as named
1212

1313
![prototype](object-prototype-empty.svg)
1414

15-
The prototype is a little bit "magical". When we want to read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called "prototypal inheritance". Many cool language features and programming techniques are based on it.
15+
When we read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called "prototypal inheritance". And soon we'll study many examples of such inheritance, as well as cooler language features built upon it.
1616

1717
The property `[[Prototype]]` is internal and hidden, but there are many ways to set it.
1818

@@ -27,19 +27,11 @@ let rabbit = {
2727
};
2828

2929
*!*
30-
rabbit.__proto__ = animal;
30+
rabbit.__proto__ = animal; // sets rabbit.[[Prototype]] = animal
3131
*/!*
3232
```
3333

34-
```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`"
35-
Please note that `__proto__` is *not the same* as `[[Prototype]]`. It's a getter/setter for it.
36-
37-
It exists for historical reasons. In modern language it is replaced with functions `Object.getPrototypeOf/Object.setPrototypeOf` that also get/set the prototype. We'll study the reasons for that and these functions later.
38-
39-
By the specification, `__proto__` must only be supported by browsers, but in fact all environments including server-side support it. For now, as `__proto__` notation is a little bit more intuitively obvious, we'll use it in the examples.
40-
```
41-
42-
If we look for a property in `rabbit`, and it's missing, JavaScript automatically takes it from `animal`.
34+
Now if we read a property from `rabbit`, and it's missing, JavaScript will automatically take it from `animal`.
4335

4436
For instance:
4537

@@ -130,13 +122,28 @@ alert(longEar.jumps); // true (from rabbit)
130122

131123
![](proto-animal-rabbit-chain.svg)
132124

125+
Now if we read something from `longEar`, and it's missing, JavaScript will look for it in `rabbit`, and then in `animal`.
126+
133127
There are only two limitations:
134128

135129
1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle.
136130
2. The value of `__proto__` can be either an object or `null`. Other types are ignored.
137131

138132
Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others.
139133

134+
135+
```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`"
136+
It's a common mistake of novice developers not to know the difference between these two.
137+
138+
Please note that `__proto__` is *not the same* as the internal `[[Prototype]]` property. It's a getter/setter for `[[Prototype]]`. Later we'll see situations where it matters, for now let's just keep it in mind, as we build our understanding of JavaScript language.
139+
140+
The `__proto__` property is a bit outdated. It exists for historical reasons, modern JavaScript suggests that we should use `Object.getPrototypeOf/Object.setPrototypeOf` functions instead that get/set the prototype. We'll also cover these functions later.
141+
142+
By the specification, `__proto__` must only be supported by browsers. In fact though, all environments including server-side support `__proto__`, so we're quite safe using it.
143+
144+
As the `__proto__` notation is a bit more intuitively obvious, we use it in the examples.
145+
```
146+
140147
## Writing doesn't use prototype
141148
142149
The prototype is only used for reading properties.
@@ -198,8 +205,8 @@ alert(admin.fullName); // John Smith (*)
198205
// setter triggers!
199206
admin.fullName = "Alice Cooper"; // (**)
200207

201-
alert(admin.fullName); // Alice Cooper , state of admin modified
202-
alert(user.fullName); // John Smith , state of user protected
208+
alert(admin.fullName); // Alice Cooper, state of admin modified
209+
alert(user.fullName); // John Smith, state of user protected
203210
```
204211

205212
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.

1-js/08-prototypes/04-prototype-methods/article.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ alert(Object.keys(chineseDictionary)); // hello,bye
176176
Modern methods to set up and directly access the prototype are:
177177

178178
- [Object.create(proto, [descriptors])](mdn:js/Object/create) -- creates an empty object with a given `proto` as `[[Prototype]]` (can be `null`) and optional property descriptors.
179-
- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter).
180-
- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter).
179+
- [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter).
180+
- [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter).
181181

182182
The built-in `__proto__` getter/setter is unsafe if we'd want to put user-generated keys into an object. Just because a user may enter `"__proto__"` as the key, and there'll be an error, with hopefully light, but generally unpredictable consequences.
183183

0 commit comments

Comments
 (0)