diff --git a/1-js/02-first-steps/15-function-basics/article.md b/1-js/02-first-steps/15-function-basics/article.md index 4c6eaddd7..dee2a5a58 100644 --- a/1-js/02-first-steps/15-function-basics/article.md +++ b/1-js/02-first-steps/15-function-basics/article.md @@ -154,7 +154,7 @@ showMessage('Ann', "What's up?"); // Ann: What's up? (**) Quando la funzione viene chiamata nelle righe `(*)` e `(**)`, il valore passato viene copiato nelle variabili locali `from` e `text`, che verranno utilizzate nella chiamata ad `alert`. -Guardiamo un altro esempio: abbiamo una variabile `from` e la passiamo a una funzione. Da notare: la funzione cambia `from`, ma il cambiamento non è visibile all'esterno perchè la funzione usa sempre una copia del valore passato: +Guardiamo un altro esempio: abbiamo una variabile `from` e la passiamo a una funzione. Da notare: la funzione cambia `from`, ma il cambiamento non è visibile all'esterno perché la funzione usa sempre una copia del valore passato: ```js run @@ -232,7 +232,7 @@ function showMessage(text) { showMessage(); // empty message ``` -...Oppure utilizare l'operatore `||`: +...Oppure utilizzare l'operatore `||`: ```js function showMessage(from, text) { @@ -342,7 +342,7 @@ Per espressioni lunghe dopo la direttiva `return`, si potrebbe essere tentati da return (some + long + expression + or + whatever * f(a) + f(b)) ``` -Questo non funziona, perchè JavaScript interpreta un punto e virgola dopo `return`. E' come se dopo `return` ci fosse scritto: +Questo non funziona, perché JavaScript interpreta un punto e virgola dopo `return`. E' come se dopo `return` ci fosse scritto: ```js return*!*;*/!* @@ -370,7 +370,7 @@ Esempi di nomi: ```js no-beautify showMessage(..) // mostra un messaggio -getAge(..) // ritonra l'età (prendendola da qualche parte) +getAge(..) // ritorna l'età (prendendola da qualche parte) calcSum(..) // calcola la somma e ritorna il risultato createForm(..) // crea un form (e solitamente lo ritorna) checkPermission(..) // controlla i permessi, ritorna true/false @@ -397,14 +397,14 @@ Funzioni che vengono utilizzate *molto spesso* potrebbero avere nomi molto corti Ad esempio il framework [jQuery](http://jquery.com) definisce una funzione con `$`. La libreria [Lodash](http://lodash.com/) ha nel *core* una funzione denominata `_`. -Queste sono eccezioni. Generalmente i nomi delle funzioni sono precisi e descrittivi. +Queste sono eccezioni. Generalmente i nomi delle funzioni dovrebbero essere concisi e descrittivi. ``` ## Funzioni == Commenti Le funzioni dovrebbero essere brevi ed eseguire un solo compito. Se invece risultano lunghe, forse varrebbe la pena spezzarle in funzioni più piccole. Qualche volta può non essere semplice seguire questa regola, anche se sarebbe la cosa migliore. -Una funzione separata non è solo semplice da testare e debuggare -- la sua stessa esistenza è un commento! +Una funzione separata non è solo semplice da testare e correggere -- la sua stessa esistenza è un commento! Ad esempio, osserviamo le due funzioni `showPrimes(n)` sotto . Entrambe ritornano i [numeri primi](https://en.wikipedia.org/wiki/Prime_number) fino a `n`. diff --git a/1-js/03-code-quality/05-testing-mocha/article.md b/1-js/03-code-quality/05-testing-mocha/article.md index ab0811940..e117b8959 100644 --- a/1-js/03-code-quality/05-testing-mocha/article.md +++ b/1-js/03-code-quality/05-testing-mocha/article.md @@ -259,7 +259,7 @@ Il `describe` annidato definisce un nuovo "sotto-gruppo" di test. Nell'output po [iframe height=250 src="pow-4" edit border="1"] -In futuro potremmo aggiungere più `it` e `describe` allo stesso livello, ognugo di questi avrà le proprie funzioni di supporto ma non potranno vedere `makeTest`. +In futuro potremmo aggiungere più `it` e `describe` allo stesso livello, ognuno di questi avrà le proprie funzioni di supporto ma non potranno vedere `makeTest`. ````smart header="`before/after` and `beforeEach/afterEach`" Possiamo impostare le funzione `before/after` (prima/dopo) che vengono eseguite prima/dopo i test, o addirittura le funzioni `beforeEach/afterEach` (prima di ogni/dopo di ogni) che verranno eseguite prima di *ogni* `it`. diff --git a/1-js/03-code-quality/06-polyfills/article.md b/1-js/03-code-quality/06-polyfills/article.md index ff6b97ee4..e56c120a3 100644 --- a/1-js/03-code-quality/06-polyfills/article.md +++ b/1-js/03-code-quality/06-polyfills/article.md @@ -48,7 +48,7 @@ I moderni 'bundler' utilizzati per 'assemblare' progetti, come [webpack](http:// Nuove caratteristiche di un linguaggio possono riguardare, oltre alla sintassi, operatori e costrutti, anche funzioni integrate. -Ad esempio, `Math.trunc(n)` è una funziona che "tronca" la parte decimale di un numero, es. `Math.trunc(1.23) = 1`. +Ad esempio, `Math.trunc(n)` è una funziona che "tronca" la parte decimale di un numero, es. `Math.trunc(1.23)` ritorna `1`. In alcuni (vecchissimi) motori JavaScript, non esiste `Math.trunc`, quindi il codice non funzionerebbe. diff --git a/1-js/04-object-basics/04-object-methods/article.md b/1-js/04-object-basics/04-object-methods/article.md index a3a65a518..bec5a5e71 100644 --- a/1-js/04-object-basics/04-object-methods/article.md +++ b/1-js/04-object-basics/04-object-methods/article.md @@ -81,7 +81,7 @@ user = { // la sintassi più breve risulta più carina user = { *!* - sayHi() { // equivalente a "sayHi: function()" + sayHi() { // equivalente a "sayHi: function(){...}" */!* alert("Hello"); } diff --git a/1-js/05-data-types/08-weakmap-weakset/article.md b/1-js/05-data-types/08-weakmap-weakset/article.md index 9257ee5f6..737dc2ecf 100644 --- a/1-js/05-data-types/08-weakmap-weakset/article.md +++ b/1-js/05-data-types/08-weakmap-weakset/article.md @@ -6,7 +6,7 @@ Ad esempio: ```js let john = { name: "John" }; -// l'oggetto è accessibilie, john è un suo riferimento +// l'oggetto è accessibile, john è un suo riferimento // sovrascriviamo il riferimento john = null; @@ -99,7 +99,7 @@ Confrontiamolo con l'esempio di `Map` visto sopra. Ora, se `john` esiste solo co - `weakMap.delete(key)` - `weakMap.has(key)` -Perché questa limitazione? Per ragioni tecniche. Se un oggetto ha perso tutti i riferimenti (come `john` nel codice sopra), allora verrà automaticamente eliminato. Ma tecnicamente non è specificato esattamente *quando averrà la pulizia*. +Perché questa limitazione? Per ragioni tecniche. Se un oggetto ha perso tutti i riferimenti (come `john` nel codice sopra), allora verrà automaticamente eliminato. Ma tecnicamente non è specificato esattamente *quando avverrà la pulizia*. Sarà il motore JavaScript a deciderlo. Potrebbe decidere di effettuare subito la pulizia della memoria oppure aspettare più oggetti per eliminarli in blocco. Quindi, tecnicamente il numero degli elementi di una `WeakMap` non è conosciuto. Il motore potrebbe già aver effettuato la pulizia oppure no, o averlo fatto solo parzialmente. Per questo motivo, i metodi che accedono a `WeakMap` per intero non sopo supportati. @@ -120,7 +120,7 @@ weakMap.set(john, "secret documents"); Proviamo a guardare un esempio. -Immaginiamo di avere del codice che tiene nota del numero di visite per ogni utente. L'informazioni viene memorizzata in un map: l'utente è la chiave, mentre il conteggio delle visite è il valore. Quando l'utente esce, vogliamo smettere di mantenere in memoria il conteggio delle visite. +Immaginiamo di avere del codice che tiene nota del numero di visite per ogni utente. L'informazione viene memorizzata in un map: l'utente è la chiave, mentre il conteggio delle visite è il valore. Quando l'utente esce, vogliamo smettere di mantenere in memoria il conteggio delle visite. Qui vediamo un esempio di conteggio utilizzando `Map`: @@ -188,7 +188,7 @@ function process(obj) { } *!* -// Ora utilizzaimo process() in un altro file: +// Ora utilizziamo process() in un altro file: */!* // 📁 main.js @@ -205,7 +205,7 @@ obj = null; alert(cache.size); // 1 (Ouch! L'oggetto è ancora in cache, sta occupando memoria!) ``` -Per chiamate multiple di `process(obj)` con lo stesso oggetto, il risultato viene calcolato solamente la prima volta, le successive chiamate lo prenderanno dalla `cache`. Il lato negatico è che dobbiamo ricordarci di pulire la `cache` quando non è più necessaria. +Per chiamate multiple di `process(obj)` con lo stesso oggetto, il risultato viene calcolato solamente la prima volta, le successive chiamate lo prenderanno dalla `cache`. Il lato negativo è che dobbiamo ricordarci di pulire la `cache` quando non è più necessaria. Se sostituiamo `Map` con `WeakMap`, il problema si risolve. I risultati in cache vengono automaticamente rimossi una volta che l'oggetto viene ripulito dal garbage collector. @@ -232,10 +232,10 @@ let obj = {/* un oggetto */}; let result1 = process(obj); let result2 = process(obj); -// ...più tadi, quando non abbiamo più bisogno dell'oggetto +// ...più tardi, quando non abbiamo più bisogno dell'oggetto obj = null; -// Non possiamo ottenere la dimensione della cache, poichè è una WeakMap, +// Non possiamo ottenere la dimensione della cache, poiché è una WeakMap, // ma è 0 oppure lo sarà presto // Quando un oggetto viene ripulito dal garbage collector, anche i dati associati vengono ripuliti ``` diff --git a/1-js/05-data-types/09-keys-values-entries/article.md b/1-js/05-data-types/09-keys-values-entries/article.md index e45b41e04..3e3cc7af6 100644 --- a/1-js/05-data-types/09-keys-values-entries/article.md +++ b/1-js/05-data-types/09-keys-values-entries/article.md @@ -99,5 +99,5 @@ let doublePrices = Object.fromEntries( alert(doublePrices.meat); // 8 ``` -Ad un primo sguardo potrebbe risultare complesso, ma diventa molto più familiare dopo un paio di utilizzi. +Ad un primo sguardo potrebbe risultare complesso, ma diventa molto più familiare dopo un paio di utilizzi. In questo modo possono essere create potenti catene per la trasformazione. diff --git a/1-js/11-async/02-promise-basics/article.md b/1-js/11-async/02-promise-basics/article.md index 579637156..4d55aa87a 100644 --- a/1-js/11-async/02-promise-basics/article.md +++ b/1-js/11-async/02-promise-basics/article.md @@ -24,21 +24,19 @@ La funzione passata a `new Promise` è chiamata *esecutore (executor)*. Quando l I suoi argomenti `resolve` e `reject` sono delle callback fornite da JavaScript stesso. Il nostro codice sta solamente dentro l'esecutore. -![](promise-resolve-reject.svg) +- `resolve(value)` — se il processo termina correttamente, col risultato `value`. +- `reject(error)` — se si verifica un errore, `error` è l'oggetto errore. + +Ricapitolando: l'esecutore parte automaticamente e tenta di eseguire un compito. Quando l'esecuzione termina, viene invocato `resolve` in caso di successo, oppure `reject` in caso di errore. -L'oggetto `promise` risultante ha queste proprietà interne: +L'oggetto `promise` restituito ha le seguenti proprietà interne: -- `state` — inizialmente "pending", poi cambia con "fulfilled" o "rejected", -- `result` — un valore arbitrario di tua scelta, inizialmente `undefined`. +- `state` — inizialmente "pending", poi cambia in "fulfilled" se viene invocato `resolve` o in "rejected" se viene invocato `reject`. +- `result` — inizialmente `undefined`, poi cambia in `value` se viene invocato `resolve(value)` o in `error` se viene invocato `reject(error)`. -Quando l'esecutore finisce il lavoro (job), dovrebbe chiamare una delle funzioni che riceve come argomento: +Quindi l'esecutore, alla fine, mette la promise in uno di questi stati: -- `resolve(value)` — per indicare che il lavoro è finito con successo: - - imposta `state` come `"fulfilled"`, - - imposta `result` come `value`. -- `reject(error)` — per indicare che si è verificato un errore: - - imposta `state` come `"rejected"`, - - imposta `result` come `error`. +![](promise-resolve-reject.svg) Più avanti vedremo come questi cambiamenti diventano noti ai "fan". diff --git a/1-js/11-async/07-microtask-queue/article.md b/1-js/11-async/07-microtask-queue/article.md index 299ed54de..86601faaa 100644 --- a/1-js/11-async/07-microtask-queue/article.md +++ b/1-js/11-async/07-microtask-queue/article.md @@ -30,7 +30,7 @@ Come detto nella [specifica](https://tc39.github.io/ecma262/#sec-jobs-and-job-qu - La coda è primo-dentro-primo-fuori: i task messi in coda per primi sono eseguiti per primi. - L'esecuzione di un task è iniziata solo quando nient'altro è in esecuzione. -Oppure, per dirla in modo semplice, quando una promise è pronta, i suoi gestori `.then/catch/finally` sono messi nella coda. Non sono ancora eseguiti. Il motore JavaScript prende un task dalla coda e lo esegue, quando diventa libero dal codice corrente. +Oppure, per dirla in modo semplice, quando una promise è pronta, i suoi gestori `.then/catch/finally` sono messi nella coda. Non vengono ancora eseguiti. Il motore JavaScript prende un task dalla coda e lo esegue, quando diventa libero dal codice corrente. Questo è il motivo per cui "codice finito" nell'esempio sopra viene mostrato prima. @@ -40,7 +40,7 @@ I gestori delle promise passano sempre da quella coda interna. Se c'è una catena con diversi `.then/catch/finally`, allora ognuno di essi viene eseguito in modo asincrono. Cioè, viene prima messo in coda ed eseguito quando il codice corrente è completo e i gestori messi in coda precedentemente sono finiti. -**Che cosa succede se per noi l'ordine è importante? Come possiamo far funzionare `codice finito` dopo `promise completa`?** +**Che cosa succede se per noi l'ordine è importante? Come possiamo far funzionare `code finished` dopo `promise done`?** Facile, basta metterlo in coda con `.then`: diff --git a/1-js/12-generators-iterators/2-async-iterators-generators/article.md b/1-js/12-generators-iterators/2-async-iterators-generators/article.md index 6ee290ab9..d231eb411 100644 --- a/1-js/12-generators-iterators/2-async-iterators-generators/article.md +++ b/1-js/12-generators-iterators/2-async-iterators-generators/article.md @@ -353,6 +353,8 @@ Un esempio di utilizzo (visualizza gli autori delle commit nella console): } } })(); + +// Note: If you are running this in an external sandbox, you'll need to paste here the function fetchCommits described above ``` Questo è esattamente quello che volevamo. I meccanismi interni delle richieste paginate sono invisibili dall'esterno. Per noi non è altro che un generatore asincrono che ritorna delle commit. diff --git a/2-ui/1-document/10-size-and-scroll-window/article.md b/2-ui/1-document/10-size-and-scroll-window/article.md index 138812f75..02e96c091 100644 --- a/2-ui/1-document/10-size-and-scroll-window/article.md +++ b/2-ui/1-document/10-size-and-scroll-window/article.md @@ -73,6 +73,12 @@ alert('Scorrimento corrente da sinistra: ' + window.pageXOffset); Queste proprietà sono in sola lettura. +```smart header="`scrollX` e `scrollY` disponibili anche come proprietà di `window`" +Per ragioni storiche, esistono entrambe le proprietà, ma sono identiche: +- `window.pageXOffset` è un alias di `window.scrollX`. +- `window.pageYOffset` è un alias di `window.scrollY`. +``` + ## Lo scorrimento con scrollTo, scrollBy, scrollIntoView [#window-scroll] ```warn diff --git a/4-binary/03-blob/article.md b/4-binary/03-blob/article.md index a44308f6f..5031afa32 100644 --- a/4-binary/03-blob/article.md +++ b/4-binary/03-blob/article.md @@ -74,7 +74,7 @@ link.href = URL.createObjectURL(blob); We can also create a link dynamically in JavaScript and simulate a click by `link.click()`, then download starts automatically. -Here's the similar code that causes user to download the dynamicallly created `Blob`, without any HTML: +Here's the similar code that causes user to download the dynamically created `Blob`, without any HTML: ```js run let link = document.createElement('a'); @@ -186,7 +186,7 @@ let context = canvas.getContext('2d'); context.drawImage(img, 0, 0); // we can context.rotate(), and do many other things on canvas -// toBlob is async opereation, callback is called when done +// toBlob is async operation, callback is called when done canvas.toBlob(function(blob) { // blob ready, download it let link = document.createElement('a'); @@ -235,7 +235,7 @@ That makes Blobs convenient for upload/download operations, that are so common i Methods that perform web-requests, such as [XMLHttpRequest](info:xmlhttprequest), [fetch](info:fetch) and so on, can work with `Blob` natively, as well as with other binary types. -We can easily convert betweeen `Blob` and low-level binary data types: +We can easily convert between `Blob` and low-level binary data types: - We can make a Blob from a typed array using `new Blob(...)` constructor. - We can get back `ArrayBuffer` from a Blob using `FileReader`, and then create a view over it for low-level binary processing. diff --git a/5-network/11-websocket/article.md b/5-network/11-websocket/article.md index 12ac30a76..386e7c8eb 100644 --- a/5-network/11-websocket/article.md +++ b/5-network/11-websocket/article.md @@ -93,7 +93,7 @@ Sec-WebSocket-Version: 13 - `Origin` -- l'origine della pagina del client, ad esempio: `https://javascript.info`. Gli oggetti WebSocket sono per loro natura cross-origin. Non vi sono headers particolari o altre limitazioni. I server di vecchia data non gestiscono i WebSocket in nessun modo, quindi non ci sono problemi di compatibilità. Ma l'header `Origin` è importante, dal momento che permette al server di decidere se parlare o meno con quel sito. - `Connection: Upgrade` -- indica che il client vuole cambiare protocollo di comunicazione. - `Upgrade: websocket` -- il protocollo richiesto è "websocket". -- `Sec-WebSocket-Key` -- una chiave generata randomicamente dal browser per sicurezza. +- `Sec-WebSocket-Key` -- una chiave casuale generata dal browser per sicurezza. - `Sec-WebSocket-Version` -- versione di protocollo del WebSocket, 13 è quella corrente. ```smart header="L'handsnake del WebSocket non può essere emulato." diff --git a/6-data-storage/03-indexeddb/article.md b/6-data-storage/03-indexeddb/article.md index a4fb78c1e..7520c6e0e 100644 --- a/6-data-storage/03-indexeddb/article.md +++ b/6-data-storage/03-indexeddb/article.md @@ -95,7 +95,7 @@ openRequest.onupgradeneeded = function(event) { }; ``` -Please note: as our current version is `2`, `onupgradeneeded` handler has a code branch for version `0`, suitable for users that are accessing for the first time and have no database, and also for version `1`, for upgrades. +Please note: as our current version is `2`, the `onupgradeneeded` handler has a code branch for version `0`, suitable for users that are accessing for the first time and have no database, and also for version `1`, for upgrades. And then, only if `onupgradeneeded` handler finishes without errors, `openRequest.onsuccess` triggers, and the database is considered successfully opened. @@ -156,7 +156,7 @@ openRequest.onsuccess = function() { openRequest.onblocked = function() { // this event shouldn't trigger if we handle onversionchange correctly - // it means that there's another open connection to same database + // it means that there's another open connection to the same database // and it wasn't closed after db.onversionchange triggered for it }; */!* @@ -171,7 +171,7 @@ We can handle things more gracefully in `db.onversionchange`, prompt the visitor Or, an alternative approach would be to not close the database in `db.onversionchange`, but instead use the `onblocked` handler (in the new tab) to alert the visitor, tell him that the newer version can't be loaded until they close other tabs. -These update collisions happen rarely, but we should at least have some handling for them, at least `onblocked` handler, to prevent our script from dying silently. +These update collisions happen rarely, but we should at least have some handling for them, at least an `onblocked` handler, to prevent our script from dying silently. ## Object store @@ -189,7 +189,7 @@ An example of an object that can't be stored: an object with circular references **There must be a unique `key` for every value in the store.** -A key must be one of the these types - number, date, string, binary, or array. It's a unique identifier, so we can search/remove/update values by the key. +A key must be one of these types - number, date, string, binary, or array. It's a unique identifier, so we can search/remove/update values by the key. ![](indexeddb-structure.svg) @@ -253,7 +253,7 @@ db.deleteObjectStore('books') The term "transaction" is generic, used in many kinds of databases. -A transaction is a group operations, that should either all succeed or all fail. +A transaction is a group of operations, that should either all succeed or all fail. For instance, when a person buys something, we need to: 1. Subtract the money from their account. @@ -347,9 +347,9 @@ Usually, we can assume that a transaction commits when all its requests are comp So, in the example above no special call is needed to finish the transaction. -Transactions auto-commit principle has an important side effect. We can't insert an async operation like `fetch`, `setTimeout` in the middle of transaction. IndexedDB will not keep the transaction waiting till these are done. +Transactions auto-commit principle has an important side effect. We can't insert an async operation like `fetch`, `setTimeout` in the middle of a transaction. IndexedDB will not keep the transaction waiting till these are done. -In the code below, `request2` in line `(*)` fails, because the transaction is already committed, and can't make any request in it: +In the code below, `request2` in the line `(*)` fails, because the transaction is already committed, and can't make any request in it: ```js let request1 = books.add(book); @@ -370,7 +370,7 @@ That's because `fetch` is an asynchronous operation, a macrotask. Transactions a Authors of IndexedDB spec believe that transactions should be short-lived. Mostly for performance reasons. -Notably, `readwrite` transactions "lock" the stores for writing. So if one part of application initiated `readwrite` on `books` object store, then another part that wants to do the same has to wait: the new transaction "hangs" till the first one is done. That can lead to strange delays if transactions take a long time. +Notably, `readwrite` transactions "lock" the stores for writing. So if one part of the application initiated `readwrite` on `books` object store, then another part that wants to do the same has to wait: the new transaction "hangs" till the first one is done. That can lead to strange delays if transactions take a long time. So, what to do? @@ -792,7 +792,7 @@ await inventory.add({ id: 'js', price: 10, created: new Date() }); // Error The next `inventory.add` after `fetch` `(*)` fails with an "inactive transaction" error, because the transaction is already committed and closed at that time. -The workaround is same as when working with native IndexedDB: either make a new transaction or just split things apart. +The workaround is the same as when working with native IndexedDB: either make a new transaction or just split things apart. 1. Prepare the data and fetch all that's needed first. 2. Then save in the database. diff --git a/9-regular-expressions/05-regexp-multiline-mode/article.md b/9-regular-expressions/05-regexp-multiline-mode/article.md index d13997433..a103184bb 100644 --- a/9-regular-expressions/05-regexp-multiline-mode/article.md +++ b/9-regular-expressions/05-regexp-multiline-mode/article.md @@ -32,7 +32,13 @@ alert( str.match(/^\d+/g) ); // 1 */!* ``` -Questo accade perchè di base il comportamento del caret `pattern:^` trova corrispondenza solo con l'inizio del testo, mentre in modo multilinea trova -- con l'inizio di ogni riga. +Questo accade perché il comportamento default del caret `pattern:^` trova corrispondenza solo con l'inizio del testo, mentre in modalità multilinea trova all'inizio di ogni riga. + +```smart +"Inizio di linea" formalmente significa "immediatamente dopo un'interruzione di linea": il test `pattern:^` in modalità multilinea trova tutte le posizioni precedute dal carattere di nuova linea `\n`. + +And at the text start. +``` ## Fine linea $