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/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
@@ -9,7 +9,7 @@ Per poter visualizzare gli errori e ricevere altre informazioni utili riguardo g
9
9
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.
10
10
Quindi molte perone hanno un browser "preferito" e utilizzano gli altri solo quando un problema è specifico di quel browser.
11
11
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.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/01-object/article.md
-24Lines changed: 0 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,30 +87,6 @@ let user = {
87
87
```
88
88
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.
89
89
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
-
114
90
## Parentesi quadre
115
91
116
92
Per le proprietà con nomi "multi-parola", l'accesso con notazione puntata non funziona:
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/02-object-copy/article.md
+24-1Lines changed: 24 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,7 +73,6 @@ 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
76
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.
78
77
79
78
## Comparison by reference
@@ -230,6 +229,30 @@ To fix that, we should use the cloning loop that examines each value of `user[ke
230
229
231
230
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).
232
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* 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
+
233
256
## Summary
234
257
235
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.
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:
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/05-global-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
@@ -24,7 +24,7 @@ var gVar = 5;
24
24
alert(window.gVar); // 5 (diventa una proprietà dell'oggetto globale)
25
25
```
26
26
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).
28
28
29
29
Inoltre, la dichiarazione di variabili in stile moderno, tramite `let` e `const` non hanno questo tipo di comportamento:
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`.
Copy file name to clipboardExpand all lines: 1-js/08-prototypes/01-prototype-inheritance/article.md
+20-13Lines changed: 20 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@ In JavaScript, objects have a special hidden property `[[Prototype]]` (as named
12
12
13
13

14
14
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.
16
16
17
17
The property `[[Prototype]]` is internal and hidden, but there are many ways to set it.
```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`.
Now if we read something from `longEar`, and it's missing, JavaScript will look for it in `rabbit`, and then in `animal`.
126
+
133
127
There are only two limitations:
134
128
135
129
1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle.
136
130
2. The value of `__proto__` can be either an object or `null`. Other types are ignored.
137
131
138
132
Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others.
139
133
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
+
140
147
## Writing doesn't use prototype
141
148
142
149
The prototype is only used for reading properties.
@@ -198,8 +205,8 @@ alert(admin.fullName); // John Smith (*)
198
205
// setter triggers!
199
206
admin.fullName="Alice Cooper"; // (**)
200
207
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
203
210
```
204
211
205
212
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.
Modern methods to set up and directly access the prototype are:
177
177
178
178
-[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).
181
181
182
182
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.
0 commit comments