diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 0f1ea9a86..8bef36104 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -1,42 +1,42 @@ -# Optional chaining '?.' +# Concatenamento opzionale '?.' [recent browser="new"] -The optional chaining `?.` is a safe way to access nested object properties, even if an intermediate property doesn't exist. +Il concatenamento opzionale (optional chaining), `?.`, è un modo sicuro di accedere alle proprietà annidate di un oggetto, anche nel caso in cui una proprietà intermedia non dovesse esistere. -## The "non-existing property" problem +## Il problema della "proprietà inesistente" -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. +Se avete appena cominciato a leggere il tutorial e a imparare JavaScript, forse questo problema non lo avete ancora affrontato, ma è piuttosto comune. -As an example, let's say we have `user` objects that hold the information about our users. +Ad esempio, ipotizziamo di avere un oggetto `user`, in cui sono memorizzate le informazioni relative ai nostri utenti. -Most of our users have addresses in `user.address` property, with the street `user.address.street`, but some did not provide them. +La maggior parte dei nostri utenti possiedono l'indirizzo nella proprietà `user.address`, la via in `user.address.street`, ma qualcuno potrebbe non averle fornite. -In such case, when we attempt to get `user.address.street`, and the user happens to be without an address, we get an error: +In questo caso, quando proviamo ad accedere a `user.address.street`, e l'utente non possiede un indirizzo, otterremo un errore: ```js run -let user = {}; // a user without "address" property +let user = {}; // un utente senza la proprietà "address" -alert(user.address.street); // Error! +alert(user.address.street); // Errore! ``` -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. +Questo è il risultato che ci si aspetta. JavaScript funziona in questo modo. Se `user.address` è `undefined`, un tentativo di accesso a `user.address.street` fallirà con un errore. -In many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street"). +Nella maggior parte dei casi, preferiremmo avere `undefined` piuttosto di un errore (con il significato "nessuna via"). -...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. +... Un altro esempio. Il metodo `document.querySelector('.elem')` ritorna un oggetto che corrisponde ad un elemento della pagina web, che ritorna `null` quando l'elemento non esite. ```js run -// document.querySelector('.elem') is null if there's no element -let html = document.querySelector('.elem').innerHTML; // error if it's null +// document.querySelector('.elem') è null se non esiste l'elemento +let html = document.querySelector('.elem').innerHTML; // errore se è null ``` -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. +Di nuovo, se un elemente non esiste, otterremo un errore nel tentativo di accedere a `.innerHTML` di `null`. In alcuni casi, in cui l'assenza di un elemento è normale, vorremo evitare l'errore e accettare come risultato `html = null`. -How can we do this? +Come possiamo farlo? -The obvious solution would be to check the value using `if` or the conditional operator `?`, before accessing its property, like this: +La soluzione più ovvia sarebbe di controllare il valore utilizzando `if` o l'operatore condizionale `?`, prima di accedere alle proprietà, come nell'esempio: ```js let user = {}; @@ -44,55 +44,55 @@ let user = {}; alert(user.address ? user.address.street : undefined); ``` -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. +Funziona, nessun errore... Ma è poco elegante. Come potete vedere , `"user.address"` appare due volte nel codice. Per proprietà molto più annidate, potrebbe diventare un problema, in quanto saranno necessarie molte più ripetizioni. -E.g. let's try getting `user.address.street.name`. +Ad esempio, proviamo a recuperare il valore di `user.address.street.name`. -We need to check both `user.address` and `user.address.street`: +Dobbiamo verificare sia `user.address` che `user.address.street`: ```js -let user = {}; // user has no address +let user = {}; // l'utente non ha address alert(user.address ? user.address.street ? user.address.street.name : null : null); ``` -That's just awful, one may even have problems understanding such code. +Questo è semplicemente terribile, un codice del genere potrebbe essere difficile da comprendere. -Don't even care to, as there's a better way to write it, using the `&&` operator: +Ci sarebbe un modo migliore per riscriverlo, utilizzando l'operatore `&&`: ```js run -let user = {}; // user has no address +let user = {}; // l'utente non ha address -alert( user.address && user.address.street && user.address.street.name ); // undefined (no error) +alert( user.address && user.address.street && user.address.street.name ); // undefined (nessune errore) ``` -AND'ing the whole path to the property ensures that all components exist (if not, the evaluation stops), but also isn't ideal. +Concatenare con `&&` l'intero percorso verso la proprietà ci assicura che tutti i componenti esistano (in caso contrario, la valutazione si interrompe), ma non è comunque l'ideale. -As you can see, property names are still duplicated in the code. E.g. in the code above, `user.address` appears three times. +Come potete vedere, il nome della proprietà è ancora duplicato nel codice. Ad esempio, nel codice sopra, `user.address` è ripetuto tre volte. -That's why the optional chaining `?.` was added to the language. To solve this problem once and for all! +Questo è il motivo per cui la concatenazione opzionale `?.` è stata aggiunta al linguaggio. Per risolvere questo problema una volta per tutte! -## Optional chaining +## Concatenazione opzionale -The optional chaining `?.` stops the evaluation if the value before `?.` is `undefined` or `null` and returns `undefined`. +La concatenazione opzionale `?.` interrompe la valutazione se il valore prima di `?.` è `undefined` o `null`, e ritorna `undefined`. -**Further in this article, for brevity, we'll be saying that something "exists" if it's not `null` and not `undefined`.** +**D'ora in poi in questo articolo, per brevità, diremo che qualcosa "esiste" se non è ne `null` né `undefined`.** -In other words, `value?.prop`: -- works as `value.prop`, if `value` exists, -- otherwise (when `value` is `undefined/null`) it returns `undefined`. +In altre parole, `value?.prop`: +- funziona come `value.prop`, se `value` esiste, +- altrimenti (quando `value` è `undefined/null`) ritorna `undefined`. -Here's the safe way to access `user.address.street` using `?.`: +Vediamo un modo sicuro per accedere a `user.address.street` utilizzando `?.`: ```js run -let user = {}; // user has no address +let user = {}; // user non possiede l'address -alert( user?.address?.street ); // undefined (no error) +alert( user?.address?.street ); // undefined (nessun errore) ``` -The code is short and clean, there's no duplication at all. +Il codice è corto e pulito, non c'è alcuna duplicazione. -Reading the address with `user?.address` works even if `user` object doesn't exist: +Leggendo l'indirizzo con `user?.address` funzionerebbe anche se l'oggetto `user` non esistesse: ```js run let user = null; @@ -101,52 +101,52 @@ alert( user?.address ); // undefined alert( user?.address.street ); // undefined ``` -Please note: the `?.` syntax makes optional the value before it, but not any further. +Da notare: la sintassi `?.` rende opzionale il valore che la precede, nulla di più. -E.g. in `user?.address.street.name` the `?.` allows `user` to safely be `null/undefined` (and returns `undefined` in that case), but that's only for `user`. 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 `?.`. +Ad esempio in `user?.address.street.name` il costrutto `?.` permette alla proprietà `user` di essere `null/undefined` in sicurezza (e ritornare `undefined` in questo caso), ma questo vale solamente per `user`. Si accederà alle altre proprietà normalmente. Se vogliamo che anche altre proprietà siano opzionali, dobbiamo rimpiazzare `.` con `?.`. -```warn header="Don't overuse the optional chaining" -We should use `?.` only where it's ok that something doesn't exist. +```warn header="Non abusate della concatenazione opzionale" +Dovremmo utilizzare `?.` solamente quando va bene che una proprietà possa non esistere. -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`. +Ad esempio, considerando la logica del nostro codice, l'oggetto `user` deve necessariamente esistere, mentre `address` è opzionale, quindi dovremmo scrivere `user.address?.street`, non `user?.address?.street`. -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. +Quindi, se `user` dovesse essere `undefined` per errore, otterremo un errore e potremmo sistemarlo. Altrimenti, gli errori di programmazione potrebbero essere silenziati in modo non appropriato, rendendo il debug molto difficile. ``` -````warn header="The variable before `?.` must be declared" -If there's no variable `user` at all, then `user?.anything` triggers an error: +````warn header="La variabile che precede `?.` deve essere dichiarata" +Se non esiste alcuna variabile `user`, allora `user?.anything` provocherà un errore: ```js run // ReferenceError: user is not defined user?.address; ``` -The variable must be declared (e.g. `let/const/var user` or as a function parameter). The optional chaining works only for declared variables. +La variabile deve essere dichiarata (ad esempio come `let/const/var user` o come parametro di funzione). La concatenazione opzionale funziona solamente con le variabili dichiarate. ```` -## Short-circuiting +## Corto circuito -As it was said before, the `?.` immediately stops ("short-circuits") the evaluation if the left part doesn't exist. +Come detto in precedenza, il costrutto `?.` interrompe immediatamente (manda in "corto circuito") la valutazione se la proprietà a destra non esiste. -So, if there are any further function calls or side effects, they don't occur. +Quindi, nel caso ci siano ulteriori chiamate a funzione o side-effects, questi non verranno elaborati. -For instance: +Ad esempio: ```js run let user = null; let x = 0; -user?.sayHi(x++); // no "sayHi", so the execution doesn't reach x++ +user?.sayHi(x++); // non esiste "sayHi", quindi l'esecuzione non raggiungerà x++ -alert(x); // 0, value not incremented +alert(x); // 0, valore non incrementato ``` -## Other variants: ?.(), ?.[] +## Altre varianti: ?.(), ?.[] -The optional chaining `?.` is not an operator, but a special syntax construct, that also works with functions and square brackets. +La concatenazione opzionale `?.` non è un operatore, ma uno speciale costrutto sintattico, che funziona anche con le funzioni e le parentesi quadre. -For example, `?.()` is used to call a function that may not exist. +Ad esempio, `?.()` viene utilizzato per invocare una funzione che potrebbe non esistere. -In the code below, some of our users have `admin` method, and some don't: +Nel codice sotto, alcuni dei nostri utenti possiedono il metodo `admin`, mentre altri no: ```js run let userAdmin = { @@ -162,15 +162,15 @@ userAdmin.admin?.(); // I am admin */!* *!* -userGuest.admin?.(); // nothing (no such method) +userGuest.admin?.(); // niente (il metodo non esiste) */!* ``` -Here, in both lines we first use the dot (`user1.admin`) to get `admin` property, because the user object must exist, so it's safe read from it. +Qui, in entrambe le righe, come prima cosa abbiamo utilizzato il punto (`user1.admin`) per ottenere la proprietà `admin`, poiché l'oggetto `user` deve necessariamente esistere, quindi l'accesso è sicuro. -Then `?.()` checks the left part: if the admin function exists, then it runs (that's so for `user1`). Otherwise (for `user2`) the evaluation stops without errors. +Successivamente `?.()` controlla la parte sinistra: se la funzione `admin` esiste, allora viene eseguita (ciò che accade con `user1`). Altrimenti (con `user2`) la valutazione si interrompe senza errori. -The `?.[]` syntax also works, if we'd like to use brackets `[]` to access properties instead of dot `.`. Similar to previous cases, it allows to safely read a property from an object that may not exist. +La sintassi `?.` funziona anche con le parentesi `[]` (invece del punto `.`). Come nei casi precedenti, possiamo accedere con sicurezza ad una proprietà di un oggetto che potrebbe non esistere. ```js run let key = "firstName"; @@ -185,36 +185,36 @@ alert( user1?.[key] ); // John alert( user2?.[key] ); // undefined ``` -Also we can use `?.` with `delete`: +Possiamo anche utilizzare `?.` con `delete`: ```js run -delete user?.name; // delete user.name if user exists +delete user?.name; // cancella user.name se l'utente esiste ``` -````warn header="We can use `?.` for safe reading and deleting, but not writing" -The optional chaining `?.` has no use at the left side of an assignment. +````warn header="Possiamo utilizzare `?.` per l'accesso e la rimozione sicura, ma non per la scrittura" +La concatenazione opzionale `?.` non ha alcun significato alla sinistra di un'assegnazione. -For example: +Ad esempio: ```js run let user = null; -user?.name = "John"; // Error, doesn't work -// because it evaluates to undefined = "John" +user?.name = "John"; // Errore, non funziona +// poiché valuta undefined = "John" ``` -It's just not that smart. +Non è cosi intelligente. ```` -## Summary +## Riepilogo -The optional chaining `?.` syntax has three forms: +La concatenazione opzionale `?.` ha tre forme: -1. `obj?.prop` -- returns `obj.prop` if `obj` exists, otherwise `undefined`. -2. `obj?.[prop]` -- returns `obj[prop]` if `obj` exists, otherwise `undefined`. -3. `obj.method?.()` -- calls `obj.method()` if `obj.method` exists, otherwise returns `undefined`. +1. `obj?.prop` -- ritorna `obj.prop` se `obj` esiste, altrimenti ritorna `undefined`. +2. `obj?.[prop]` -- ritorna `obj[prop]` se `obj` esiste, altrimenti ritorna `undefined`. +3. `obj.method?.()` -- invoca `obj.method()` se `obj.method` esiste, altrimenti ritorna `undefined`. -As we can see, all of them are straightforward and simple to use. The `?.` checks the left part for `null/undefined` and allows the evaluation to proceed if it's not so. +Come possiamo vedere, le tre forme sono semplici da utilizzare. Il costrutto `?.` verifica che la parte sinistra non sia `null/undefined`; se non lo è, permette alla valutazione di proseguire, altrimenti interrompe immediatamente la valutazione. -A chain of `?.` allows to safely access nested properties. +La concatenazione di `?.` permette di accedere in sicurezza a proprietà annidate. -Still, we should apply `?.` carefully, only where it's acceptable that the left part doesn't exist. So that it won't hide programming errors from us, if they occur. +In ogni caso, dovremmo applicare `?.` con prudenza, solamente nei casi in cui è accettabile che la parte sinistra possa non esistere. In questo modo evitiamo di nascondere errori di programmazione, nel caso ce ne siano.