diff options
author | Divay Prakash <divayprakash@users.noreply.github.com> | 2019-12-23 23:14:50 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-12-23 23:14:50 +0530 |
commit | 16dc074e39f5f996639f23f4d6812c211ae5d22d (patch) | |
tree | 63be0d1a3885201f3d13f1dc00266fb719f304a7 /it-it/javascript-it.html.markdown | |
parent | ffd1fed725668b48ec8c11cbe419bd1e8d136ae3 (diff) | |
parent | 1d5f3671ea4bc6d7a70c3026c1ae6857741c50a6 (diff) |
Merge branch 'master' into master
Diffstat (limited to 'it-it/javascript-it.html.markdown')
-rw-r--r-- | it-it/javascript-it.html.markdown | 617 |
1 files changed, 617 insertions, 0 deletions
diff --git a/it-it/javascript-it.html.markdown b/it-it/javascript-it.html.markdown new file mode 100644 index 00000000..68bf6287 --- /dev/null +++ b/it-it/javascript-it.html.markdown @@ -0,0 +1,617 @@ +--- +language: javascript +contributors: + - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Ariel Krakowski", "http://www.learneroo.com"] +translators: + - ["vinniec", "https://github.com/vinniec"] +filename: javascript-it.js +lang: it-it +--- + +JavaScript è stato creato da Netscape di Brendan Eich nel 1995. È stato originariamente pensato come un semplice linguaggio di scripting per i siti web, complementare all'uso di java per applicazioni più complesse ma la sua stretta integrazione con le pagine Web e il supporto integrato con esse ha causato il suo divenire più comune di Java per i frontend web. + +Tuttavia JavaScript non è semplicemente limitato ai web browser: Node.js è un progetto che fornisce una runtime standalone dell'engine JavaScript V8 per Google Chrome, sta diventando sempre più popolare. + +JavaScript ha una sintassi C-like, quindi se usate linguaggi come C o Java, molta della sintassi di base sarà già familiare. A dispetto di questo, e a dispetto del nome similare, il modello a oggetti di JavaScript è significativamente diverso da quello di Java. + +```js +// I commenti a singola linea iniziano con due slash. +/* I commenti multilinea cominciano con uno slash e un asterisco, + e terminano con un asterisco e uno slash */ + +// Le istruzioni possono essere terminate con ; +doStuff(); + +// ... ma non devono esserci per forza, i punti e virgola vengono automaticamente inseriti +// dove c'è un newline, ad eccezione di alcuni casi. +doStuff() + +// Poiché questi casi possono causare risultati inaspettati, noi continueremo ad usare +// i punti e virgola in questa guida. + +/////////////////////////////////// +// 1. Numeri, Stringe e Operatori + +// JavaScript ha un tipo numero (che è a 64-bit IEEE 754 double). +// Double ha una mantissa di 52-bit che è abbastanza per memorizzare interi +// fino a 9x10¹⁵ per essere precisi. +3; // = 3 +1.5; // = 1.5 + +// Alcuni lavori aritmetici di base come ci si può aspettare. +1 + 1; // = 2 +0.1 + 0.2; // = 0.30000000000000004 +8 - 1; // = 7 +10 * 2; // = 20 +35 / 5; // = 7 + +// inclusa la divisione con la virgola. +5 / 2; // = 2.5 + +// E il modulo. +10 % 2; // = 0 +30 % 4; // = 2 +18.5 % 7; // = 4.5 + +// Anche le operazioni binarie funzionano; quando effettuate una operazione binaria il vostro numero decimale +// è convertito in un intero con segno *fino a* 32 bit.. +1 << 2; // = 4 + +// Le precedenza è subordinata dalle parentesi. +(1 + 3) * 2; // = 8 + +// Ci sono tre valori speciali che non sono numeri reali: +Infinity; // ad esempio il risultato di 1/0 +-Infinity; // ad esempio il risultato di -1/0 +NaN; // ad esempio il risultato di 0/0, sta per 'Not a Number' + +// Ci sono anche i tipi booleani. +true; +false; + +// Le stringe sono create con ' oppure ". +'abc'; +"Hello, world"; + +// La negazione usa il ! simbolo +!true; // = false +!false; // = true + +// L'uguaglianza è === +1 === 1; // = true +2 === 1; // = false + +// L'inuguaglianza è !== +1 !== 1; // = false +2 !== 1; // = true + +// Altre comparazioni +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true + +// Le stringhe si concatenano con il + +"Hello " + "world!"; // = "Hello world!" + +// ... che funziona con qualcosa in più delle semplici stringhe +"1, 2, " + 3; // = "1, 2, 3" +"Hello " + ["world", "!"]; // = "Hello world,!" + +// e sono comparate con < e > +"a" < "b"; // = true + +// La comparazione con conversione implicita si fa con il doppio uguale... +"5" == 5; // = true +null == undefined; // = true + +// ...ammenoché non si usi === +"5" === 5; // = false +null === undefined; // = false + +// ...che può provocare strani comportamenti... +13 + !0; // 14 +"13" + !0; // '13true' + +// Si può accedere ai caratteri di una stringa con `charAt` +"This is a string".charAt(0); // = 'T' + +// ...o usando le `substring` per ottenere una parte. +"Hello world".substring(0, 5); // = "Hello" + +// `length` è una proprietà, quindi non usate le (). +"Hello".length; // = 5 + +// Ci sono anche `null` e `undefined`. +null; // usato per indicato deliberatamente un non-valore +undefined; // usato per indicare un valore che attualmente non è presente (sebbene + // `undefined` sia un valore a sua stessa volta) + +// false, null, undefined, NaN, 0 e "" sono falsi; tutto il resto è vero. +// Notare che 0 è falso e "0" è vero, nonostante 0 == "0". + +/////////////////////////////////// +// 2. Variabili, Array e Oggetti + +// Le variabili sono dichiarate con la parola chiave `var`. JavaScript è tipato +// dinamicamente, quindi non serve specificare il tipo. L'assegnamento usa un carattere `=` +// singolo. +var someVar = 5; + +// Se si toglie la parola chiave var non si otterrà un errore... +someOtherVar = 10; + +// ...ma la tua variabile sarà creata con visibilità globale e non +// nel blocco dove la si è definita. + +// Le variabili dichiarate senza essere definite vengono impostate come undefined. +var someThirdVar; // = undefined + +// Se si vuole dichiarare una coppia di variabili, lo si può fare usando una virgola +// come separatore +var someFourthVar = 2, someFifthVar = 4; + +// C'è una scorciatoia per effettuare operazioni matematiche sulle variabili: +someVar += 5; // equivalente di someVar = someVar + 5; someVar vale 10 ora +someVar *= 10; // ora someVar è 100 + +// e un ulteriore scorciatoia per aggiungere o sottrarre 1 +someVar++; // ora someVar è 101 +someVar--; // di nuovo 100 + +// Gli array sono liste ordinati di valori, di qualsiasi tipo. +var myArray = ["Hello", 45, true]; + +// Si può accedere ai loro membri usando la sintassi sottoscritta con le parentesi quadra. +// Gli indici degli array iniziano a zero. +myArray[1]; // = 45 + +// Gli Array sono mutabili e di dimensione variabile. +myArray.push("World"); +myArray.length; // = 4 + +// Aggiungere/Modificare in un indice preciso +myArray[3] = "Hello"; + +// Aggiungere e rimovere un elemento dall'inizio o dalla fine di un array +myArray.unshift(3); // Aggiungere come primo elemento +someVar = myArray.shift(); // Rimuovere il primo elemento e restituirlo +myArray.push(3); // Aggiungere come ultimo elemento +someVar = myArray.pop(); // Rimuovere l'ultimo elemento e restituirlo + +// Unire tutti gli elementi di un array con un punto e virgola +var myArray0 = [32,false,"js",12,56,90]; +myArray0.join(";") // = "32;false;js;12;56;90" + +// Ottenere un subarray di elementi dall'indice 1 (incluso) al 4 (escluso) +myArray0.slice(1,4); // = [false,"js",12] + +// Rimuovere 4 elementi partendo dall'indice 2 e inserirci delle stringhe +// "hi","wr" e "ld"; restituiscono i subarray rimossi +myArray0.splice(2,4,"hi","wr","ld"); // = ["js",12,56,90] +// myArray0 === [32,false,"hi","wr","ld"] + +// Gli oggetti di JavaScript sono equivalenti ai "dizionari" o "mappe" in altri +// linguaggi: una collezione non ordinata di coppie di chiave-valore. +var myObj = {key1: "Hello", key2: "World"}; + +// Le chiavi sono stringhe, ma non è necessario quotarle se sono identificatori +// JavaScript validi. I valori possono essere di ogni tipo. +var myObj = {myKey: "myValue", "my other key": 4}; + +// Gli attributi degli oggetti possono essere acceduti usando la sintassi "subscript", +myObj["my other key"]; // = 4 + +// ... o usando la notazione puntata fornendo una chiave che sia un identificatore valido. +myObj.myKey; // = "myValue" + +// Gli oggetti sono mutabilil; i valori possono essere cambiati e nuove chiavi possono essere aggiunte. +myObj.myThirdKey = true; + +// se si prova ad accedere ad un valore che non è stato ancora impostato, si otterrà undefined. +myObj.myFourthKey; // = undefined + +/////////////////////////////////// +// 3. Strutture logiche e di controllo. + +// La struttura `if` funziona come ci si aspetta. +var count = 1; +if (count == 3){ + // eseguito se count vale 3 +} else if (count == 4){ + // eseguito se count vale 4 +} else { + // eseguito se count non è né 3 e né 4 +} + +// Così come il `while`. +while (true){ + // Un ciclo infinito! +} + +// I cicli do-while sono come i cicli while ad eccezione che loro iterano almeno una volta. +var input; +do { + input = getInput(); +} while (!isValid(input)); + +// Il ciclo `for` è lo stesso di C e di Java: +// inizializzazione, condizione di proseguimento; iterazione. +for (var i = 0; i < 5; i++){ + // verrà eseguito 5 volte +} + +// Uscire forzatamente da un un ciclo etichettato è simile a java: +outer: +for (var i = 0; i < 10; i++) { + for (var j = 0; j < 10; j++) { + if (i == 5 && j ==5) { + break outer; + // esce fuori dal ciclo outer invece che solo da quello più interno + } + } +} + +// L'istruzione for/in permette l'iterazione sulle proprietà di un oggetto. +var description = ""; +var person = {fname:"Paul", lname:"Ken", age:18}; +for (var x in person){ + description += person[x] + " "; +} // description = 'Paul Ken 18 ' + +// L'istruzione for/of permette l'iterazione su oggetti iterabili (inclusi i built-in String, +// Array, es. gli argomenti Array-like o gli oggetti NodeList, TypedArray, Map e Set, +// e gli iterabili decisi dall'utente). +var myPets = ""; +var pets = ["cat", "dog", "hamster", "hedgehog"]; +for (var pet of pets){ + myPets += pet + " "; +} // myPets = 'cat dog hamster hedgehog ' + +// && è la congiunzione logica, || è la disgiunione logica +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear"; +} +if (colour == "red" || colour == "blue"){ + // i colori sono sia rossi che blu +} + +// && e || "short circuit", utili per impostare i valori di default. +var name = otherName || "default"; + +// L'istruzione `switch` controlla l'uguaglianza con `===`. +// Usare 'break' dopo ogni caso +// oppure i casi dopo quello corretto verranno eseguiti comunque. +grade = 'B'; +switch (grade) { + case 'A': + console.log("Great job"); + break; + case 'B': + console.log("OK job"); + break; + case 'C': + console.log("You can do better"); + break; + default: + console.log("Oy vey"); + break; +} + + +/////////////////////////////////// +// 4. Funzioni, Visibilità e Closure + +// Le funzioni di JavaScript sono dichiarate con la parolachiave `function`. +function myFunction(thing){ + return thing.toUpperCase(); +} +myFunction("foo"); // = "FOO" + +// Nota che il valore da restituire deve iniziare nella stessa riga della +// keyword `return`, altrimenti verrà sempre restituito `undefined` per via due to +// dell'inserimento automatico dei punti e virgola. Fare attenzione a questo quando si usa lo stile Allman. +function myFunction(){ + return // <- punto e virgola automaticamente inserito qui + {thisIsAn: 'object literal'}; +} +myFunction(); // = undefined + +// Le funzioni di JavaScript sono oggetti di prima classe, quindi possono essere riassegnate +// a diversi nomi di variabili e passate ad altre funzioni come argomenti - per esempio, +// mentre si fornisce un gestore di eventi: +function myFunction(){ + // questo codice sarà chiamato in 5 secondi +} +setTimeout(myFunction, 5000); +// Nota: setTimeout non è parte del linguaggio JS, ma è fornito dai browser +// e da Node.js. + +// Un altra funzione fornita dai browser è setInterval +function myFunction(){ + // questo codice verrà chiamato ogni 5 secondi +} +setInterval(myFunction, 5000); + +// Gli oggetti funzione non devono essere dichiarati con un nome - potete scrivere +// la definizione di una funzione anonima direttamente come argomento di un'altra. +setTimeout(function(){ + // questo codice sarà chiamato in 5 secondi +}, 5000); + +// In JavaScript le funzioni hanno una propria visibilità; le funzioni hanno +// il loro scope ma gli altri blocchi no. +if (true){ + var i = 5; +} +i; // = 5 - non è undefined come ci si potrebbe aspettare in un linguaggio con una propria visibilità per blocco + +// Questo ha portato ad un pattern comune di "esecuzione immediata di funzioni +// anonime", che previene alle variabili temporanee di finire nella +// visibilità globale. +(function(){ + var temporary = 5; + // Noi possiamo accedere alla visibilità globale assegnando all' "oggetto globale", che + // in un browser web è sempre `windows`. L'oggetto globale potrebbe avere + // nomi differenti in ambienti diverso dal browser come Node.js. + window.permanent = 10; +})(); +temporary; // solleva ReferenceError +permanent; // = 10 + +// Una delle più potenti caratteristiche di javascript sono le closure. Se una funzione è +// definita dentro un'altra funzione, la funzione interna ha accesso a le variabili +// della funzione esterna, anche dopo essere uscita dalla funzione esterna. +function sayHelloInFiveSeconds(name){ + var prompt = "Hello, " + name + "!"; + // Le funzioni interne sono messe nella visibilità locale in modo predefinito, anche se vengono + // dichiarate con `var`. + function inner(){ + alert(prompt); + } + setTimeout(inner, 5000); + // setTimeout è asincrono, quindi la funzione sayHelloInFiveSeconds + // esce immediatamente e setTimeout chiamera inner successivamente. Tuttavia, + // poiché inner è "chiuso prima" di sayHelloInFiveSeconds, inner ha ancora + // accesso alla variabile `prompt` quando viene finalmente richiamato. +} +sayHelloInFiveSeconds("Adam"); // aprirà un popup con "Hello, Adam!" in 5s + +/////////////////////////////////// +// 5. Di più sugli oggetti, costruttori e prototipi. + +// Gli oggetti possono contenere funzioni. +var myObj = { + myFunc: function(){ + return "Hello world!"; + } +}; +myObj.myFunc(); // = "Hello world!" + +// Quando una funzione contenuta in un oggetto viene chiamata, essa può accedere a questo oggetto +// possono farlo usando la parola chiave `this`. +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString; + } +}; +myObj.myFunc(); // = "Hello world!" + +// Questo ha a che fare con come la funzione è chiamata, non con dove +// è definita. Quindi, la nostra funzione non funziona se non è chiamata +// nel contesto dell'oggetto. +var myFunc = myObj.myFunc; +myFunc(); // = undefined + +// Al contrario, una funzione può essere assegnata ad un oggetto e poi accedere ad esso +// attraverso `this`, anche se non è stata inserita durante la definizione. +var myOtherFunc = function(){ + return this.myString.toUpperCase(); +}; +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!" + +// Possiamo anche specificare un contesto per una funzione da eseguire quando la invochiamo +// usando `call` o `apply`. + + +var anotherFunc = function(s){ + return this.myString + s; +}; +anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" + +// La funzione `apply` è quasi identica, ma prende un array come lista +// di argomenti. + +anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" + +// Questo è utile quanso si lavora con una funzione che accetta una sequenza di +// argomenti e si vuole passare un array. + +Math.min(42, 6, 27); // = 6 +Math.min([42, 6, 27]); // = NaN (uh-oh!) +Math.min.apply(Math, [42, 6, 27]); // = 6 + +// Ma, `call` e `apply` sono solo temporanei. Quando vogliamo incollarli, possiamo +// usare `bind` + +var boundFunc = anotherFunc.bind(myObj); +boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" + +// `bind` può essere anche usato per applicare parzialmente (curry) una funzione. + +var product = function(a, b){ return a * b; }; +var doubler = product.bind(this, 2); +doubler(8); // = 16 + +// Quando si chiama una funzione con la parola chiave `new`, un nuovo oggetto viene creato +// e reso disponibile alla funzione attraverso la parola chiave `this`. Le funzioni progettate per essere +// invocate in questo modo sono chiamate costruttrici. + +var MyConstructor = function(){ + this.myNumber = 5; +}; +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5 + +// Diversamente dalla molti degli altri linguaggi orientati agli oggetti, Javascript non ha +// il concetto di 'istanze' create sull'impronta di una 'classe'; invece Javascript +// combina l'instanziamento e l'ereditarietà in un singolo concetto: il 'prototipo'. + +// Ogni oggetto Javascript ha un 'prototipo'. Quando si cerca di accedere a una proprietà +// su un oggetto che non la contiene, l'interprete +// guarderà i suoi prototipi. + +// Alcune implementazioni di JS faranno accedere al propotipo di un oggetto con la proprietà +// magica `__proto__`: Anche se questo è utile per spiegare i prototipi, non è +// parte dello standard; capiremo più avanti come usare i prototipi in modo standard. +var myObj = { + myString: "Hello world!" +}; +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase(); + } +}; + +myObj.__proto__ = myPrototype; +myObj.meaningOfLife; // = 42 + +// Questo funziona anche per le funzioni. +myObj.myFunc(); // = "hello world!" + +// Ovviamente, se la proprietà non è nel prototipo, il prototipo +// del prototipo viene ricercato, e così via. +myPrototype.__proto__ = { + myBoolean: true +}; +myObj.myBoolean; // = true + +// Non c'è nessuna copia coinvolta qui; ogni oggetto mantiene una referenza al suo +// prototipo. Questo significa che possiamo modificare il prototipo e i nostri cambiamenti +// si rifletteranno da ogni parte. +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43 + +// L'istruzione for/in permette di iterare sulle proprietà di un oggetto, +// risalendo la catena dei prototipi finché non trova un prototipo null. +for (var x in myObj){ + console.log(myObj[x]); +} +///stampa: +// Hello world! +// 43 +// [Function: myFunc] +// true + +// Per considerare solamente le proprietà inserite nell'oggetto stesso +// e non i loro prototipi, usare il check `hasOwnProperty()`. +for (var x in myObj){ + if (myObj.hasOwnProperty(x)){ + console.log(myObj[x]); + } +} +///stampa: +// Hello world! + +// Abbiamo menzionato che `__proto__` non è standard, e non c'è nessun modo standard per +// cambiare il prototipo di un oggetto esistente. Tuttavia, ci sono due strade per +// creare un nuovo oggetto con un dato prototipo. + +// La prima è Object.create, che è una recente aggiunta a JS, e che quindi +// non è disponibile ancora in tutte le implementazioni. +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43 + +// La seconda strada, che funziona ovunque, ha a che fare con i costruttori. +// I costruttori hanno una proprietà chiamata prototype. Questo *non* è il prototipo del +// costruttore della stessa funzione; invece è il prototipo del nuovo oggetto +// che gli viene conferito alla creazione con quel costruttore e la parola chiave new. +MyConstructor.prototype = { + myNumber: 5, + getMyNumber: function(){ + return this.myNumber; + } +}; +var myNewObj2 = new MyConstructor(); +myNewObj2.getMyNumber(); // = 5 +myNewObj2.myNumber = 6; +myNewObj2.getMyNumber(); // = 6 + +// I tipi built-in come stringhe e numeri hanno anche costruttori che creano +// oggetti wrapper equivalenti. +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true + +// Eccezione, loro non sono esattamente equivalenti. +typeof myNumber; // = 'number' +typeof myNumberObj; // = 'object' +myNumber === myNumberObj; // = false +if (0){ + // Questo codice non verrà eseguito perchè 0 è falso. +} +if (new Number(0)){ + // Questo codice verrà eseguito poiché i numeri wrappati sono oggetti e gli oggetti + // sono sempre veri. +} + +// Tuttavia, gli oggetti wrapper e i regolari built-in condividono un prototipo, quindi +// si possono aggiungere funzionalità ad una stringa, per esempio. +String.prototype.firstCharacter = function(){ + return this.charAt(0); +}; +"abc".firstCharacter(); // = "a" + +// Questa caratteristica viene spesso usata nel "polyfilling", che implementa nuovi +// aspetti in un vecchio sottoinsieme di JavaScript, in modo che si possano +// usare in vecchi ambienti come browser non aggiornati. + +// Per esempio, abbiamo menzionato che Object.create non è disponibile in tutte le +// implementazioni, ma possiamo ancora usarlo con questo polyfill: +if (Object.create === undefined){ // non lo sovrascrive se esiste già + Object.create = function(proto){ + // crea un costruttore temporaneo con il giusto prototipo + var Constructor = function(){}; + Constructor.prototype = proto; + // quindi lo usa per creare un nuovo, propriamente-prototipato oggetto + return new Constructor(); + }; +} +``` + +## Approfondimenti + +Il [Mozilla Developer Networ][1] fornisce una documentazione eccellente su come Javascript è utilizzato nei browsers. In più è un wiki, quindi si può imparare di più aiutando gli altri condividendo la propria conoscenza. + +MDN's [A re-introduction to JavaScript][2] copre molti dei concetti qui trattati in maggiore dettaglio. Questa guida ha deliberatamente coperto solamente il linguaggio JavaScript; se volete sapere di più su come usare JavaScript in una pagina web, iniziate leggendo il [Document Object Model][3]. + +[Learn Javascript by Example and with Challenges][4] è una variante di questo referenziario con integrate delle sfide. + +[Javascript Garden][5] è una guida approfondita di tutte le parti controintuitive del linguaggio. + +[JavaScript: The Definitive Guide][6] è una guida classica e referenziario. + +[Eloqunt Javascript][8] di Marijn Haverbeke è un ottimo libro/ebook JS con terminale annesso + +[Javascript: The Right Way][10] è una guida dedicata all'introduzione dei nuovi sviluppatori a JavaScript e come aiuto agli sviluppatori esperti per imparare di più sulle best practice. + +[Javascript:info][11] è un moderno tutorial su javascript che copre le basi (linguaggio principale e lavorazione con un browser) come anche argomenti avanzati con spiegazioni concise. + + +In aggiunta ai contributori di questo articolo, alcuni contenuti sono adattati dal Louie Dinh's Python tutorial su questo sito, e da [JS Tutorial][7] sul Mozilla Developer Network. + + +[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript +[2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript +[3]: https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core +[4]: http://www.learneroo.com/modules/64/nodes/350 +[5]: http://bonsaiden.github.io/JavaScript-Garden/ +[6]: http://www.amazon.com/gp/product/0596805527/ +[7]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript +[8]: http://eloquentjavascript.net/ +[10]: http://jstherightway.org/ +[11]: https://javascript.info/ |