diff --git a/README.md b/README.md index 4cfa2556..b203a060 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,26 @@
+From basic to advanced: test how well you know JavaScript, refresh your knowledge a bit or prepare for your coding interview! :muscle: :rocket: I update this repo regularly with new questions. I added the answers in the **collapsed sections** below the questions, simply click on them to expand it. It's just for fun, good luck! :heart:
-Feel free to reach out to me! 😊Feel free to reach out to me! 😊
-| Feel free to use them in a project! 😃 I would _really_ appreciate a reference to this repo, I create the questions and explanations (yes I'm sad lol) and the community helps me so much to maintain and improve it! 💪🏼 Thank you and have fun! | -|---| ++ Instagram || Twitter || LinkedIn || Blog +
---- +| Feel free to use them in a project! 😃 I would _really_ appreciate a reference to this repo, I create the questions and explanations (yes I'm sad lol) and the community helps me so much to maintain and improve it! 💪🏼 Thank you and have fun! | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -
- [🇸🇦 العربية](./ar-AR/README_AR.md)
@@ -27,11 +30,15 @@ Feel free to reach out to me! 😊
- [🇪🇸 Español](./es-ES/README-ES.md)
- [🇫🇷 Français](./fr-FR/README_fr-FR.md)
- [🇮🇩 Indonesia](./id-ID/README.md)
+- [🇮🇹 Italiano](./it-IT/README.md)
- [🇯🇵 日本語](./ja-JA/README-ja_JA.md)
- [🇰🇷 한국어](./ko-KR/README-ko_KR.md)
- [🇳🇱 Nederlands](./nl-NL/README.md)
+- [🇵🇱 Polski](./pl-PL/README.md)
- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md)
+- [🇷o Română](./ro-RO/README.ro.md)
- [🇷🇺 Русский](./ru-RU/README.md)
+- [🇽🇰 Shqip](./sq-KS/README_sq_KS.md)
- [🇹🇭 ไทย](./th-TH/README-th_TH.md)
- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md)
- [🇺🇦 Українська мова](./uk-UA/README.md)
@@ -135,7 +142,7 @@ Note that the value of `diameter` is a regular function, whereas the value of `p
With arrow functions, the `this` keyword refers to its current surrounding scope, unlike regular functions! This means that when we call `perimeter`, it doesn't refer to the shape object, but to its surrounding scope (window for example).
-There is no value `radius` on that object, which returns `NaN`.
+Since there is no value `radius` in the scope of the arrow function, `this.radius` returns `undefined` which, when multiplied by `2 * Math.PI`, results in `NaN`.
-#### Answer: C +#### Answer: D + +By using [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) syntax we can unpack values from arrays, or properties from objects, into distinct variables: + +```javascript +const { firstName } = { firstName: 'Lydia' }; +// ES5 version: +// var firstName = { firstName: 'Lydia' }.firstName; + +console.log(firstName); // "Lydia" +``` + +Also, a property can be unpacked from an object and assigned to a variable with a different name than the object property: + +```javascript +const { firstName: myName } = { firstName: 'Lydia' }; +// ES5 version: +// var myName = { firstName: 'Lydia' }.firstName; + +console.log(myName); // "Lydia" +console.log(firstName); // Uncaught ReferenceError: firstName is not defined +``` + +Therefore, `firstName` does not exist as a variable, thus attempting to access its value will raise a `ReferenceError`. + +**Note:** Be aware of the `global scope` properties: + +```javascript +const { name: myName } = { name: 'Lydia' }; + +console.log(myName); // "lydia" +console.log(name); // "" ----- Browser e.g. Chrome +console.log(name); // ReferenceError: name is not defined ----- NodeJS + +``` -When we unpack the property `name` from the object on the right-hand side, we assign its value `"Lydia"` to a variable with the name `myName`. +Whenever Javascript is unable to find a variable within the _current scope_, it climbs up the [Scope chain](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch3.md) and searches for it and if it reaches the top-level scope, aka **Global scope**, and still doesn't find it, it will throw a `ReferenceError`. -With `{ name: myName }`, we tell JavaScript that we want to create a new variable called `myName` with the value of the `name` property on the right-hand side. +- In **Browsers** such as _Chrome_, `name` is a _deprecated global scope property_. In this example, the code is running inside _global scope_ and there is no user-defined local variable for `name`, therefore it searches the predefined _variables/properties_ in the global scope which is in the case of browsers, it searches through `window` object and it will extract the [window.name](https://developer.mozilla.org/en-US/docs/Web/API/Window/name) value which is equal to an **empty string**. -Since we try to log `name`, a variable that is not defined, `undefined` is returned on the left side assignment. Later, the value of `Lydia` is stored through the destructuring assignment. +- In **NodeJS**, there is no such property on the `global` object, thus attempting to access a non-existent variable will raise a [ReferenceError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined).
-- [🇸🇦 العربية](./ar-AR/README_AR.md) -- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md) -- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md) +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) - [🇬🇧 English](../README.md) -- [🇪🇸 Español](./es-ES/README-ES.md) -- [🇫🇷 Français](./fr-FR/README_fr-FR.md) -- [🇮🇩 Indonesia](./id-ID/README.md) -- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) -- [🇰🇷 한국어](./ko-KR/README-ko_KR.md) -- [🇳🇱 Nederlands](./nl-NL/README.md) -- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) -- [🇷🇺 Русский](./ru-RU/README.md) -- [🇹🇭 ไทย](./th-TH/README-th_TH.md) -- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) -- [🇺🇦 Українська мова](./uk-UA/README.md) -- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) -- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) -- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](../id-ID/README.md) +- [🇮🇹 Italiano](../it-IT/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](../ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](../nl-NL/README.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](../ru-RU/README.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md)
-- [🇸🇦 العربية](./ar-AR/README_AR.md) -- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md) -- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md) -- [🇩🇪 Deutsch](./de-DE/README.md) +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](../de-DE/README.md) - [🇬🇧 English](../README.md) -- [🇪🇸 Español](./es-ES/README-ES.md) -- [🇫🇷 Français](./fr-FR/README_fr-FR.md) -- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) -- [🇰🇷 한국어](./ko-KR/README-ko_KR.md) -- [🇳🇱 Nederlands](./nl-NL/README.md) -- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) -- [🇷🇺 Русский](./ru-RU/README.md) -- [🇹🇭 ไทย](./th-TH/README-th_TH.md) -- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) -- [🇺🇦 Українська мова](./uk-UA/README.md) -- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) -- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) -- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇹 Italiano](../it-IT/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](../ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](../nl-NL/README.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](../ru-RU/README.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md)
+ +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](../de-DE/README.md) +- [🇬🇧 English](../README.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](../id-ID/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](../ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](../nl-NL/README.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](../ru-RU/README.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md) + +
++ +#### Risposta: D + +All'interno della funzione, dichiariamo prima la variabile `name` con la parola chiave `var`. Ciò significa che la variabile viene sollevata all'interno del codice (ovvero lo spazio di memoria viene impostato durante la fase di creazione) e viene inizializzata con il valore predefinito di `undefined`, finché non arriviamo effettivamente alla riga in cui la definiamo. +Al momento in cui proviamo ad eseguire il log della variabile `name` non l'abbiamo ancora dichiarata, quindi mantiene il valore di `undefined`. + +Le variabili dichiarate con la chiave `let` (o `const`) vengono sollevate, ma a differenza delle variabili dichiarate con `var`, non vengono inizializzate. Per questo motivo non sono accessibili prima della loro dichiarazione (dove le inizializzaimo). Questa è chiamata "temporal dead zone". Quando proviamo ad accedere alle variabili prima che vengano dichiarate, JavaScript genera un `ReferenceError`. + +
++ +#### Risposta: C + +A causa della coda degli eventi in JavaScript la funzione di callback `setTimeout` viene chiamata _dopo_ che il loop è stato eseguito. Poiché la variabile `i` nel primo loop è stata dichiarata usando la chiave `var`, questo valore è globale. Durante il loop abbiamo incrementato ogni volta il valore di `i` di `1` usando l'operatore unario `++`. Quando è stata invocata la funzione di callback `setTimeout`, `i` nel primo esempio risultava sin dal principio uguale a `3`. + +Nel secondo loop, la variabile `i` è stata dichiarata usando la chiave `let`: le variabili dichiarate con la chiave `let` (e `const`) hanno lo scope del blocco (un blocco è qualsiasi cosa tra `{ }`). Durante ogni iterazione, `i` avrà un nuovo valore e ogni valore avrà lo scope all'interno del loop. + +
++ +#### Risposta: B + +Il valore di `diameter` è una funzione regolare, mentre il valore di `perimeter` è generato con una arrow function. + +Nelle arrow functions, la chiave `this` fa riferimento al suo scope interno a differenza delle funzioni regolari. Questo vuol dire che quando richiamiamo `perimeter` non stiamo facendo riferimento all'oggetto shape, ma al suo ambito circostante (ad esempio window). + +Non troviamo quindi alcun valore `radius` in quell'oggetto e quindi viene restituito `NaN`. + +
++ +#### Risposta: A + +Il + unario tenta di convertire un operando in un numero. `true` equivale ad `1` e `false` equivale a `0`. + +La stringa `'Lydia'` è un valore veritiero. Quello che in realtà ci stiamo chiedendo con `!'Lydia'` è "questo valore veritiero è falso?". Per cui la risposta è `false`. + +
++ +#### Risposta: A + +In JavaScript, tutte le chiavi degli oggetti sono stringhe (a meno che non sia un simbolo). Anche se potremmo non scriverle come stringhe, vengono sempre convertite come tali. + +JavaScript interpreta le istruzioni, quindi quando usiamo la bracket notation, vede la prima parentesi aperta `[` e continua finché non trova la parentesi chiusa `]`. Solo allora valuterà la dichiarazione. + +Quando in JavaScript richiamiamo `mouse[bird.size]`: per prima cosa viene valorizzato `bird.size`, che è `"small"`, per JS viene tradotto quindi come `mouse["small"]` che restituisce `true`. + +Con l'utilizzo del punto questo non accade perché `mouse` non ha una chiave chiamata `bird`, e questo significa che `mouse.bird` è `undefined`. Per JavaScript quindi l'istruzione `mouse.bird.size` viene tradotta con `mouse.undefined.size` che è un valore non valido e che quindi genererà un errore simile a `Cannot read property "size" of undefined`. + +
+
+
+#### Risposta: A
+
+In JavaScript, tutti gli oggetti interagiscono per _referenza_.
+
+La variabile `c` contiene come valore un oggetto. Alla variabile `d` assegniamo come valore il riferimento di `c` che quindi contiene l'oggetto (e non un suo clone).
+
+
+
+Quando modifichi il valore di questo oggetto, lo stai modificando sia per `c`che per `d`, che contiene il suo riferimento.
+
+
+ +#### Risposta: C + +`new Number()` è una funzione costruttore integrata. Nonostante sembri un numero, in realtà non lo è, si tratta infatti di un oggetto con un sacco di funzioni extra. + +Quando utilizziamo l'operatore `==`, stiamo verificando solo se il suo _valore_ è uguale. Entrambe le variabili hanno il valore di `3`, quindi il primo log restituisce `true`. + +Quando invece utilizziamo l'operatore `===`, stiamo verificando che sia il valore che il tipo di valore siano uguali. `new Number()` non è un numero, è un **oggetto** quindi entrambi i log restituiscono `false`. + +
++ +#### Risposta: D + +La funzione `colorChange` è statica. I metodi statici sono progettati per vivere solo nel costruttore in cui vengono creati e non possono essere passati a nessun figlio o richiamati su istanze di classe. Poiché `freddie` è un'istanza della classe `Chameleon`, la funzione non può essere chiamata su di essa. Viene restituito quindi un errore di tipo `TypeError`. + +
++ +#### Risposta: A + +Il nostro log restituisce un oggetto perché abbiamo appena creato un oggetto vuoto come oggetto globale nel momento in cui per errore abbiamo digitato `greetign` al posto di `greeting`. + +Il nostro interprete a quel punto ha letto `global.greetign = {}` (o `window.greetign = {}` se parliamo di un browser). + +Per evitare ciò, possiamo usare `"use strict"`. Questo assicura di aver dichiarato una variabile prima di impostarla uguale a qualsiasi cosa. + +
++ +#### Risposta: A + +In JavaScript non succede nulla, perché le funzioni sono oggetti! (Tutto tranne i tipi primitivi sono oggetti). + +Una funzione è un tipo speciale di oggetto. Il codice che scrivi non è la funzione effettiva. La funzione è un oggetto con delle proprietà e quindi questa proprietà è invocabile. + +
++ +#### Risposta: A + +In JavaScript, le funzioni sono oggetti e quindi il metodo `getFullName` viene aggiunto al costruttore della funzione stessa. Per questo motivo possiamo chiamare `Person.getFullName()`, mentre `member.getFullName` genera un `TypeError`. + +Se vuoi che un metodo sia disponibile per tutte le istanze dell'oggetto, devi aggiungerlo alla proprietà del prototipo: + + +```js +Person.prototype.getFullName = function() { + return `${this.firstName} ${this.lastName}`; +}; +``` + +
++ +#### Risposta: A + +Per la const `sarah`, non abbiamo usato la chiave `new`. Quando si usa `new`, `this` si riferisce al nuovo oggetto vuoto che creiamo. Tuttavia, se non aggiungiamo `new`, `this` si riferisce all'**oggetto globale**! + +Abbiamo quindi scritto che `this.firstName` equivale a `"Sarah"` e `this.lastName` equivale a `"Smith"`. Quello che abbiamo effettivamente fatto è definire `global.firstName = 'Sarah'` e `global.lastName = 'Smith'`. La `const` `sarah` viene lasciata come `non definita`, perché non restituiamo un valore dalla funzione `Persona`. + +
+
+
+#### Risposta: D
+
+Durante la fase di **capturing**, l'evento passa attraverso gli elementi predecessori fino all'elemento target. Quindi raggiunge l'elemento **target** e inizia il **bubbling**.
+
+
+
+
+ +#### Risposta: B + +Tutti gli oggetti hanno prototipi, ad eccezione dell'**oggetto base**. L'oggetto base è l'oggetto creato dall'utente, o un oggetto creato usando la parola chiave `new`. L'oggetto base ha accesso ad alcuni metodi e proprietà, come `.toString`. Questo è il motivo per cui puoi utilizzare i metodi JavaScript built-in! Tutti questi metodi sono disponibili sul prototype. Quindi, anche se JavaScript non riesce a trovarlo direttamente sul tuo oggetto, scende lungo la chain del prototype e lo trova lì, il che lo rende accessibile anche per l'oggetto creato da te. + +
++ +#### Risposta: C + +JavaScript è un **linguaggio tipizzato dinamicamente**: non specifichiamo quali tipi siano determinate variabili. I valori possono essere automaticamente convertiti in un altro tipo, questa azione è chiamata _coercizione implicita del tipo_. **Coercizione** è la conversione da un tipo all'altro. + +In questo esempio, JavaScript converte il numero `1` in una stringa, in modo che la funzione abbia un senso e restituisca un valore. Durante l'aggiunta di un tipo numerico (`1`) e di un tipo stringa (`'2'`), il numero viene trattato come una stringa. Possiamo concatenare stringhe come `"Hello" + "World"`, quindi quello che sta succedendo qui è `"1" + "2"` che restituisce `"12"`. + +
++ +#### Risposta: C + +Utilizzando l'operatore unario come **postfisso** `number++` succede che: + +1. Restituisce prima il suo valore (`0`) +2. Subito dopo incrementa il valore di 1 (quindi è ora `1`) + +Utilizzando l'operatore unario come **prefisso** `++number` succede che: + +1. Incrementa prima il valore (il numero è ora `2`) +2. Restituisce subito dopo il valore già incrementato (`2`) + +Quindi il nostro log sarà `0 2 2`. + +
++ +#### Risposta: B + +Utilizzando i template literals, il valore del primo argomento sarà un array di valori della stringa. Gli altri argomenti prenderanno i valori dell'espressione passata. + +
++ +#### Risposta: C + +Quando si verifica l'uguaglianza, i primitivi vengono confrontati in base al loro _valore_, mentre gli oggetti vengono confrontati in base al loro _riferimento_. JavaScript controlla se gli oggetti hanno un riferimento alla stessa posizione in memoria. + +I due oggetti che stiamo confrontando non lo hanno: l'oggetto che abbiamo passato come parametro si riferisce a una posizione di memoria diversa rispetto all'oggetto che abbiamo usato per verificare l'uguaglianza. + +Questo è il motivo per cui sia `{ age: 18 } === { age: 18 }` e `{ age: 18 } == { age: 18 }` restituiscono `false`. + +
++ +#### Risposta: C + +Il parametro rest (`...args`) ci permette di "collettare" tutti gli argomenti in un array. L'array è un oggetto, quindi `typeof args` restituisce `"oggetto"` + +
++ +#### Risposta: C + +Con `"use strict"`, puoi assicurarti di non dichiarare variabili globali per sbaglio. In questo caso la variabile `age` non è mai stata dichiarata, e siccome usiamo `"use strict"`, genererà un `ReferenceError`. Se non avessimo usato `"use strict"`, avrebbe funzionato perché la proprietà `age` sarebbe stata aggiunta all'oggetto globale. + +
++ +#### Risposta: A + +`eval` "valuta" i codici passati come stringa. Se è un'espressione, come in questo caso, valuta l'espressione. L'espressione è `10 * 10 + 5`. Quindi il valore restituito è il numero `105`. + +
++ +#### Risposta: B + +I dati memorizzati in `sessionStorage` vengono rimossi dopo aver chiuso la _tab_. + +Se avessi usato `localStorage`, i dati sarebbero rimasti lì per sempre, a meno che, ad esempio, non fosse stato invocato `localStorage.clear()`. + +
++ +#### Risposta: B + +Con la chiave `var` puoi dichiarare più variabili con lo stesso nome. La variabile conterrà quindi l'ultimo valore. + +Non puoi farlo con `let` o `const` poiché sono block-scoped. + +
++ +#### Risposta: C + +Tutte le chiavi degli oggetti (esclusi i simboli) sono stringhe, anche se non vengono scritte come tali. Questo è il motivo per cui anche `obj.hasOwnProperty('1')` restituisce true. + +Per i set non funziona allo stesso modo degli oggetti. Non c'è alcun `'1'` nel nostro set, per cui `set.has('1')` restituisce `false`, è però presente il tipo numerico `1` per cui `set.has(1)` restituisce `true`. + +
++ +#### Risposta: C + +Se hai due chiavi con lo stesso nome, questa verrà sostituita. Sarà quindi ancora nella sua prima posizione, ma con l'ultimo valore specificato. + +
++ +#### Risposta: A + +Il contesto di esecuzione di base è il contesto di esecuzione globale: è ciò che è accessibile ovunque nel codice. + +
++ +#### Risposta: C + +L'istruzione `continue` salta un'iterazione se una certa condizione restituisce `true`. + +
++ +#### Risposta: A + +`String` è un costruttore built-in, a cui possiamo aggiungere proprietà. In questo caso è stato appena aggiunto un metodo al suo prototipo. +Le stringhe primitive vengono automaticamente convertite in un oggetto stringa, generato dalla string prototype function. Quindi, tutte le stringhe hanno accesso a quel metodo! + +
++ +#### Risposta: B + +Le chiavi degli oggetti vengono automaticamente convertite in stringhe. Stiamo cercando di impostare un oggetto come chiave per l'oggetto `a` con il valore di `123`. + +Tuttavia, quando convertiamo in stringa un oggetto, diventa `"[object Object]"`. Quindi quello che stiamo dicendo qui è che `a["[object Object]"] = 123`. `c` è un altro oggetto che stiamo implicitamente stringendo. Quindi, `a["[object Object]"] = 456`. + +Quindi, quando facciamo console.log di `a[b]`, che in realtà è `a["[object Object]"]` che abbiamo appena valorizzato con `456`, restituisce `456`. + +
+
+
+#### Risposta: B
+
+Abbiamo una funzione `setTimeout` e l'abbiamo invocata per prima. Eppure, viene loggata per ultima.
+
+Questo succede perché nei browser non abbiamo solo il runtime engine, ma anche qualcosa chiamata `WebAPI`. La `WebAPI` ci fornisce la funzione `setTimeout` con cui iniziare, e per esempio il DOM.
+
+Dopo che la _callback_ è stata inviata alla `WebAPI`, la stessa funzione `setTimeout` (ma non la sua callback) viene eliminata dallo stack.
+
+
+
+Ora, `foo` viene invocato e `"First"` viene loggato.
+
+
+
+`foo` viene quindi tolto dallo stack e `baz` viene invocato. `"Third"` viene loggato.
+
+
+
+La WebAPI non può semplicemente aggiungere elementi allo stack ogni volta che è pronta, spinge quindi la funzione di callback in quella che chiamiamo _queue_.
+
+
+
+È qui che un ciclo di eventi inizia a funzionare. Un **event loop** esamina lo stack e la coda delle attività. Se lo stack è vuoto, prende la prima cosa in coda e la inserisce nello stack.
+
+
+
+`bar` viene invocato, `"Second"` viene registrato e viene tolto dallo stack.
+
+
+ +#### Risposta: C + +L'elemento annidato più in profondità è quello che ha causato l'evento ed è quindi l'event.target. Puoi stoppare la propagazione con `event.stopPropagation` + +
++ Click here! +
++ +#### Risposta: A + +Se clicchiamo su `p`, vediamo due log: `p` e `div`. Durante la propagazione dell'evento, ci sono 3 fasi: capturing, target, e bubbling. Di default, i gestori di eventi vengono eseguiti nella fase di bubbling (a meno che non si imposti `useCapture` su `true`) e va quindi dall'elemento annidato più profondo verso l'esterno. + +
++ +#### Risposta: D + +Con entrambi possiamo passare l'oggetto a cui vogliamo che la chiave `this` faccia riferimento. Tuttavia, anche `.call` viene _eseguito immediatamente_! + +`.bind.` restituisce una _copia_ della funzione, ma con un contesto vincolato! Non viene eseguito immediatamente. + +
++ +#### Risposta: B + +La funzione `sayHi` restituisce il valore dato dell'espressione della immediately invoked function expression (IIFE). Questa funzione ha restituito `0`, che è di tipo `"numero"`. + +Ci sono solo 7 tipi built-in: `null`, `undefined`, `boolean`, `number`, `string`, `object` e `symbol`. `"function"` non è un tipo, poiché le funzioni sono oggetti, è quindi di tipo "oggetto"`. + +
++ +#### Risposta: A + +Ci sono 8 valori falsi: + +- `undefined` +- `null` +- `NaN` +- `false` +- `''` (empty string) +- `0` +- `-0` +- `0n` (BigInt(0)) + +I costruttori di funzioni, come `new Number` e `new Boolean` sono veritieri. + +
++ +#### Risposta: B + +`typeof 1` ritorna `"number"`. +`typeof "number"` ritorna `"string"` + +
++ +#### Risposta: C + +Quando imposti un valore su un elemento in un array che supera la lunghezza dell'array JavaScript crea degli "slot vuoti". Questi in realtà hanno il valore di `undefined`, ma vedrai qualcosa come: + +`[1, 2, 3, 7 x empty, 11]` + +a seconda di dove lo esegui (è diverso per ogni browser, node, ecc.) + +
++ +#### Risposta: A + +Il blocco `catch` riceve l'argomento `x` ma non è la stessa `x` della variabile, bensì passiamo un argomento della funzione. Questa "variabile" `x` è block-scoped quindi ha un ambito di blocco. + +Subito dopo impostiamo il valore di variabile block-scoped a `1` e impostiamo il valore della variabile `y`. Ora facciamo un console.log della variabile block-scoped `x`, che è uguale a `1`. + +Fuori dal blocco `catch`, `x` è ancora `undefined` e `y` è `2` quindi quando facciamo `console.log(x)` al di fuori del blocco `catch`, otterremo `undefined` e `y` restituirà `2`. + +
++ +#### Risposta: A + +JavaScript ha solo tipi primitivi e oggetti. + +I tipi primitivi sono `boolean`, `null`, `undefined`, `bigint`, `number`, `string` e `symbol`. + +Ciò che differenzia un tipo primitivo da un oggetto è che i primitivi non hanno proprietà o metodi. Tuttavia, noterai che `'foo'.toUpperCase()` restituisce `'FOO'` e non genera un `TypeError`. Questo perché quando si tenta di accedere a una proprietà o a un metodo su di un tipo primitivo come lo è una stringa, JavaScript racchiuderà implicitamente il tipo primitivo utilizzando una delle classi wrapper, ovvero "String", valuterà l'espressione ed eliminerà il wrapper una volta terminato. Tutti i primitivi tranne `null` e `undefined` subiscono questo comportamento. + +
++ +#### Risposta: C + +`[1, 2]` rappresenta il nostro valore interno. Ovvero il valore con cui iniziamo e il valore del primo `acc`. Durante il primo round, `acc` è `[1,2]` e `cur` è `[0, 1]`. Li concateniamo ottenendo `[1, 2, 0, 1]`. + +A questo punto `acc` corrisponderà a `[1, 2, 0, 1]` e `cur` sarà ancora `[2, 3]`. Li concateniamo e otteniamo `[1, 2, 0, 1, 2, 3]` +
++ +#### Risposta: B + +`null` è falso. `!null` restituisce `true`. `!true` restituisce `false`. + +`""` è falso. `!""` restituisce `true`. `!true` restituisce `false`. + +`1` è vero. `!1` restituisce `falso`. `!false` restituisce `true`. + +
++ +#### Risposta: A + +Restituisce un ID univoco. Questo id può essere usato per cancellare quell'intervallo con la funzione `clearInterval()`. + +
++ +#### Risposta: A + +Una stringa è un iterabile. L'operatore spread mappa ogni carattere di una stringa rendendola parte di array. + +
++ +#### Risposta: C + +Le funzioni regolari non possono essere interrotte a metà dopo l'invocazione. Tuttavia, una funzione "generator" può essere stoppata a metà e in seguito continuare da dove si era interrotta. Ogni volta che una funzione generator incontra una parola chiave `yield`, la funzione restituisce il valore specificato dopo di essa. Nota che la funzione del generator in quel caso non _restituisce (return)_ il valore, _rende (yeld)_ il valore. + +Come prima cosa inizializziamo la funzione del generator con `i` uguale a `10`. Invochiamo la funzione usando il metodo `next()`. La prima volta che invochiamo la funzione generator, `i` è uguale a `10`, incontra la prima parola chiave `yield` quindi restituisce il valore di `i`. Il generatore è ora "in pausa" e `10` viene loggato. + +Invochiamo di nuovo la funzione con il metodo `next()`. Inizia a continuare da dove si era fermata in precedenza, sempre con `i` uguale a `10`. Ora incontra il secondo `yield` e restituisce `i * 2`, quindi restituisce `10 * 2`, che è `20`. Ciò risulta in `10, 20`. + +
++ +#### Risposta: B + +Quando passiamo più promises al metodo `Promise.race`, questo risolve/rifiuta la _prima_ promise. Al metodo `setTimeout` passiamo un timer: 500ms per la prima promise (`firstPromise`) e 100ms per la seconda promise (`secondPromise`). Ciò significa che `secondPromise` si risolve prima con il valore di `'due'`. `res` ora contiene il valore di `'two'`, che viene loggato. + +
+
+
+#### Risposta: D
+
+Per prima cosa, dichiariamo una variabile `person` con un oggetto che ha una proprietà `name`.
+
+
+
+Quindi, dichiariamo una variabile chiamata `members`. Impostiamo il primo elemento di quell'array uguale al valore della variabile `person`. Gli oggetti interagiscono per _riferimento_ quando vengono impostati uguali tra loro. Quando assegni un riferimento da una variabile all'altra, esegui una _copia_ di quel riferimento. (nota che non hanno lo _stesso_ riferimento!)
+
+
+
+Quindi, impostiamo la variabile `person` uguale a `null`.
+
+
+
+Stiamo modificando solo il valore della variabile `person`, e non il primo elemento nell'array, poiché quell'elemento ha un riferimento diverso (copiato) dall'oggetto. Il primo elemento in `members` mantiene ancora il suo riferimento all'oggetto originale. Quando logghiamo l'array `members`, il primo elemento contiene ancora il valore dell'oggetto, che viene loggato.
+
+
+ +#### Risposta: B + +Con il ciclo `for-in`, possiamo iterare le chiavi degli oggetti, in questo caso `name` e `age`. Le chiavi degli oggetti sono stringhe (se non sono un simbolo). In ogni ciclo, impostiamo il valore di `item` uguale alla chiave corrente su cui sta iterando. Il primo `item` è uguale a `name` e viene loggato, `item` sarà poi uguale a `age`, che viene loggato. + +
++ +#### Risposta: B + +L'associazione è l'ordine in cui il compilatore valuta le espressioni, da sinistra a destra o da destra a sinistra. Questo accade solo se tutti gli operatori hanno la _stessa_ precedenza. Abbiamo solo un tipo di operatore: `+`. Inoltre, l'associazione è da sinistra a destra. + +`3 + 4` viene valutato per primo. E risulta nell'addizione dei due valori che restituiscono quindi `7`. + +`7 + '5'` risulta in `"75"` per via della coercizione. JavaScript converte il numero `7` in una stringa, (vedi la domanda 15). Possiamo concatenare due stringhe usando l'operatore `+`. `"7" + "5"` risulta quindi in "75"`. + +
++ +#### Risposta: C + +Viene restituito solo il primo valore della stringa. In base alla _radice_ (ovvero il secondo argomento per specificare sulla base di quale tipo di numero vogliamo analizzarlo: base 10, esadecimale, ottale, binario, ecc.), `parseInt` controlla se i caratteri nella stringa sono validi. Una volta che incontra un carattere che non è un numero valido nella radice, interrompe l'analisi e ignora i seguenti caratteri. + +`*` non è un numero valido. Analizza solo `"7"` nel decimale `7`. `num` ora contiene il valore di `7`. + +
++ +#### Risposta: C + +Quando si esegue il mapping sull'array, il valore di `num` è uguale all'elemento su cui sta attualmente scorrendo. In questo caso, gli elementi sono numeri, quindi la condizione dell'istruzione if `typeof num === "number"` restituisce `true`. La funzione map crea un nuovo array e inserisce i valori restituiti dalla funzione. + +Tuttavia, non ritorniamo un valore. Quando non ritorniamo un valore dalla funzione, la funzione restituisce `undefined`. Per ogni elemento nell'array, viene chiamato il blocco funzione, quindi per ogni elemento restituiamo `undefined`. + +
++ +#### Risposta: A + +Gli argomenti vengono passati come _valori_, a meno che il loro valore non sia un oggetto, quindi vengono passati come _reference_. `birthYear` viene passato per valore, poiché è una stringa, non un oggetto. Quando passiamo argomenti per valore, viene creata una _copia_ di quel valore (vedi domanda 46). + +La variabile `birthYear` ha un riferimento al valore `"1997"`. Anche l'argomento `year` fa riferimento al valore `"1997"`, ma non è lo stesso valore a cui fa riferimento `birthYear`. Quando aggiorniamo il valore di `year` impostando `year` uguale a `"1998"`, stiamo solo aggiornando il valore di `year`. `birthYear` è ancora uguale a `"1997"`. + +Il valore di `person` è un oggetto. L'argomento `member` ha un riferimento (copiato) dello stesso oggetto. Quando modifichiamo una proprietà dell'oggetto a cui `member` fa riferimento, verrà modificato anche il valore di `person`, poiché entrambi hanno un riferimento allo stesso oggetto. La proprietà `name` di `person` è ora uguale al valore `"Lydia"` +
++ +#### Risposta: D + +Con l'istruzione `throw`, possiamo creare errori personalizzati. Con questa istruzione, puoi generare eccezioni. Un'eccezione può essere una stringa, un numero, un booleano o un oggetto. In questo caso, la nostra eccezione è la stringa `'Hello world!'`. + +Con l'istruzione `catch`, possiamo specificare cosa fare se viene generata un'eccezione nel blocco `try`. Viene generata un'eccezione: la stringa `'Hello world!'`. `e` è ora uguale a quella stringa, che logghiamo. Ciò si traduce in `'Oh an error: Hello world!'`. + +
++ +#### Risposta: B + +Quando si restituisce una proprietà, il valore della proprietà è uguale al valore _restituito_, non al valore impostato nella funzione di costruzione. Restituiamo la stringa `"Maserati"`, quindi `myCar.make` è uguale a `"Maserati"`. + +
++ +#### Risposta: A + +`let x = (y = 10);` in realtà è un'abbreviazione per: + +```javascript +y = 10; +let x = y; +``` + +Quando impostiamo `y` uguale a `10`, in realtà aggiungiamo una proprietà `y` all'oggetto globale (`window` nel browser, `global` in Node). In un browser, `window.y` ora è uguale a `10`. + +Quindi, dichiariamo una variabile `x` con il valore di `y`, che è `10`. Le variabili dichiarate con la parola chiave `let` sono _block scoped_, ovvero sono definite solo all'interno del blocco in cui sono dichiarate, l'espressione di funzione immediatamente invocata (IIFE) in questo caso. Quando utilizziamo l'operatore `typeof`, l'operando `x` non è definito: stiamo cercando di accedere a `x` al di fuori del blocco in cui è dichiarato. Ciò significa che `x` non è definito. I valori a cui non è stato assegnato un valore o dichiarati sono di tipo `"undefined"`. `console.log(typeof x)` restituisce `"undefined"`. + +Tuttavia, abbiamo creato una variabile globale `y` quando abbiamo impostato `y` uguale a `10`. Questo valore è accessibile ovunque nel nostro codice. `y` è definito e contiene un valore di tipo `"number"`. `console.log(typeof y)` restituisce `"number"`. + +
++ +#### Risposta: A + +Possiamo eliminare le proprietà dagli oggetti usando la parola chiave `delete`, anche sul prototype. Eliminando una proprietà sul prototipo, questa non è più disponibile nella catena di prototype. In questo caso, la funzione `bark` non è più disponibile sul prototipo dopo `delete Dog.prototype.bark`, ma proviamo comunque ad accedervi. + +Quando proviamo a invocare qualcosa che non è una funzione, viene lanciato un `TypeError`. In questo caso `TypeError: pet.bark is not a function`, poiché `pet.bark` è `undefined`. + +
++ +#### Risposta: D + +L'oggetto `Set` è una collezione di valori _unici_: un valore può verificarsi solo una volta in un set. + +Abbiamo passato l'array `[1, 1, 2, 3, 4]` con il valore duplicato `1`. Poiché non possiamo avere due valori uguali in un set, uno di essi viene rimosso. Ciò risulta in `{1, 2, 3, 4}`. + +
++ +#### Risposta: C + +Un modulo importato è di _sola lettura_: non è quindi possibile modificare il modulo importato. Solo il modulo che li esporta può cambiarne il valore. + +Quando proviamo ad incrementare il valore di `myCounter`, viene generato un errore: perché `myCounter` è di sola lettura e non può essere modificato. + +
++ +#### Risposta: A + +L'operatore `delete` restituisce un valore booleano: `true` su una cancellazione riuscita, altrimenti restituirà `false`. Tuttavia, le variabili dichiarate con la parola chiave `var`, `const` o `let` non possono essere cancellate usando l'operatore `delete`. + +La variabile `name` è stata dichiarata con la chiave `const`, quindi la sua cancellazione non va a buon fine e viene restituito `false`. Quando impostiamo `age` uguale a `21`, abbiamo effettivamente aggiunto una proprietà chiamata `age` all'oggetto globale. Puoi eliminare con successo le proprietà dagli oggetti in questo modo, anche l'oggetto globale, quindi `delete age` restituisce `true`. + +
+
+
+#### Risposta: C
+
+Possiamo spacchettare i valori da un array o proprietà dagli oggetti attraverso la destrutturazione. Per esempio:
+
+```javascript
+[a, b] = [1, 2];
+```
+
+
+
+Il valore di `a` ora è `1`, e il valore di `b` è ora `2`. Quello che abbiamo effettivamente fatto nella domanda è:
+
+```javascript
+[y] = [1, 2, 3, 4, 5];
+```
+
+
+
+Questo significa che il valore di `y` è uguale al primo valore nell'array, che è il numero `1`. Quando registriamo `y`, viene restituito `1`.
+
+
+ +#### Risposta: B + +È possibile combinare oggetti utilizzando l'operatore spread `...`. Questo ti consente di creare copie delle coppie chiave/valore di un oggetto e aggiungerle a un altro oggetto. In questo caso, creiamo copie dell'oggetto `user` e le aggiungiamo all'oggetto `admin`. L'oggetto `admin` ora contiene le coppie chiave/valore copiate, che risultano in `{ admin: true, name: "Lydia", age: 21 }`. + +
++ +#### Risposta: B + +Con il metodo `defineProperty`, possiamo aggiungere nuove proprietà a un oggetto o modificare quelle esistenti. Quando aggiungiamo delle proprietà a un oggetto usando il metodo `defineProperty`, queste per impostazione predefinita sono _non enumerabili_. Il metodo `Object.keys` restituisce tutti i nomi di proprietà _enumerabili_ da un oggetto, in questo caso solo `"name"`. + +Le proprietà aggiunte usando il metodo `defineProperty` sono immutabili per impostazione predefinita. Puoi ignorare questo comportamento usando le proprietà `writable`, `configurable` ed `enumerable`. In questo modo, il metodo `defineProperty` ti dà molto più controllo sulle proprietà che stai aggiungendo a un oggetto. + +
++ +#### Risposta: A + +Il secondo argomento di `JSON.stringify` è _replacer_. Il replacer può essere una funzione o un array e consente di controllare cosa e come i valori devono essere stringati. + +Se il replacer è un _array_, solo i nomi delle proprietà inclusi nell'array verranno aggiunti alla stringa JSON. In questo caso, sono incluse solo le proprietà con i nomi `"level"` e `"health"`, `"username"` è esclusa. `data` quindi ora è uguale a `"{"level":19, "health":90}"`. + +Se il replacer è una _funzione_, questa funzione viene chiamata su ogni proprietà nell'oggetto che stai stringendo. Il valore restituito da questa funzione sarà il valore della proprietà quando viene aggiunto alla stringa JSON. Se il valore è `undefined`, questa proprietà viene esclusa dalla stringa JSON. + +
++ +#### Risposta: A + +L'operatore unario `++` _prima_ restituisce il valore dell'operando, _poi_ incrementa il valore dell'operando. Il valore di `num1` è `10`, poiché la funzione `increaseNumber` restituisce prima il valore di `num`, che è `10`, e solo successivamente incrementa il valore di `num`. + +`num2` è `10`, poiché abbiamo passato `num1` a `increasePassedNumber`. `number` è uguale a `10` (il valore di `num1`. Anche in questo caso, l'operatore unario `++` _prima_ restituisce il valore dell'operando, _poi_ lo incrementa. Il valore di `number` è ` 10`, quindi `num2` è uguale a `10`. + +
++ +#### Risposta: C + +In ES6, possiamo inizializzare i parametri con un valore predefinito. Il valore del parametro sarà il valore predefinito se nessun altro valore è stato passato alla funzione o se è stato passato un valore `"undefined"`. In questo caso, distribuiamo le proprietà dell'oggetto `value` in un nuovo oggetto, quindi `x` ha il valore predefinito di `{ number: 10 }`. + +L'argomento predefinito viene valutato quando viene chiamato! Ogni volta che chiamiamo la funzione, viene creato un _nuovo_ oggetto. Invochiamo la funzione `multiply` le prime due volte senza passare un valore, quindi `x` ha il valore predefinito di `{ number: 10 }`. Quindi logghiamo il valore moltiplicato di quel numero, che è `20`. + +La terza volta che invochiamo la funzione multiply, passiamo un argomento: l'oggetto chiamato `value`. L'operatore `*=` è in realtà un'abbreviazione per `x.number = x.number * 2`: modifichiamo il valore di `x.number` e logghiamo il valore moltiplicato `20`. + +La quarta volta, passiamo di nuovo l'oggetto `value`, in questo caso `x.number` è stato precedentemente modificato in `20`, quindi `x.number *= 2` logga `40`. + +
++ +#### Risposta: D + +Il primo argomento che il metodo `reduce` riceve è l'_accumulatore_, in questo caso `x`. Il secondo argomento è il _valore corrente_ `y`. +Con il metodo reduce, eseguiamo una funzione di callback su ogni elemento dell'array, che alla fine potrebbe risultare in un singolo valore. + +In questo esempio, non stiamo restituendo alcun valore, stiamo semplicemente loggando i valori dell'accumulatore e il valore corrente. + +Il valore dell'accumulatore è uguale al valore restituito in precedenza dalla funzione di callback. Se non si passa l'argomento opzionale `initialValue` al metodo `reduce`, l'accumulatore è uguale al primo elemento della prima chiamata. + +Alla prima chiamata, l'accumulatore (`x`) è `1` e il valore corrente (`y`) è `2`. Non facciamo un return con la funzione di callback ma logghiamo l'accumulatore e il valore corrente: `1` e `2` vengono loggati. + +Se non restituisci un valore da una funzione questa restituisce `undefined`. Alla chiamata successiva, l'accumulatore è `undefined` e il valore corrente è "3". `undefined` e `3` vengono loggati. + +Alla quarta chiamata, di nuovo non facciamo un return dalla funzione di callback. L'accumulatore è di nuovo `undefined` e il valore corrente è "4". `undefined` e `4` vengono loggati. +
++ +#### Risposta: B + +In una classe derivata, non puoi accedere alla chiave `this` prima di chiamare `super`. Se provi a farlo, genererà un ReferenceError: 1 e 4 genererebbero un errore di riferimento. + +Con la chiave `super`, chiamiamo il costruttore di quella classe parent con gli argomenti forniti. Il costruttore del parent riceve l'argomento `name`, quindi passiamo `name` a `super`. + +La classe `Labrador` riceve due argomenti, `name` poiché estende `Dog`, e `size` come proprietà extra sulla classe `Labrador`. Entrambi devono essere passati alla funzione di costruzione su `Labrador`, cosa che viene eseguita correttamente usando il costruttore 2. + +
++ +#### Risposta: B + +Con la chiave `import` tutti i moduli importati sono _pre-parsed_. Ciò significa che i moduli importati vengono eseguiti _prima_, il codice nel file che importa il modulo viene eseguito _dopo_. + +Questa è una delle differenze tra `require()` in CommonJS e `import`. Con `require()`, puoi caricare le dipendenze su richiesta mentre il codice è in esecuzione. Se avessimo usato `require` invece di `import`, sulla console avremmo loggato `running index.js`, `running sum.js`, `3`. + +
++ +#### Risposta: A + +Ogni Simbolo è unico. Lo scopo dell'argomento passato a Symbol è di dargli una descrizione. Il valore del Symbol non dipende dall'argomento passato. Mentre testiamo l'uguaglianza, stiamo creando due simboli completamente nuovi: il primo `Symbol('foo')` e il secondo `Symbol('foo')`. Questi due valori sono unici e non uguali tra loro, `Symbol('foo') === Symbol('foo')` quindi restituisce `false`. + +
++ +#### Risposta: C + +Con il metodo `padStart`, possiamo aggiungere un riempimento all'inizio di una stringa. Il valore passato a questo metodo è la lunghezza _totale_ della stringa insieme al riempimento. La stringa `"Lydia Hallie"` ha una lunghezza di `12`. `name.padStart(13)` inserisce quindi 1 spazio all'inizio della stringa, perché 12 + 1 è 13. + +Se l'argomento passato al metodo `padStart` è inferiore alla lunghezza dell'array, non verrà aggiunto alcun riempimento. + +
++ +#### Risposta: A + +Con l'operatore `+` puoi concatenare stringhe. In questo caso, stiamo concatenando la stringa `"🥑"` con la stringa `"💻"`, ottenendo `"🥑💻"`. + +
++ +#### Risposta: C + +Una funzione generator "mette in pausa" la sua esecuzione quando incontra la parola chiave `yield`. Innanzitutto dobbiamo lasciare che la funzione produca la stringa "Ami JavaScript?", che può essere eseguita chiamando `game.next().value`. + +Ogni riga viene quindi eseguita, finché non trova la prima chiave `yield`. C'è una parola chiave `yield` sulla prima riga all'interno della funzione: l'esecuzione si interrompe con il primo rendimento! _Questo significa che la variabile `answer` non è ancora definita!_ + +Quando chiamiamo `game.next("Yes").value`, il precedente `yield` viene sostituito con il valore dei parametri passati alla funzione `next()`, in questo caso `"Yes"`. Il valore della variabile `answer` è ora uguale a `"Yes"`. La condizione dell'istruzione if restituisce `false` e `JavaScript loves you back ❤️` viene registrato. + +
++ +#### Risposta: C + +`String.raw` restituisce una stringa in cui gli escape (`\n`, `\v`, `\t` ecc.) vengono ignorati! I backslash possono essere un problema poiché potresti finire con qualcosa del tipo: + +`` const path = `C:\Documents\Projects\table.html` `` + +Il che risulterebbe in: + +`"C:DocumentsProjects able.html"` + +Con `String.raw`, il compilatore ignorerebbe semplicemente l'escape e stamperebbe: + +`C:\Documents\Projects\table.html` + +In questo caso, è la stringa `Hello\nworld` che viene loggata. + +
++ +#### Risposta: C + +Una funzione asincrona restituisce sempre una promise. L'`await` deve ancora attendere che la promise si risolva: una promise in sospeso viene restituita quando chiamiamo `getData()` per impostare `data` uguale ad essa. + +Se volessimo accedere al valore risolto `"I made it"`, potremmo usare il metodo `.then()` su `data`: + +`data.then(res => console.log(res))` + +Questo avrebbe loggato `"I made it!"` + +
++ +#### Risposta: B + +Il metodo `.push()` restituisce la _lunghezza_ del nuovo array! +Inizialmente, l'array conteneva un solo elemento (la stringa `"banana"`) e aveva una lunghezza di `1`. Dopo aver aggiunto la stringa `"apple"` allo stesso array, questo contiene due elementi e ha una lunghezza di `2` + +Attraverso la funzione `addToList`, il metodo `push` modifica l'array originale. +Per restituire l'_array_ dalla funzione invece della _lunghezza dell'array_, serve fare un return di `list` dopo aver inserito l'`item`. + +
++ +#### Risposta: B + +`Object.freeze` rende impossibile aggiungere, rimuovere o modificare le proprietà di un oggetto (a meno che il valore della proprietà non sia un altro oggetto). + +Quando creiamo la variabile `shape` e la impostiamo come all'oggetto congelato `box`, anche `shape` si riferisce ad un oggetto congelato. +Puoi controllare se un oggetto è congelato usando `Object.isFrozen`. In questo caso, `Object.isFrozen(shape)` restituisce true, poiché la variabile `shape` ha un riferimento a un oggetto congelato. + +Poiché `shape` è congelata, e poiché il valore di `x` non è un oggetto, non possiamo modificare la proprietà `x`. +`x` è ancora uguale a `10` e `{ x: 10, y: 20 }` viene loggato. + +
++ +#### Risposta: C + +Quando spacchettiamo la proprietà `name` dall'oggetto, assegniamo il suo valore `"Lydia"` a una variabile con il nome `myName`. + +Con `{ name: myName }`, diciamo a JavaScript che vogliamo creare una nuova variabile chiamata `myName` con il valore della proprietà `name`. + +Poiché proviamo a loggare `name`, una variabile che non è definita, viene restituito `undefined` nell'assegnazione. Successivamente, il valore di `Lydia` viene memorizzato tramite l'assegnazione di destrutturazione. + +
++ +#### Risposta: A + +Una funzione pura è una funzione che restituisce _sempre_ lo stesso risultato, se vengono passati gli stessi argomenti. + +La funzione `sum` restituisce sempre lo stesso risultato. Se le passiamo `1` e `2`, restituirà _sempre_ `3` senza effetti collaterali. Se passiamo `5` e `10`, restituirà _sempre_ `15` e così via. Questa è la definizione di funzione pura. + +
++ +#### Risposta: C + +La funzione `add` è una funzione _memoizzata_. Con la memorizzazione, possiamo memorizzare nella cache i risultati di una funzione per velocizzarne l'esecuzione. +In questo caso, creiamo un oggetto `cache` che memorizza i valori precedentemente restituiti. + +Se chiamiamo di nuovo la funzione `addFunction` con lo stesso argomento, prima controlla se ha già ottenuto quel valore nella sua cache, in tal caso, verrà restituito il valore della cache, consentendo di risparmiare tempo di esecuzione. Altrimenti, se non è memorizzato nella cache, calcolerà il valore e lo memorizzerà in seguito. + +Chiamiamo la funzione `addFunction` tre volte con lo stesso valore: alla prima chiamata, il valore della funzione quando `num` è uguale a `10` non è ancora memorizzato nella cache. +La condizione dell'istruzione if `num in cache` restituisce `false`, e il blocco else viene eseguito: `Calculated! 20` viene loggato e il valore del risultato viene aggiunto all'oggetto cache. +`cache` ora è uguale a `{ 10: 20 }`. + +La seconda volta, l'oggetto `cache` contiene il valore che viene restituito per `10`. La condizione dell'istruzione if `num in cache` restituisce `true` e `'From cache! 20'` viene loggato. + +La terza volta, passiamo `5 * 2` alla funzione che viene valutata a `10`. L'oggetto `cache` contiene il valore che viene restituito `10`. La condizione dell'istruzione if `num in cache` restituisce `true` e `'From cache! 20'` viene registrato. + +
++ +#### Risposta: A + +Con un ciclo _for-in_, possiamo scorrere su proprietà **enumerabili**. In un array, le proprietà enumerabili sono le "chiavi" degli elementi dell'array, che sono in realtà i loro indici. Potresti immaginare un array come: + +`{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}` + +Dove le chiavi sono le proprietà enumerabili. `0` `1` `2` `3` viene quindi loggato. + +Con un ciclo _for-of_, possiamo iterare su **iterabili**. Un array è un iterabile. Quando iteriamo sull'array, la variabile "item" è uguale all'elemento su cui sta attualmente iterando, `"☕"` `"💻"` `"🍷"` `"🍫"` viene loggato. + +
++ +#### Risposta: C + +Gli elementi di un array possono contenere qualsiasi valore. Numeri, stringhe, oggetti, altri array, null, booleani, undefined e altre espressioni come date, funzioni e calcoli. + +L'elemento sarà uguale al valore restituito. `1 + 2` restituirà quindi `3`, `1 * 2` restituirà `2` e `1 / 2` restituirà `0.5`. + +
++ +#### Risposta: B + +Di default, gli argomenti hanno il valore di `undefined`, a meno che un valore non sia stato passato alla funzione. In questo caso, non abbiamo passato un valore per l'argomento `name`. `name` è uguale a `undefined` che viene loggato. + +In ES6, possiamo sovrascrivere questo valore predefinito `undefined` con dei parametri predefiniti. Per esempio: + +`function sayHi(name = "Lydia") { ... }` + +In questo caso, se non abbiamo passato un valore o se abbiamo passato `undefined`, `name` sarà sempre uguale alla stringa `Lydia` + +
++ +#### Risposta: B + +Il valore della parola chiave `this` dipende da dove la usi. In un **metodo**, come il metodo `getStatus`, la parola chiave `this` si riferisce all'_oggetto a cui appartiene il metodo_. Nel nostro caso il metodo appartiene all'oggetto `data`, quindi `this` si riferisce all'oggetto `data`. Quando logghiamo `this.status`, stiamo chiedendo la proprietà `status` sull'oggetto `data` che è `"🥑"`. + +Con il metodo `call` possiamo cambiare l'oggetto a cui fa riferimento la parola chiave `this`. Nelle **funzioni**, la parola chiave `this` si riferisce all'_oggetto a cui appartiene la funzione_. Abbiamo dichiarato la funzione `setTimeout` sull'_oggetto globale_, quindi all'interno della funzione `setTimeout`, la parola chiave `this` si riferisce all'_oggetto globale_. Sull'oggetto globale c'è una variabile chiamata _status_ con il valore di `"😎"`. Quando si fa un console.log di `this.status`, otteniamo `"😎"`. + +
++ +#### Risposta: A + +Impostiamo la variabile `city` uguale al valore della proprietà chiamata `city` sull'oggetto `person`. Non c'è alcuna proprietà su questo oggetto chiamato `city`, quindi la variabile `city` ha il valore di `undefined`. + +Nota che _non_ stiamo facendo riferimento all'oggetto `person`! Impostiamo semplicemente la variabile `city` uguale al valore corrente della proprietà `city` sull'oggetto `person`. + +Quindi, impostiamo `city` uguale alla stringa `"Amsterdam"`. Questo non cambia l'oggetto `person`: non c'è alcun riferimento a quell'oggetto. + +Quando si logga l'oggetto `person`, viene restituito l'oggetto non modificato. + +
++ +#### Risposta: C + +Le variabili con la chiave `const` e `let` sono _block-scoped_. Un blocco è qualsiasi cosa si trovi tra parentesi graffe (`{ }`). In questo caso, le parentesi graffe delle istruzioni if/else. Non puoi fare riferimento a una variabile al di fuori del blocco in cui è dichiarata, viene quindi generato un ReferenceError. + +
++ +#### Risposta: C + +Il valore di `res` nel secondo `.then` è uguale al valore restituito del precedente `.then`. Puoi continuare a concatenare i `.then` in questo modo, dove il valore viene passato al gestore successivo. + +
++ +#### Risposta: A + +Con `!!name`, determiniamo se il valore di `name` è vero o falso. Se il nome è vero, cosa che vogliamo testare, `!name` restituisce `false`. +`!false` (che è `!!name`) restituisce `true`. + +Impostando `hasName` uguale a `name`, imposti `hasName` uguale a qualsiasi valore passato alla funzione `getName`, non il valore booleano `true`. + +`new Boolean(true)` restituisce un oggetto wrapper, non il valore booleano stesso. + +`name.length` restituisce la lunghezza dell'argomento passato, non se è `true`. + +
++ +#### Risposta: B + +Per ottenere un carattere in un indice specifico di una stringa, puoi usare la notazione tra parentesi. Il primo carattere nella stringa ha indice 0 e così via. In questo caso, vogliamo ottenere l'elemento con indice 0, il carattere `"I'`, che viene loggato. + +Tieni presente che questo metodo non è supportato in IE7 e versioni precedenti. In tal caso, usa `.charAt()`. + +
++ +#### Risposta: B + +È possibile impostare il valore di un parametro predefinito uguale a un altro parametro della funzione, purché sia stato definito _prima_ del parametro predefinito. Passiamo il valore `10` alla funzione `sum`. Se la funzione `sum` riceve solo 1 argomento, significa che il valore di `num2` non è passato e il valore di `num1` è uguale al valore passato `10` in questo caso. Il valore predefinito di `num2` è il valore di `num1`, che è `10`. `num1 + num2` restituisce `20`. + +Se stai cercando di impostare il valore di un parametro predefinito uguale a un parametro che è definito _dopo_ (a destra), il valore del parametro non è stato ancora inizializzato, il che genererà un errore. +
++ +#### Risposta: A + +Con la sintassi `import * as name`, importiamo _tutte le esportazioni_ dal file `module.js` nel file `index.js` come nuovo oggetto chiamato `data`. Nel file `module.js` ci sono due esportazioni: l'esportazione predefinita e un'esportazione denominata. L'esportazione predefinita è una funzione che restituisce la stringa `"Hello World"`, e l'esportazione denominata è una variabile chiamata `name` che ha il valore della stringa `"Lydia"`. + +L'oggetto `data` ha una proprietà `default` per l'esportazione predefinita, altre proprietà hanno i nomi delle esportazioni e i loro valori corrispondenti. + +
++ +#### Risposta: C + +Le classi sono come caramelle sintattiche. L'equivalente della classe `Person` come funzione sarebbe: + +```javascript +function Person() { + this.name = name; +} +``` + +Instanziando un costruttore con `new` si ottiene la creazione di un'istanza di `Person`, la chiave `typeof` restituisce `"object"`. `typeof member` restituisce `"object"`. + +
++ +#### Risposta: D + +Il metodo `.push` restituisce la _nuova lunghezza_ dell'array, non l'array stesso! Impostando `newList` uguale a `[1, 2, 3].push(4)`, settiamo `newList` uguale alla nuova lunghezza dell'array: `4`. + +Quindi quando proviamo a usare il metodo `.push` su `newList` poiché `newList` è il valore numerico `4`, non possiamo usare il metodo `.push` e viene generato un TypeError. + +
++ +#### Risposta: D + +Le funzioni regolari, come la funzione `giveLydiaPizza`, hanno una proprietà `prototipo`, che è un oggetto (prototype object) con un `costruttore`. Tuttavia, le arrow functions, come la funzione `giveLydiaChocolate`, non hanno una proprietà `prototype`. Viene quindi restituito `undefined` quando si tenta di accedere alla proprietà `prototype` usando `giveLydiaChocolate.prototype`. +
++ +#### Risposta: A + +`Object.entries(person)` restituisce un array di array nidificati, contenente le chiavi e gli oggetti: + +`[ [ 'name', 'Lydia' ], [ 'age', 21 ] ]` + +Usando il ciclo `for-of`, possiamo scorrere ogni elemento nell'array, i sottoarray in questo caso. Possiamo destrutturare i sottoarray istantaneamente nel ciclo for-of, usando `const [x, y]`. `x` è uguale al primo elemento, `y` è uguale al secondo elemento. + +Il primo sottoarray è `[ "name", "Lydia" ]`, con `x` uguale a `"name"`, e `y` uguale a `"Lydia"`, che vengono loggati. +Il secondo sottoarray è `[ "age", 21 ]`, con `x` uguale a `"age"`, e `y` uguale a `21`, che vengono loggati. + +
++ +#### Risposta: D + +`...args` è un parametro rest. Il valore del parametro rest è un array contenente tutti gli argomenti, **e può essere solo l'ultimo parametro**! In questo esempio, il parametro rest è in seconda posizione. Questo non è possibile e genererà un errore di sintassi. + +```javascript +function getItems(fruitList, favoriteFruit, ...args) { + return [...fruitList, ...args, favoriteFruit]; +} + +getItems(['banana', 'apple'], 'pear', 'orange'); +``` + +L'esempio qui sopra invece funziona e restituisce l'array `[ 'banana', 'apple', 'orange', 'pear' ]` + +
++ +#### Risposta: B + +In JavaScript, non _è necessario_ scrivere il punto e virgola (`;`) in modo esplicito poiché il motore JavaScript li aggiunge comunque dopo le istruzioni. +Questo procedimento è chiamato **Automatic Semicolon Insertion**. Un'istruzione può ad esempio essere una variabile o parole chiave come `throw`, `return`, `break`, ecc. + +Qui, abbiamo scritto un'istruzione di `return` e un altro valore `a + b` su una _nuova riga_. Tuttavia, trattandosi di una nuova linea, il motore non sa che in realtà è il valore che volevamo restituire. Invece, ha aggiunto automaticamente un punto e virgola dopo `return`. + +Potresti considerare ad esempio: + +```javascript +return; +a + b; +``` + +`a + b` non viene mai raggiunto, poiché la funzione smette di funzionare dopo la parola chiave `return`. +Se non viene restituito alcun valore, come qui, la funzione restituisce `undefined`. Nota: non c'è un inserimento automatico dopo le istruzioni `if/else`! + +
++ +#### Risposta: B + +Possiamo impostare classi uguali ad altre classi/costruttori di funzioni. In questo caso, impostiamo `Person` uguale a `AnotherPerson`. Il name su questo costruttore è `Sarah`, quindi la proprietà del nome di`Person` sulla nuova istanza `member` è `"Sarah"`. + +
++ +#### Risposta: D + +Un simbolo non è _enumerabile_. Il metodo Object.keys restituisce tutte le proprietà _enumerabili_ su un oggetto. Il simbolo non sarà visibile e verrà restituito un array vuoto. Quando si logga l'intero oggetto, tutte le proprietà saranno visibili, anche quelle non enumerabili. + +Questa è una delle tante qualità di un simbolo: oltre a rappresentare un valore del tutto univoco (che evita collisioni accidentali di nomi sugli oggetti, ad esempio quando si lavora con 2 librerie che vogliono aggiungere proprietà allo stesso oggetto), puoi anche "nascondere" proprietà sugli oggetti in questo modo (anche se non del tutto. Puoi comunque accedere ai simboli usando il metodo `Object.getOwnPropertySymbols()`). + +
++ +#### Risposta: A + +La funzione `getList` riceve un array come argomento. Tra le parentesi della funzione `getList`, destrutturiamo subito questo array. Esempio: + +`[x, ...y] = [1, 2, 3, 4]` + +Con il parametro rest `...y`, mettiamo tutti gli argomenti "rimanenti" in un array. Gli argomenti rimanenti sono `2`, `3` e `4` in questo caso. +Il valore di `y` è un array, contenente tutti i parametri rimanenti. Il valore di `x` è uguale a `1` in questo caso, quindi quando facciamo un console.log di `[x, y]`, viene loggato `[1, [2, 3, 4]]`. + +La funzione `getUser` riceve un oggetto. Con le arrow functions, non _è necessario_ scrivere parentesi graffe se restituiamo solo un valore. Tuttavia, se vuoi restituire istantaneamente un _oggetto_ da una arrow function, devi scriverlo tra parentesi tonde, altrimenti tutto ciò che si trova tra le due parentesi graffe verrà interpretato come un'istruzione di blocco. In questo caso il codice tra parentesi non è un codice JavaScript valido, quindi viene generato un `SyntaxError`. + +La seguente funzione avrebbe restituito un oggetto: + +`const getUser = user => ({ name: user.name, age: user.age })` + +
++ +#### Risposta: C + +La variabile `name` contiene il valore di una stringa, che non è una funzione, quindi non può essere invocata. + +I TypeErrors vengono generati quando un valore non è del tipo previsto. JavaScript "prevede" che `name` è una funzione poiché stiamo cercando di invocarla. In realtà è una stringa, quindi viene generato un TypeError: name is not a function! + +I SyntaxErrors vengono generati quando si scrive qualcosa che non è valido in JavaScript, ad esempio quando si scrive la parola `return` come `rerun`. +I ReferenceErrors vengono generati quando JavaScript non è in grado di trovare un riferimento a un valore a cui stai tentando di accedere. + +
++ +#### Risposta: B + +`[]` è un valore vero. Con l'operatore `&&`, verrà restituito il valore di destra se il valore di sinistra è un valore reale. In questo caso, il valore di sinistra `[]` è un valore vero, quindi `"Im'` viene restituito. + +`""` è un valore falso. Se il valore di sinistra è falso, non viene restituito nulla. `n't` quindi non viene restituito. + +
++ +#### Risposta: C + +Con l'operatore `||` possiamo restituire il primo operando veritiero. Se tutti i valori sono falsi, viene restituito l'ultimo operando. + +`(false || {} || null)`: l'oggetto vuoto `{}` è un valore veritiero. Questo è il primo (e unico) valore veritiero, che viene restituito. `one` è uguale a `{}`. + +`(null || false || "")`: tutti gli operandi sono valori falsi. Ciò significa che viene restituito l'ultimo operando, `""`. `two` è uguale a `""`. + +`([] || 0 || "")`: l'array vuoto`[]` è un valore veritiero. Questo è il primo valore veritiero, che viene restituito. `three` è uguale a `[]`. + +
++ +#### Risposta: D + +Con una promise, in pratica diciamo _Voglio eseguire questa funzione, ma per ora la metto da parte mentre è in esecuzione poiché ciò potrebbe richiedere del tempo. Solo quando un determinato valore viene risolto (o rifiutato) e quando lo stack di chiamate è vuoto, voglio utilizzare questo valore._ + +Possiamo ottenere questo valore sia con `.then` che con la chiave `await` in una funzione `async`. Sebbene possiamo ottenere il valore di una promise sia con `.then` che con `await`, funzionano in modo leggermente diverso. + +Nella `first Function`, abbiamo (più o meno) messo da parte la funzione myPromise mentre era in esecuzione, ma abbiamo continuato a eseguire l'altro codice, che in questo caso è `console.log('second')`. Quindi, la funzione è stata risolta con la stringa `I have resolved`, che è stata quindi loggata dopo aver visto che lo stack di chiamate era vuoto. + +Con await in `secondFunction`, mettiamo letteralmente in pausa l'esecuzione di una funzione asincrona fino a quando il valore non è stato risolto prima di passare alla riga successiva. + +Ciò significa che ha aspettato che `myPromise` si risolvesse con il valore `I have resolved`, e solo allora, siamo passati alla riga successiva e `second` è stato loggato. + +
++ +#### Risposta: C + +L'operatore `+` non viene utilizzato solo per aggiungere valori numerici, ma possiamo anche usarlo per concatenare stringhe. Ogni volta che il motore JavaScript vede che uno o più valori non sono un numero, forza il numero in una stringa. + +Il primo è `1`, che è un valore numerico. `1 + 2` restituisce il numero 3. + +Tuttavia, la seconda è una stringa `"Lydia"`. `"Lydia"` è una stringa e `2` è un numero: `2` viene forzato in una stringa. `"Lydia"` e `"2"` vengono concatenati, il che risulta nella stringa `"Lydia2"`. + +`{ name: "Lydia" }` è un oggetto. Né un numero né un oggetto sono una stringa, quindi li rende stringhe entrambi. Ogni volta che stringhiamo un oggetto regolare, diventa `"[object Object]"`. `"[object Object]"` concatenato con `2` diventa `"[object Object]"`. + +
+
+
+#### Risposta: C
+
+Possiamo passare a `Promise.resolve` qualsiasi tipo di valore desideriamo, sia una promise che una non-promise. Il metodo stesso restituisce una promise con il valore risolto (`
+ +#### Risposta: B + +Gli oggetti vengono passati per riferimento. Quando controlliamo gli oggetti per strict equality (`===`), stiamo confrontando i loro riferimenti. + +Abbiamo impostato il valore predefinito per `person2` uguale all'oggetto `person` e abbiamo passato l'oggetto `person` come valore per `person1`. + +Ciò significa che entrambi i valori hanno un riferimento allo stesso punto in memoria, quindi sono uguali. + +Il blocco di codice nell'istruzione `else` viene eseguito e `They are the same!` viene loggato. + +
++ +#### Risposta: D + +In JavaScript, abbiamo due modi per accedere alle proprietà di un oggetto: le bracket notation o le dot notation. In questo esempio, utilizziamo la notazione con il punto (`colorConfig.colors`) invece della notazione tra parentesi (`colorConfig["colors"]`). + +Con la notazione del punto, JavaScript tenta di trovare la proprietà sull'oggetto con quel nome esatto. In questo esempio, JavaScript tenta di trovare una proprietà chiamata `colors` sull'oggetto `colorConfig`. Non esiste una proprietà chiamata `colors`, quindi restituisce `undefined`. Quando proviamo ad accedere al valore del primo elemento usando `[1]`, non possiamo farlo su un valore che è `undefined`, quindi genera un `TypeError`: `Cannot read property '1' of undefined`. + +JavaScript interpreta (o decomprime) le istruzioni. Quando usiamo la notazione tra parentesi, vede la prima parentesi aperta `[` e continua finché non trova la parentesi chiusa `]`. Solo allora valuterà la dichiarazione. Se avessimo usato `colorConfig[colors[1]]`, avrebbe restituito il valore della proprietà `red` sull'oggetto `colorConfig`. + +
++ +#### Risposta: A + +Le emoji sono unicode. L'unicode per l'emoji del cuore è `"U+2764 U+FE0F"`. Questi sono sempre gli stessi per gli stessi emoji, stiamo confrontando due stringhe uguali tra loro, e quindi restituisce true. + +
++ +#### Risposta: D + +Con il metodo `splice` modifichiamo l'array originale cancellando, sostituendo o aggiungendo elementi. In questo caso, abbiamo rimosso 2 elementi dall'indice 1 (abbiamo rimosso `'🥑'` e `'😍'`) e aggiunto invece l'emoji ✨. + +`map`, `filter` e `slice` restituiscono un nuovo array, `find` restituisce un elemento e `reduce` restituisce un valore ridotto. +
++ +#### Risposta: A + +Impostiamo il valore della proprietà `favoriteFood` sull'oggetto `info` uguale alla stringa con l'emoji della pizza, `'🍕'`. Una stringa è un tipo di dati primitivo. In JavaScript, i tipi di dati primitivi non interagiscono per riferimento. + +In JavaScript, i tipi di dati primitivi (tutto ciò che non è un oggetto) interagiscono per _value_. In questo caso, impostiamo il valore della proprietà `favoriteFood` sull'oggetto `info` uguale al valore del primo elemento nell'array `food`, in questo caso la stringa con l'emoji della pizza (`'🍕'`). Una stringa è un tipo di dati primitivo e interagisce per valore (vedi il mio [blogpost](https://www.theavocoder.com/complete-javascript/2018/12/21/by-value-vs-by-reference) se sei interessato a saperne di più). + +Quindi, cambiamo il valore della proprietà `favoriteFood` sull'oggetto `info`. L'array `food` non è cambiato, poiché il valore di `favoriteFood` era semplicemente una _copia_ del valore del primo elemento nell'array e non ha un riferimento allo stesso punto in memoria dell'elemento su ` food[0]`. Quando logghiamo food, è ancora l'array originale, `['🍕', '🍫', '🥑', '🍔']`. +
++ +#### Risposta: A + +Con il metodo `JSON.parse()`, possiamo analizzare la stringa JSON come un valore JavaScript. + +```javascript +// Stringhiamo un numero in un JSON valido, quindi analizziamo la stringa JSON come valore JavaScript: +const jsonNumber = JSON.stringify(4); // '4' +JSON.parse(jsonNumber); // 4 + +// Stringhiamo un array in un JSON valido, quindi analizziamo la stringa JSON come valore JavaScript: +const jsonArray = JSON.stringify([1, 2, 3]); // '[1, 2, 3]' +JSON.parse(jsonArray); // [1, 2, 3] + +// Stringhiamo un object in un JSON valido, quindi analizziamo la stringa JSON come valore JavaScript: +const jsonArray = JSON.stringify({ name: 'Lydia' }); // '{"name":"Lydia"}' +JSON.parse(jsonArray); // { name: 'Lydia' } +``` + +
++ +#### Risposta: D + +Ogni funzione ha il proprio _contesto di esecuzione_ (o _ambito_). La funzione `getName` cerca prima all'interno del proprio contesto (scope) per vedere se contiene la variabile `name` a cui stiamo cercando di accedere. In questo caso, la funzione `getName` contiene la propria variabile `name` perché dichiariamo la variabile `name` con la chiave `let`, e con il valore di `'Sarah'`. + +Le variabili con la chiave `let` (e `const`) vengono sollevate, ma a differenza di `var`, non vengono inizializzate. Non sono quindi accessibili prima della riga in cui le dichiariamo (inizializziamo). Questa è chiamata "temporal dead zone". Quando proviamo ad accedere alle variabili prima che vengano dichiarate, JavaScript genera un `ReferenceError`. + +Se non avessimo dichiarato la variabile `name` all'interno della funzione `getName`, JavaScript avrebbe esaminato la _scope chain_. Lo scope esterno ha una variabile chiamata `name` con il valore di `Lydia`. In tal caso, avrebbe loggato "Lydia". + +```javascript +let name = 'Lydia'; + +function getName() { + console.log(name); +} + +getName(); // Lydia +``` + +
++ +#### Risposta: C + +Con la parola chiave `yield`, otteniamo valori in una funzione generatore. Con la chiave `yield*`, possiamo produrre valori da un'altra funzione del generatore, o da un oggetto iterabile (per esempio un array). + +In `generatorOne`, produciamo l'intero array `['a', 'b', 'c']` usando la parola chiave `yield`. Il valore della proprietà `value` sull'oggetto restituito dal metodo `next` su `one` (`one.next().value`) è uguale all'intero array `['a', 'b', 'c']`. + +```javascript +console.log(one.next().value); // ['a', 'b', 'c'] +console.log(one.next().value); // undefined +``` + +In `generatorTwo`, utilizziamo la parola chiave `yield*`. Ciò significa che il primo valore ottenuto è `two`, ed è uguale al primo valore ottenuto nell'iteratore. L'iteratore è l'array `['a', 'b', 'c']`. Il primo valore ottenuto è `a`, quindi la prima volta che chiamiamo `two.next().value`, viene restituito `a`. + +```javascript +console.log(two.next().value); // 'a' +console.log(two.next().value); // 'b' +console.log(two.next().value); // 'c' +console.log(two.next().value); // undefined +``` + +
++ +#### Risposta: A + +Le espressioni all'interno dei template literals vengono valutate per prime. Ciò significa che la stringa conterrà il valore restituito dell'espressione, in questo caso la funzione immediatamente invocata `(x => x)('I love')`. Passiamo il valore `'I love'` come argomento alla funzione freccia `x => x`. `x` è uguale a `'I love'`, che viene restituito. Ciò si traduce in `I love to program`. + +
++ +#### Risposta: C + +Normalmente quando impostiamo oggetti uguali a `null`, quegli oggetti vengono _garbage collected_ poiché non c'è più alcun riferimento a quell'oggetto. Tuttavia, poiché la funzione di callback all'interno di `setInterval` è una funzione freccia (quindi legata all'oggetto `config`), la funzione di callback mantiene ancora un riferimento all'oggetto `config`. +Finché c'è un riferimento, l'oggetto non verrà raccolto. +Poiché si tratta di un intervallo, impostare `config` su `null` o `delete`-ing `config.alert` non raccoglierà l'intervallo, quindi l'intervallo verrà comunque chiamato. +Dovrebbe essere cancellato con `clearInterval(config.alert)` per rimuoverlo dalla memoria. +Dal momento che non è stato cancellato, la funzione di callback `setInterval` verrà comunque invocata ogni 1000 ms (1 s). + +
++ +#### Risposta: B + +Quando si aggiunge una coppia chiave/valore usando il metodo `set`, la chiave sarà il valore del primo argomento passato alla funzione `set`, e il valore sarà il secondo argomento. La chiave è _function_ `() => 'greeting'` in questo caso, e il valore `'Hello world'`. `myMap` ora è `{ () => 'greeting' => 'Hello world!' }`. + +1 è sbagliato, poiché la chiave non è `'greeting'` ma `() => 'greeting'`. +3 è sbagliato, poiché stiamo creando una nuova funzione passandola come parametro al metodo `get`. L'oggetto interagisce per _reference_. Le funzioni sono oggetti, che è il motivo per cui due funzioni non sono mai rigorosamente uguali, anche se identiche: hanno un riferimento a un punto diverso della memoria. + +
++ +#### Risposta: C + +Entrambe le funzioni `changeAge` e `changeAgeAndName` hanno un parametro predefinito, ovvero un oggetto _appena_ creato `{ ...person }`. Questo oggetto ha copie di tutte le chiavi/valori nell'oggetto `person`. + +Per prima cosa, invochiamo la funzione `changeAge` e passiamo l'oggetto `person` come argomento. Questa funzione aumenta il valore della proprietà `age` di 1. `person` ora è `{ name: "Lydia", age: 22 }`. + +Quindi, invochiamo la funzione `changeAgeAndName`, tuttavia non passiamo un parametro. Invece, il valore di `x` è uguale a un _nuovo_ oggetto: `{ ...person }`. Poiché si tratta di un nuovo oggetto, non influisce sui valori delle proprietà sull'oggetto `person`. `person` è ancora uguale a `{ name: "Lydia", age: 22 }`. +
++ +#### Risposta: C + +Con l'operatore spread `...`, possiamo _distribuire_ gli iterabili come singoli elementi. La funzione `sumValues` riceve tre argomenti: `x`, `y` e `z`. `...[1, 2, 3]` risulterà in `1, 2, 3`, che passiamo alla funzione `sumValues`. + +
++ +#### Risposta: B + +Con l'operando `+=`, stiamo incrementando il valore di `num` di `1`. `num` aveva il valore iniziale `1`, quindi `1 + 1` è `2`. L'elemento sul secondo indice nell'array `list` è 🥰, `console.log(list[2])` stampa 🥰. + +
++ +#### Risposta: B + +Con l'operatore di concatenamento opzionale `?.`, non è più necessario verificare esplicitamente se i valori annidati più profondi sono validi o meno. Se stiamo cercando di accedere a una proprietà su un valore `undefined` o `null` (_nullish_), l'espressione va in cortocircuito e restituisce `undefined`. + +`person.pet?.name`: `person` ha una proprietà denominata `pet`: `person.pet` non è nullo. Ha una proprietà chiamata `name` e restituisce `Mara`. +`person.pet?.family?.name`: `person` ha una proprietà denominata `pet`: `person.pet` non è nullo. `pet` _non_ ha una proprietà chiamata `family`, `person.pet.family` è nullo. L'espressione restituisce `undefined`. +`person.getFullName?.()`: `person` ha una proprietà denominata `getFullName`: `person.getFullName()` non è nullo e può essere invocato, il che restituisce `Lydia Hallie`. +`member.getLastName?.()`: la variabile `member` non esiste quindi viene generato un `ReferenceError`! + +
++ +#### Risposta: B + +Abbiamo passato la condizione `groceries.indexOf("banana")` all'istruzione if. `groceries.indexOf("banana")` restituisce `0`, che è un valore falso. Poiché la condizione nell'istruzione if è falsa, il codice nel blocco `else` viene eseguito e `We don't have to buy bananas!` viene registrato. + +
++ +#### Risposta: D + +Il metodo `language` è un `setter`. I setter non detengono un valore effettivo, il loro scopo è _modificare_ le proprietà. Quando si chiama un metodo `setter`, viene restituito `undefined`. + +
++ +#### Risposta: C + +`typeof name` restituisce `"string"`. La stringa `"string"` è un valore veritiero, quindi `!typeof name` restituisce il valore booleano `false`. `false === "object"` e `false === "string"` restituiscono entrambi `false`. + +(Se volessimo verificare se il tipo era (non)uguale a un certo tipo, avremmo dovuto scrivere `!==` invece di `!typeof`) +
++ +#### Risposta: A + +La funzione `add` restituisce una arrow function, che restituisce una arrow function, che restituisce arrow function (mi segui ancora?). +La prima funzione riceve un argomento `x` con il valore di `4`. Invochiamo la seconda funzione, che riceve un argomento `y` con il valore `5`. Quindi invochiamo la terza funzione, che riceve un argomento `z` con il valore `6`. Quando si tenta di accedere ai valori `x`, `y` e `z` all'interno dell'ultima arrow function, il motore JS risale la catena dell'ambito per trovare i valori per `x` e `y`. Questo restituisce `4` `5` `6`. + +
++ +#### Risposta: C + +La funzione `range` restituisce un oggetto asincrono con promises per ogni elemento nell'intervallo che passiamo: `Promise{1}`, `Promise{2}`, `Promise{3}`. Impostiamo la variabile `gen` uguale all'oggetto asincrono, dopodiché lo eseguiamo in loop usando un ciclo `for await ... of`. Impostiamo la variabile `item` uguale ai valori Promise restituiti: prima `Promise{1}`, poi `Promise{2}`, quindi `Promise{3}`. Poiché stiamo _attendendo_ il valore di `item`, la promise risolta, vengono restituiti i _valori_ risolti delle promises: `1`, `2` e quindi `3`. + +
++ +#### Risposta: D + +`myFunc` si aspetta un oggetto con le proprietà `x`, `y` e `z` come argomento. Poiché stiamo passando solo tre valori numerici separati (1, 2, 3) invece di un oggetto con le proprietà `x`, `y` e `z` ({x: 1, y: 2, z: 3}), `x`, `y` e `z` hanno il loro valore predefinito di `undefined`. + +
++ +#### Risposta: B + +Con il metodo `Intl.NumberFormat`, possiamo formattare i valori numerici in qualsiasi locale. Formattiamo il valore numerico `130` nella locale `en-US` come `unit` in `mile-per-hour`, che risulta in `130 mph`. Il valore numerico `300` nella locale `en-US` come `currency` in `USD` risulta in `$300.00`. + +
++ +#### Risposta: B + +Destrutturando gli oggetti, possiamo decomprimere i valori dall'oggetto di destra e assegnare il valore decompresso al valore dello stesso nome di proprietà sull'oggetto di sinistra. In questo caso, stiamo assegnando il valore "💀" a `spookyItems[3]`. Ciò significa che stiamo modificando l'array `spookyItems`, stiamo aggiungendo il "💀" ad esso. Quando facciamo console.log di `spookyItems`, `["👻", "🎃", "🕸", "💀"]` viene loggato. + +
++ +#### Risposta: C + +Con il metodo `Number.isNaN`, puoi controllare se il valore passato è un _valore numerico_ e uguale a `NaN`. `name` non è un valore numerico, quindi `Number.isNaN(name)` restituisce `false`. `age` è un valore numerico, ma non è uguale a `NaN`, quindi `Numero.isNaN(age)` restituisce `false`. + +Con il metodo `isNaN`, puoi verificare se il valore che passi non è un numero. `name` non è un numero, quindi `isNaN(name)` restituisce true. `age` è un numero, quindi `isNaN(age)` restituisce `false`. +
++ +#### Risposta: D + +Le variabili dichiarate con la chiave `const` non sono referenziabili prima della loro inizializzazione: questa viene chiamata _temporal dead zone_. Nella funzione `getInfo`, la variabile `randomValue` ha lo scopo nell'ambito funzionale di `getInfo`. Nella riga in cui vogliamo registrare il valore di `typeof randomValue`, la variabile `randomValue` non è ancora inizializzata: viene lanciato un `ReferenceError`! Il motore non è andato giù per la catena dell'ambito poiché abbiamo dichiarato la variabile `randomValue` nella funzione `getInfo`. +
++ +#### Risposta: C + +Nel blocco `try`, stiamo loggando il valore atteso della variabile `myPromise`: `"Woah some cool data"`. Poiché non sono stati generati errori nel blocco `try`, il codice nel blocco `catch` non viene eseguito. Il codice nel blocco `finally` viene eseguito _sempre_, `"Oh finally!"` viene loggato. + +
++ +#### Risposta: B + +Con il metodo `flat`, possiamo creare un nuovo array appiattito. La profondità dell'array appiattito dipende dal valore che passiamo. In questo caso, abbiamo passato il valore `1` (cosa che non dovevamo fare, questo è il valore predefinito), il che significa che solo gli array sulla prima profondità verranno concatenati. `['🥑']` e `['✨', '✨', ['🍕', '🍕']]` in questo caso. Concatenando questi due array si ottengono `['🥑', '✨', '✨', ['🍕', '🍕']]`. +
+
+
+#### Risposta: D
+
+`counterOne` è un'istanza della classe `Counter`. La classe counter contiene una proprietà `count` sul suo costruttore e un metodo `increment`. Per prima cosa, abbiamo invocato il metodo `increment` due volte chiamando `counterOne.increment()`. Attualmente, `counterOne.count` è `2`.
+
+
+
+Quindi, creiamo una nuova variabile `counterTwo` e la impostiamo uguale a `counterOne`. Poiché gli oggetti interagiscono per riferimento, stiamo semplicemente creando un nuovo riferimento allo stesso punto della memoria a cui punta `counterOne`. Poiché ha lo stesso punto in memoria, qualsiasi modifica apportata all'oggetto a cui fa riferimento `counterTwo`, si applica anche a `counterOne`. Attualmente, `counterTwo.count` è `2`.
+
+Invochiamo `counterTwo.increment()`, che imposta `count` su `3`. Quindi, logghiamo il conteggio su `counterOne`, che stampa `3`.
+
+
+
+
+ +#### Risposta: C + +Innanzitutto, invochiamo `funcOne`. Sulla prima riga di `funcOne`, chiamiamo la funzione _asincrona_ `setTimeout`, da cui la callback viene inviato all'API Web. (vedi l'articolo sul ciclo degli eventi [qui](https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif)) + +Quindi chiamiamo la promise `myPromise`, che è un'operazione _asincrona_. + +Sia la promise che il timeout sono operazioni asincrone, la funzione continua a funzionare mentre è impegnata a completare la promise e a gestire la callback `setTimeout`. Ciò significa che `Last line 1!` viene registrato per primo, poiché questa non è un'operazione asincrona. + +Poiché la callstack non è ancora vuota, la funzione `setTimeout` e la promise in `funcOne` non possono ancora essere aggiunte al callstack. + +In `funcTwo`, la variabile `res` ottiene `Promise` perché `Promise.resolve(Promise.resolve('Promise'))` è equivalente a `Promise.resolve('Promise')` poiché risolvere una promise risolve il suo valore. L'"attesa" in questa riga interrompe l'esecuzione della funzione fino a quando non riceve la risoluzione della promise e quindi continua a funzionare in modo sincrono fino al completamento, quindi `Promise 2!` e poi `Last line 2!` vengono registrati e `setTimeout` viene inviato all'API Web. + +Quindi lo stack di chiamate è vuoto. Le promise sono _microattività_, quindi vengono risolte per prime quando lo stack di chiamate è vuoto, quindi `Promise 1!` viene registrato. + +Ora, da quando `funcTwo` è uscito dallo stack delle chiamate, lo stack delle chiamate è vuoto. Le callback in attesa nella coda (`() => console.log("Timeout 1!")` da `funcOne`, e `() => console.log("Timeout 2!")` da `funcTwo`) vengono aggiunti allo stack di chiamate uno per uno. Il primo callback registra `Timeout 1!` e viene eliminato dallo stack. Quindi, il secondo callback registra `Timeout 2!` e viene eliminato dallo stack. +
++ +#### Risposta: C + +Con l'asterisco `*`, importiamo tutti i valori esportati da quel file, sia predefinito che nominale. Se avessimo il seguente file: + +```javascript +// info.js +export const name = 'Lydia'; +export const age = 21; +export default 'I love JavaScript'; + +// index.js +import * as info from './info'; +console.log(info); +``` + +Verrebbe loggato quanto segue: + +```javascript +{ + default: "I love JavaScript", + name: "Lydia", + age: 21 +} +``` + +Per l'esempio `sum`, significa che il valore importato `sum` è simile a quanto segue: + +```javascript +{ default: function sum(x) { return x + x } } +``` + +Possiamo invocare questa funzione, chiamando `sum.default` + +
++ +#### Risposta: C + +Con un oggetto Proxy, possiamo aggiungere un comportamento personalizzato a un oggetto che gli passiamo come secondo argomento. In questo caso, passiamo all'oggetto `handler` che conteneva due proprietà: `set` e `get`. `set` viene invocato ogni volta che _settiamo_ valori di proprietà, `get` viene invocato ogni volta che _otteniamo_ (accediamo) valori di proprietà. + +Il primo argomento è un oggetto vuoto `{}`, che è il valore di `person`. A questo oggetto viene aggiunto il comportamento personalizzato specificato nell'oggetto `handler`. Se aggiungiamo una proprietà all'oggetto `person`, `set` verrà invocato. Se accediamo a una proprietà sull'oggetto `person`, `get` viene invocato. + +Innanzitutto, abbiamo aggiunto una nuova proprietà `name` all'oggetto proxy (`person.name = "Lydia"`). `set` viene invocato e registra `"Added a new property!"`. + +Quindi, accediamo a un valore di proprietà sull'oggetto proxy, la proprietà `get` sull'oggetto handler è stata invocata. `"Accessed a property!"` viene registrato. + +
++ +#### Risposta: A + +Con `Object.seal` possiamo impedire che nuove proprietà vengano _aggiunte_ o che proprietà esistenti vengano _rimosse_. + +Tuttavia, puoi comunque modificare il valore delle proprietà esistenti. + +
++ +#### Risposta: C + +Il metodo `Object.freeze` _congela_ un oggetto. Nessuna proprietà può essere aggiunta, modificata o rimossa. + +Tuttavia, blocca solo _poco profondamente_ l'oggetto, il che significa che solo le proprietà _direct_ sull'oggetto sono bloccate. Se la proprietà è un altro oggetto, come `address` in questo caso, le proprietà su quell'oggetto non vengono bloccate e possono essere modificate. + +
++ +#### Risposta: A + +Per prima cosa, abbiamo invocato `myFunc()` senza passare alcun argomento. Dal momento che non abbiamo passato argomenti, `num` e `value` hanno i loro valori predefiniti: num è `2` e `value` il valore restituito dalla funzione `add`. Alla funzione `add`, passiamo `num` come argomento, che aveva il valore di `2`. `add` restituisce `4`, che è il valore di `value`. + +Quindi, abbiamo invocato `myFunc(3)` e passato il valore `3` come valore per l'argomento `num`. Non abbiamo passato un argomento per `value`. +Poiché non abbiamo passato un valore per l'argomento `value`, ha ottenuto il valore predefinito: il valore restituito dalla funzione `add`. Ad `add` passiamo `num`, che ha il valore di `3`. `add` restituisce `6`, che è il valore di `value`. + +
++ +#### Risposta: D + +In ES2020, possiamo aggiungere variabili private nelle classi usando `#`. Non possiamo accedere a queste variabili al di fuori della classe. Quando proviamo a registrare `counter.#number`, viene generato un SyntaxError: non possiamo accedervi al di fuori della classe `Counter`! + +
++ +#### Risposta: B + +Per scorrere i `members` in ogni elemento dell'array `teams`, dobbiamo passare `teams[i].members` alla funzione `getMembers`. La funzione restituisce un oggetto. Per scorrere ogni elemento in questo oggetto generatore, dobbiamo usare `yield*`. + +Se avessimo scritto `yield`, `return yield` o `return`, l'intera funzione del generatore sarebbe stata restituita la prima volta che abbiamo chiamato il metodo `next`. + +
++ +#### Risposta: C + +La funzione `addHobby` riceve due argomenti, `hobby` e `hobby` con il valore predefinito dell'array `hobbies` sull'oggetto `person`. + +Per prima cosa, invochiamo la funzione `addHobby` e passiamo `"running"` come valore per `hobby` e un array vuoto come valore per `hobby`. Poiché passiamo un array vuoto come valore per `hobby`, `"running"` viene aggiunto a questo array vuoto. + +Quindi, invochiamo la funzione `addHobby` e passiamo a `"dancing"` come valore per `hobby`. Non abbiamo passato un valore per `hobbies`, quindi ottiene il valore predefinito, la proprietà `hobbies` sull'oggetto `person`. Spostiamo l'hobby `dancing` nell'array `person.hobbies`. + +Infine, invochiamo la funzione `addHobby` e passiamo `"baking"` come valore per `hobby`, e l'array `person.hobbies` come valore per `hobby`. Spostiamo l'hobby `baking` nell'array `person.hobbies`. + +Dopo aver fatto un push di `dancing` e `baking`, il valore di `person.hobbies` è `["coding", "dancing", "baking"]` + +
++ +#### Risposta: B + +Creiamo la variabile `pet` che è un'istanza della classe `Flamingo`. Quando istanziamo questa istanza, il `constructor` su `Flamingo` viene chiamato. Per prima cosa, `"I'm pink. 🌸"` viene loggato, dopodiché chiamiamo `super()`. + +`super()` chiama il costruttore della classe genitore, `Bird`. Il costruttore in `Bird` viene chiamato e registra `"I'm a bird. 🦢"`. + +
++ +#### Risposta: D + +La chiave `const` significa che non possiamo _ridichiarare_ il valore di quella variabile, è di _sola lettura_. Tuttavia, il valore stesso non è immutabile. Le proprietà dell'array `emojis` possono essere modificate, ad esempio facendo un push di nuovi valori, collegandoli o impostando la lunghezza dell'array su 0. + +
++ +#### Risposta: C + +Gli oggetti non sono iterabili per impostazione predefinita. Un iterabile è un iterabile se è presente il protocollo iteratore. +Possiamo aggiungerlo manualmente aggiungendo il simbolo dell'iteratore `[Symbol.iterator]`, che deve restituire un oggetto generatore, ad esempio trasformandolo in una funzione del generatore `*[Symbol.iterator]() {}`. Questa funzione di generazione deve fornire gli `Object.values` dell'oggetto `person` se vogliamo che restituisca l'array `["Lydia Hallie", 21]`: `yield* Object.values(this)`. + +
++ +#### Risposta: C + +La condizione `if` all'interno del ciclo `forEach` controlla se il valore di `num` è veritiero o falso. Poiché il primo numero nell'array `nums` è `0`, ovvero un valore falso, il blocco di codice dell'istruzione `if` non verrà eseguito. `count` viene incrementato solo per gli altri 3 numeri nell'array `nums`, `1`, `2` e `3`. Poiché `count` viene incrementato di `1` 3 volte, il valore di `count` è `3`. + +
++ +#### Risposta: D + +Il `?` ci consente di accedere opzionalmente a proprietà nidificate più profonde all'interno degli oggetti. Stiamo cercando di registrare l'elemento sull'indice `1` all'interno del sottoarray che si trova sull'indice `1` dell'array `fruits`. Se il sottoarray sull'indice `1` nell'array `fruits` non esiste, restituirà semplicemente `undefined`. Se il sottoarray sull'indice `1` nell'array `fruits` esiste, ma questo sottoarray non ha un elemento nel suo indice `1`, restituirà comunque `undefined`. + +Innanzitutto, stiamo cercando di registrare il secondo elemento nel sottoarray `['🍍']` di `[['🍊', '🍌'], ['🍍']]`. Questo sottoarray contiene solo un elemento, il che significa che non c'è alcun elemento nell'indice `1`, e restituisce `undefined`. + +Quindi, stiamo invocando la funzione `getFruits` senza passare un valore come argomento, il che significa che `fruits` ha un valore di `undefined` per impostazione predefinita. Poiché stiamo concatenando condizionatamente l'elemento sull'indice `1` di `fruits`, restituisce `undefined` poiché questo elemento sull'indice `1` non esiste. + +Infine, stiamo cercando di registrare il secondo elemento nel sottoarray `['🍊', '🍌']` di `['🍍'], ['🍊', '🍌']`. L'elemento nell'indice `1` all'interno di questo sottoarray è `🍌`, che viene registrato. +
++ +#### Risposta: A + +Impostiamo la variabile `calc` uguale a una nuova istanza della classe `Calc`. Quindi, istanziamo una nuova `Calc` e invochiamo il metodo `increase` su questa istanza. Poiché la proprietà count è all'interno del costruttore della classe `Calc`, la proprietà count non è condivisa sul prototipo di `Calc`. Ciò significa che il valore di count non è stato aggiornato per l'istanza a cui punta il calc, count è ancora `0`. +
++ +#### Risposta: B + +La funzione `updateUser` aggiorna i valori delle proprietà `email` e `password` sull'utente se i loro valori vengono passati alla funzione, dopodiché la funzione restituisce l'oggetto `user`. Il valore restituito dalla funzione `updateUser` è l'oggetto `user`, il che significa che il valore di `updateUser` è un riferimento allo stesso oggetto `user` a cui punta `user`. `updatedUser === user` è uguale a `true`. + +
++ +#### Risposta: C + +Per prima cosa, invochiamo il metodo `slice` sull'array fruit. Il metodo slice non modifica l'array originale, ma restituisce il valore che ha tagliato fuori dall'array: l'emoji banana. +Quindi, invochiamo il metodo `splice` sull'array fruit. Il metodo splice modifica l'array originale, il che significa che l'array fruit ora è composto da `['🍊', '🍎']`. +Infine, invochiamo il metodo `unshift` sull'array `fruit`, che modifica l'array originale aggiungendo il valore fornito, '🍇' in questo caso, come primo elemento nell'array. L'array fruit ora è composto da `['🍇', '🍊', '🍎']`. + +
++ +#### Risposta: B + +Le chiavi degli oggetti vengono convertite in stringhe. + +Poiché il valore di `dog` è un oggetto, `animals[dog]` significa in realtà che stiamo creando una nuova proprietà chiamata `"object Object"` uguale al nuovo oggetto. +`animals["object Object"]` è ora uguale a `{ emoji: "🐶", name: "Mara"}`. + +Anche `cat` è un oggetto, il che significa che `animals[cat]` in realtà stiamo sovrascrivendo il valore di `animals["object Object"]` con le nuove proprietà cat. + +Loggando `animals[dog]`, o effettivamente `animals["object Object"]`, poiché la conversione dell'oggetto `dog` in una stringa risulta `"object Object"`, restituisce `{ emoji: "🐈", name: "Sara" }`. + +
++ +#### Risposta: A + +La funzione `updateEmail` è una arrow function e non è legata all'oggetto `user`. Ciò significa che la parola chiave `this` non si riferisce all'oggetto `user`, ma in questo caso si riferisce allo scope globale. Il valore di `email` all'interno dell'oggetto `user` non viene aggiornato. Quando si stampa il valore di `user.email`, viene restituito il valore originale ovvero `my@email.com`. + +
++ +#### Risposta: D + +Il metodo `Promise.all` esegue le promise passate in parallelo. Se una promise fallisce, il metodo `Promise.all` effettua un _rejects_ con il valore della promise rifiutata. In questo caso, `promise3` ha rifiutato con il valore `"Third"`. Stiamo rilevando il valore rifiutato nel metodo `catch` concatenato sulla chiamata `runPromises` per rilevare eventuali errori all'interno della funzione `runPromises`. Solo `"Third"` viene registrato, poiché `promise3` viene rifiutato con questo valore. + +
++ +#### Risposta: C + +Il metodo `fromEntries` trasforma un array 2d in un oggetto. Il primo elemento in ogni sottoarray sarà la chiave e il secondo elemento in ogni sottoarray sarà il valore. In questo caso, stiamo mappando sull'array `keys`, che restituisce un array il cui primo elemento è l'elemento nell'array di chiavi sull'indice corrente e il secondo elemento è l'elemento dell'array di valori sull'indice corrente. + +Questo crea una matrice di sottoarray contenenti le chiavi e i valori corretti, che risulta in `{ nome: "Lydia", età: 22 }` + +
++ +#### Risposta: C + +Il valore predefinito di `address` è un oggetto vuoto `{}`. Quando abbiamo impostato la variabile `member` uguale all'oggetto restituito dalla funzione `createMember`, non abbiamo passato un valore per `address`, il che significa che il valore di `address` è l'oggetto vuoto predefinito `{}`. Un oggetto vuoto è un valore veritiero, il che significa che la condizione `address ? address : null` restituisce `true`. Il valore di `address` è l'oggetto vuoto `{}`. + +
++ +#### Risposta: B + +La condizione all'interno dell'istruzione `if` controlla se il valore di `!typeof randomValue` è uguale a `"string"`. L'operatore `!` converte il valore in un valore booleano. Se il valore è vero, il valore restituito sarà `false`, se il valore è falso, il valore restituito sarà `true`. In questo caso, il valore restituito di `typeof randomValue` è il vero valore `"number"`, il che significa che il valore di `!typeof randomValue` è il valore booleano `false`. + +`!typeof randomValue === "string"` restituisce sempre false, poiché stiamo effettivamente controllando `false === "string"`. Poiché la condizione ha restituito `false`, il blocco di codice dell'istruzione `else` viene eseguito e `Yay it's a string!` viene registrato. + +
+-- [🇸🇦 العربية](./ar-AR/README_AR.md) -- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md) -- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md) -- [🇩🇪 Deutsch](./de-DE/README.md) +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](../de-DE/README.md) - [🇬🇧 English](../README.md) -- [🇪🇸 Español](./es-ES/README-ES.md) -- [🇫🇷 Français](./fr-FR/README_fr-FR.md) -- [🇮🇩 Indonesia](./id-ID/README.md) -- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) -- [🇳🇱 Nederlands](./nl-NL/README.md) -- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) -- [🇷🇺 Русский](./ru-RU/README.md) -- [🇹🇭 ไทย](./th-TH/README-th_TH.md) -- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) -- [🇺🇦 Українська мова](./uk-UA/README.md) -- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) -- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) -- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](../id-ID/README.md) +- [🇮🇹 Italiano](../it-IT/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇳🇱 Nederlands](../nl-NL/README.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](../ru-RU/README.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md)
-- [🇸🇦 العربية](./ar-AR/README_AR.md) -- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md) -- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md) -- [🇩🇪 Deutsch](./de-DE/README.md) +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](../de-DE/README.md) - [🇬🇧 English](../README.md) -- [🇪🇸 Español](./es-ES/README-ES.md) -- [🇫🇷 Français](./fr-FR/README_fr-FR.md) -- [🇮🇩 Indonesia](./id-ID/README.md) -- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) -- [🇰🇷 한국어](./ko-KR/README-ko_KR.md) -- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) -- [🇷🇺 Русский](./ru-RU/README.md) -- [🇹🇭 ไทย](./th-TH/README-th_TH.md) -- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) -- [🇺🇦 Українська мова](./uk-UA/README.md) -- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) -- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) -- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](../id-ID/README.md) +- [🇮🇹 Italiano](../it-IT/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](../ko-KR/README-ko_KR.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](../ru-RU/README.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md)
+Od podstawowych do zaawansowanych: sprawdź, jak dobrze znasz JavaScript, odśwież swoją wiedzę lub przygotuj się do rozmowy kwalifikacyjnej! :muscle: :rocket: Regularnie aktualizuję to repozytorium nowymi pytaniami. Odpowiedzi znajdują się w ukrytych zakładkach poniżej pytań - po prostu kliknij, aby je rozwinięć. To dla zabawy, powodzenia! :heart:
+ +Nie krępuj się ze mną kontaktować! 😊
+ ++Instagram || Twitter || LinkedIn || Blog +
+ +| Śmiało używaj ich w projekcie! 😃 Byłabym _bardzo_ wdzięczna za referencje do tego repozytorium, tworzę pytania i wyjaśnienia (tak, jestem smutna lol) i społeczność bardzo mi pomaga w utrzymaniu i ulepszaniu go! 💪🏼 Dziękuję i baw się dobrze! | +|---| + +--- + ++ +- [🇸🇦 العربية](./ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](./de-DE/README.md) +- [🇪🇸 Español](./es-ES/README-ES.md) +- [🇫🇷 Français](./fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](./id-ID/README.md) +- [🇮🇹 Italiano](./it-IT/README.md) +- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](./ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](./nl-NL/README.md) +- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](./ru-RU/README.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](./th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](./uk-UA/README.md) +- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) +- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) + +
++ +#### Odpowiedź: D + +Wewnątrz funkcji najpierw deklarujemy zmienną `name` za pomocą słowa kluczowego `var`. Oznacza to, że zmienna jest "wyciągana" (przestrzeń pamięci jest tworzona) z domyślną wartością `undefined` podczas fazy tworzenia, aż do momentu, gdy naprawdę definiujemy zmienną. W linii, w której próbujemy wyświetlić w konsoli zmienną `name`, jeszcze jej nie zdefiniowaliśmy, więc nadal przechowuje wartość `undefined`. + +Zmienne zadeklarowane za pomocą słowa kluczowego `let` (i `const`) są wyciągane, ale w przeciwieństwie do `var`, nie są inicjalizowane. Nie są dostępne przed linią, na której je deklarujemy (inicjalizujemy). Nazywa się to "czasową strefą martwą" (temporal dead zone). Gdy próbujemy uzyskać dostęp do zmiennych przed ich zadeklarowaniem, JavaScript generuje błąd `ReferenceError`. + +
++ +#### Odpowiedź: C + +Ze względu na kolejkę zdarzeń w JavaScript, funkcja zwrotna `setTimeout` jest wywoływana _po_ wykonaniu pętli. Ponieważ zmienna `i` w pierwszej pętli została zadeklarowana za pomocą słowa kluczowego `var`, jej wartość była globalna. Podczas pętli inkrementowaliśmy wartość `i` o `1` za każdym razem, używając operatora jednoargumentowego `++`. W momencie wywołania funkcji zwrotnej `setTimeout`, `i` miało wartość `3` w pierwszym przykładzie. + +W drugiej pętli zmienna `i` została zadeklarowana za pomocą słowa kluczowego `let`: zmienne zadeklarowane za pomocą słowa kluczowego `let` (i `const`) mają zakres blokowy (blokiem jest cokolwiek między `{ }`). Podczas każdej iteracji `i` będzie miało nową wartość, a każda wartość będzie miała zakres wewnątrz pętli. + +
++ +#### Odpowiedź: B + +Zwróć uwagę, że wartość `diameter` jest zwykłą funkcją, podczas gdy wartość `perimeter` jest funkcją strzałkową. + +W przypadku funkcji strzałkowych, słowo kluczowe `this` odnosi się do bieżącego otaczającego zakresu, w przeciwieństwie do zwykłych funkcji! Oznacza to, że gdy wywołujemy `perimeter`, nie odnosi się ono do obiektu shape, ale do swojego otaczającego zakresu (np. okna). + +Na tym obiekcie nie ma wartości `radius`, co powoduje zwrócenie `NaN` (Not a Number). + +
++ +#### Odpowiedź: A + +Operator jednoargumentowy plus próbuje przekonwertować operand na liczbę. `true` jest równoważne `1`, a `false` jest równoważne `0`. + +Łańcuch znaków `'Lydia'` jest wartością prawdziwą. Tak naprawdę pytamy, "czy ta wartość prawdziwa jest fałszywa?". To zwraca `false`. + +
++ +#### Odpowiedź: A + +W JavaScript wszystkie klucze obiektów są stringami (chyba że są to symbole). Nawet jeśli nie wpisujemy ich jako stringi, zawsze są one konwertowane na stringi wewnątrz. + +JavaScript interpretuje (lub "odpakuowuje") instrukcje. Gdy używamy notacji nawiasów kwadratowych, interpreter widzi pierwszy otwierający nawias `[` i kontynuuje do momentu znalezienia zamykającego nawiasu `]`. Dopiero wtedy ocenia tę instrukcję. + +`mouse[bird.size]`: Najpierw ocenia `bird.size`, które wynosi `"small"`. `mouse["small"]` zwraca `true`. + +Jednakże, w przypadku notacji kropkowej, to się nie dzieje. `mouse` nie ma klucza o nazwie `bird`, co oznacza, że `mouse.bird` jest `undefined`. Następnie pytamy o `size` używając notacji kropkowej: `mouse.bird.size`. Ponieważ `mouse.bird` jest `undefined`, tak naprawdę pytamy o `undefined.size`. To nie jest poprawne i spowoduje błąd podobny do `Cannot read property "size" of undefined` (Nie można odczytać właściwości "size" z undefined). + +
+
+
+#### Odpowiedź: A
+
+W JavaScript wszystkie obiekty komunikują się ze sobą przez _referencje_, gdy są sobie przypisywane.
+
+Na początku zmienna `c` przechowuje referencję do obiektu. Później przypisujemy zmiennej `d` tę samą referencję, którą ma `c`, do tego obiektu.
+
+
+
+Kiedy zmieniasz jeden obiekt, zmieniasz je wszystkie.
+
+
+ +#### Odpowiedź: C + +`new Number()` jest wbudowanym konstruktorem funkcji. Chociaż wygląda jak liczba, nie jest faktycznie liczbą: ma wiele dodatkowych funkcji i jest obiektem. + +Gdy używamy operatora `==` (operator równości), sprawdza on jedynie, czy mają tą samą _wartość_. Oba mają wartość `3`, więc zwraca `true`. + +Jednak gdy używamy operatora `===` (operator ścisłej równości), zarówno wartość, jak i typ powinny być takie same. Tutaj nie są: `new Number()` nie jest liczbą, lecz **obiektem**. Oba zwracają `false`. + +
++ +#### Odpowiedź: D + +Funkcja `colorChange` jest statyczna. Metody statyczne są zaprojektowane tak, aby istniały tylko w konstruktorze, w którym zostały utworzone, i nie mogą być przekazywane do żadnych potomków (children) ani wywoływane na instancjach klasy. Ponieważ `freddie` jest instancją klasy Chameleon, funkcja nie może być na niej wywołana. Otrzymujemy błąd `TypeError`. + +
++ +#### Odpowiedź: A + +Kod wypisuje w konsoli obiekt, ponieważ właśnie utworzyliśmy pusty obiekt w obiekcie globalnym! Gdy pomyłkowo wpisaliśmy `greeting` jako `greetign`, interpreter JavaScript faktycznie zobaczył to jako: + +1. `global.greetign = {}` w Node.js. +2. `window.greetign = {}`, `frames.greetign = {}` i `self.greetign` w przeglądarkach. +3. `self.greetign` w web workerach. +4. `globalThis.greetign` we wszystkich środowiskach. + +Aby temu zapobiec, możemy użyć `"use strict"`. Powoduje to, że musisz zadeklarować zmienną przed jej przypisaniem. + +
++ +#### Odpowiedź: A + +Jest to możliwe w JavaScript, ponieważ funkcje są obiektami! (Wszystko oprócz typów prymitywnych jest obiektem) + +Funkcja jest specjalnym rodzajem obiektu. Kod, który sam piszesz, nie jest właściwą funkcją. Funkcja jest obiektem posiadającym właściwość, która jest wywoływalna. + +
++ +#### Odpowiedź: A + +W JavaScript funkcje są obiektami, więc metoda `getFullName` jest dodawana do samego obiektu funkcji konstruktora. Dlatego możemy wywołać `Person.getFullName()`, ale `member.getFullName` zwraca błąd `TypeError`. + +Jeśli chcesz, aby metoda była dostępna dla wszystkich instancji obiektów, musisz dodać ją do właściwości prototype: + +```js +Person.prototype.getFullName = function() { + return `${this.firstName} ${this.lastName}`; +}; +``` + +
++ +#### Odpowiedź: A + +Dla `sarah`, nie użyliśmy słowa kluczowego `new`. Kiedy używamy `new`, `this` odwołuje się do nowego pustego obiektu, który tworzymy. Jednak jeśli nie dodajemy `new`, `this` odwołuje się do **globalnego obiektu**! + +Mówiliśmy, że `this.firstName` równa się `"Sarah"`, a `this.lastName` równa się `"Smith"`. Czyli faktycznie zdefiniowaliśmy `global.firstName = 'Sarah'` i `global.lastName = 'Smith'`. `sarah` pozostaje `undefined`, ponieważ nie zwracaliśmy żadnej wartości z funkcji `Person`. + +
+
+
+#### Odpowiedź: D
+
+W fazie **capturing (przechwytywanie)**, zdarzenie przechodzi przez elementy nadrzędne w doł do elementu docelowego. Następnie dociera do elementu **target (cel)** i rozpoczyna się **bubbling (bąbelkowanie)**.
+
+
+
+
+ +#### Odpowiedź: B + +Wszystkie obiekty mają prototypy, z wyjątkiem **obiektu bazowego**. Obiekt bazowy jest obiektem utworzonym przez użytkownika lub obiektem utworzonym przy użyciu słowa kluczowego `new`. Obiekt bazowy ma dostęp do niektórych metod i właściwości, takich jak `.toString`. Jest to powód, dla którego można używać wbudowanych metod JavaScript! Wszystkie takie metody są dostępne w prototypie. Chociaż JavaScript nie może znaleźć ich bezpośrednio w twoim obiekcie, przechodzi w dół łańcucha prototypów i je tam znajduje, co czyni je dostępnymi dla ciebie. + +
++ +#### Odpowiedź: C + +JavaScript jest językiem **dynamicznie typowanym**: nie określamy typów niektórych zmiennych. Wartości mogą być automatycznie konwertowane na inny typ bez wiedzy użytkownika, co nazywa się _implicit type coercion_. **Koercja (Wymuszenie)** to konwersja z jednego typu na inny. + +W tym przykładzie JavaScript konwertuje liczbę `1` na string, aby funkcja miała sens i zwróciła wartość. Podczas dodawania typu liczbowego (`1`) i typu łańcuchowego (`'2'`), liczba traktowana jest jako string. Możemy łączyć stringi takie jak `"Hello" + "World"`, więc to co się tutaj dzieje to `"1" + "2"`, które zwraca `"12"`. + +
++ +#### Odpowiedź: C + +Operator jednoargumentowy **Postfix** `++`: + +1. Zwraca wartość (ten zwraca `0`) +2. Zwiększa wartość (liczba wynosi teraz `1`) + +Operator jednoargumentowy **Prefix** `++`: + +1. Zwiększa wartość (liczba wynosi teraz `2`) +2. Zwraca wartość (to zwraca `2`) + +number zwraca `0 2 2`. + +
++ +#### Odpowiedź: B + +W przypadku użycia `template strings`, wartością pierwszego argumentu jest zawsze tablica wartości łańcuchowych (string). Pozostałe argumenty otrzymują wartości przekazanych wyrażeń! + +
++ +#### Odpowiedź: C + +Podczas testowania równości, liczby i ciągi znaków są porównywane przez ich _wartości_, a obiekty są porównywane przez ich _referencję_. JavaScript sprawdza, czy obiekty mają odwołanie do tej samej lokalizacji w pamięci. + +Dwa obiekty, które porównujemy, nie mają tej samej lokalizacji w pamięci: obiekt, który przekazujemy jako parametr, odwołuje się do innej lokalizacji w pamięci niż obiekt, którego użyliśmy do sprawdzenia równości. + +Dlatego też zarówno `{ age: 18 } == { age: 18 }` i `{ age: 18 } == { age: 18 }` zwracają `false`. + +
++ +#### Odpowiedź: C + +Parametr reszty (`...args`) pozwala nam "zbierać" wszystkie pozostałe argumenty do tablicy. Tablica to obiekt, więc `typeof args` zwraca `"object"`. + +
++ +#### Odpowiedź: C + +Dzięki `"use strict"` możesz upewnić się, że przypadkowo nie zadeklarujesz zmiennych globalnych. Nigdy nie zadeklarowaliśmy zmiennej `age`, a ponieważ używamy `"use strict"`, zostanie zgłoszony błąd referencji. Gdybyśmy nie użyli `"use strict"`, to by zadziałało, ponieważ właściwość `age` zostałaby dodana do obiektu globalnego. + +
++ +#### Odpowiedź: A + +`eval` oblicza kod, który przekazywany jest jako ciąg znaków. Jeśli jest to wyrażenie, tak jak w tym przypadku, oblicza ono wyrażenie. Wyrażenie to `10 * 10 + 5`. Zwraca liczbę `105`. + +
++ +#### Odpowiedź: B + +Dane przechowywane w `sessionStorage` są usuwane po zamknięciu _zakładki_. + +Gdybyś użył `localStorage`, dane pozostałyby tam na zawsze, chyba że na przykład wywołano by `localStorage.clear()`. + +
++ +#### Odpowiedź: B + +Za pomocą słowa kluczowego `var` można zadeklarować wiele zmiennych o tej samej nazwie. Zmienna będzie wtedy przechowywać najnowszą wartość. + +Nie można tego zrobić za pomocą `let` lub `const`, ponieważ są one blokowe. + +
++ +#### Odpowiedź: C + +Wszystkie klucze obiektów (z wyjątkiem symboli) są łańcuchami znaków pod względem samego obiektu, nawet jeśli nie napiszesz ich samodzielnie jako łańcucha znaków. Dlatego `obj.hasOwnProperty('1')` również zwraca true. + +Nie działa to w ten sam sposób dla zbioru. W zbiorze nie ma klucza `'1'`:`set.has('1')`, dlatego zwraca wartość false. Zawiera on liczbę całkowitą `1`, `set.has(1)` zwraca wartość true. + +
++ +#### Odpowiedź: C + +Jeśli masz dwa klucze o takiej samej nazwie, zostanie on zastąpiony. Nadal będzie umieszczony na pierwszej pozycji, ale z ostatnią zdefiniowaną wartością. + +
++ +#### Odpowiedź: A + +Globalny kontekst wykonania jest dostępny wszędzie w kodzie. + +
++ +#### Odpowiedź: C + +Instrukcja `continue` pomija iterację, jeśli określony warunek zwróci `true`. + +
++ +#### Odpowiedź: A + +`String` jest wbudowanym konstruktorem, do którego możemy dodawać właściwości. Dodana została metoda do jego prototypu. Prymitywne ciągi znaków są automatycznie konwertowane na obiekt typu string, generowany przez funkcję prototypu ciągu znaków. Tak więc wszystkie ciągi (obiekty typu string) mają dostęp do tej metody! + +
++ +#### Odpowiedź: B + +Klucze obiektów są automatycznie konwertowane na ciągi znaków. Próbujemy ustawić obiekt jako klucz do obiektu `a`, z wartością `123`. + +Jednakże, kiedy stringujemy obiekt, staje się on `"[obiekt Object]"`. Mówimy więc, że `a["[obiekt Object]"] = 123`. Następnie próbujemy zrobić to samo. `c` jest kolejnym obiektem, który niejawnie stringujemy. Zatem `a["[obiekt Object]"] = 456`. + +Następnie wyświetlamy w konsoli `a[b]`, co w rzeczywistości jest `a["[obiekt Object]"]`, ustawiony wcześniej na `456`, więc zwraca `456`. + +
+
+
+#### Odpowiedź: B
+
+Mamy funkcję `setTimeout` i wywołaliśmy ją jako pierwszą. Została jednak wyświetlona jako ostatnia.
+
+Dzieje się tak, ponieważ w przeglądarkach mamy nie tylko silnik wykonawczy, ale także coś, co nazywa się `WebAPI`. Interfejs `WebAPI` daje nam na początek funkcję `setTimeout`.
+
+Po przesłaniu _callback_ do WebAPI, sama funkcja `setTimeout` (ale nie callback!) jest usuwana ze stosu.
+
+
+
+Teraz, `foo` jest wywoływane, a `"First"` jest wyświetlane.
+
+
+
+`foo` jest zdejmowane ze stosu, a `baz` jest wywoływane. "Third" zostaje wyświetlony.
+
+
+
+WebAPI nie może dodawać rzeczy do stosu, gdy jest gotowy. Zamiast tego przesuwa funkcję zwrotną do czegoś zwanego _kolejką_.
+
+
+
+W tym miejscu zaczyna działać pętla zdarzeń. **Pętla zdarzeń** patrzy na stos i kolejkę zadań. Jeśli stos jest pusty, pobiera pierwszą rzecz z kolejki i przesuwa ją na stos.
+
+
+
+`bar` zostaje wywołany, `"Second"` zostaje wyświetlony i zdjęty ze stosu.
+
+
+ +#### Odpowiedź: C + +Najgłębiej zagnieżdżony element, który spowodował zdarzenie jest celem zdarzenia. Możesz zatrzymać bąbelkowanie poprzez `event.stopPropagation` + +
++ Click here! +
++ +#### Odpowiedź: A + +Jeśli klikniemy `p`, zobaczymy dwa logi: `p` i `div`. Podczas propagacji zdarzeń istnieją 3 fazy: przechwytywanie, cel i bąbelkowanie (capturing, target, and bubbling). Domyślnie, event handlery są wykonywane w fazie bąbelkowania (chyba że ustawisz `useCapture` na `true`). Przebiega ona od najgłębiej zagnieżdżonego elementu na zewnątrz. + +
++ +#### Odpowiedź: D + +W obu przypadkach możemy przekazać obiekt, do którego ma się odnosić słowo kluczowe `this`. Jednakże, `.call` jest _wykonywane natychmiast_! + +`.bind.` zwraca _kopię_ funkcji, ale z powiązanym kontekstem! Nie jest ona wykonywana natychmiast. + +
++ +#### Odpowiedź: B + +Funkcja `sayHi` zwraca zwróconą wartość natychmiast wywołanego wyrażenia funkcyjnego (IIFE). Ta funkcja zwróciła wartość `0`, która jest typu `"number"`. + +FYI: `typeof` może zwrócić następującą listę wartości: `undefined`, `boolean`, `number`, `bigint`, `string`, `symbol`, `function` i `object`. Zauważ, że `typeof null` zwraca `"object"`. + +
++ +#### Odpowiedź: A + +Istnieje 8 fałszywych wartości: + +- `undefined` +- `null` +- `NaN` +- `false` +- `''` (pusty ciąg) +- `0` +- `-0` +- `0n` (BigInt(0)) + +Konstruktory funkcji, takie jak `new Number` i `new Boolean` są prawdziwe. + +
++ +#### Odpowiedź: B + +`typeof 1` zwraca `"number"`. +`typeof "number"` zwraca `"string"`. + +
++ +#### Odpowiedź: C + +Po ustawieniu wartości elementu w tablicy, która przekracza długość tablicy, JavaScript tworzy coś, co nazywa się "pustymi slotami". W rzeczywistości mają one wartość `undefined`, ale zobaczysz coś takiego jak: + +`[1, 2, 3, puste x 7, 11]`. + +w zależności od tego, gdzie go uruchomisz (jest inny dla każdej przeglądarki, node itp.). + +
++ +#### Odpowiedź: A + +Blok `catch` otrzymuje argument `x`. Nie jest to ten sam `x` co zmienna, gdy przekazujemy argumenty. Ta zmienna `x` jest blokowa. + +Później, ustawiamy tę blokową zmienną równą `1` i ustawiamy wartość zmiennej `y`. Teraz wyświetlamy w konsoli zmienną blokową `x`, która jest równa `1`. + +Poza blokiem `catch`, `x` jest wciąż `undefined`, a `y` wynosi `2`. Gdy chcemy wykonać `console.log(x)` poza blokiem `catch`, zwraca on `undefined`, a `y` zwraca `2`. + +
++ +#### Odpowiedź: A + +JavaScript ma tylko prymitywne typy i obiekty. + +Typy prymitywne to `boolean`, `null`, `undefined`, `bigint`, `number`, `string` i `symbol`. + +To, co odróżnia prymityw od obiektu, to fakt, że prymitywy nie mają żadnych właściwości ani metod; zauważysz jednak, że `'foo'.toUpperCase()` wylicza `'FOO'` i nie powoduje `TypeError`. Dzieje się tak dlatego, że gdy próbujesz uzyskać dostęp do właściwości lub metody na prymitywie takim jak ciąg znaków, JavaScript niejawnie opakuje prymitywny typ za pomocą jednej z klas opakowujących, tj. `String`, a następnie natychmiast odrzuci opakowanie po ocenie wyrażenia. Wszystkie prymitywy z wyjątkiem `null` i `undefined` wykazują to zachowanie. + +
++ +#### Odpowiedź: C + +`[1, 2]` jest naszą wartością początkową. Jest to wartość, z którą zaczynamy i wartość pierwszego `acc`.Podczas pierwszej rundy, `acc` to `[1, 2]`, a `cur` to `[0, 1]`.Łączymy je, co daje `[1, 2, 0, 1]`. + +Następnie `[1, 2, 0, 1]` to `acc`, a `[2, 3]` to `cur`. Łączymy je i otrzymujemy `[1, 2, 0, 1, 2, 3]`. + +
++ +#### Odpowiedź: B + +`null` jest fałszywe. `!null` zwraca `true`. `!true` zwraca `false`. + +`""` jest fałszywe. `!""` zwraca `true`. `!true` zwraca `false`. + +`1` jest prawdziwe. `!1` zwraca `false`. `!false` zwraca `true`. + +
++ +#### Odpowiedź: A + +Zwraca unikalny identyfikator. Ten identyfikator może być użyty do wyczyszczenia tego interwału za pomocą funkcji `clearInterval()`. + +
++ +#### Odpowiedź: A + +Łańcuch znaków jest iterowalny. Operator spread odwzorowuje każdy znak iterable na jeden element. + +
++ +#### Odpowiedź: C + +Zwykłe funkcje nie mogą zostać zatrzymane w połowie wywoływania. Jednak funkcja generatora może zostać "zatrzymana" w połowie, a następnie kontynuować od miejsca, w którym się zatrzymała. Za każdym razem, gdy funkcja generująca napotka słowo kluczowe `yield`, funkcja zwraca wartość określoną po nim. + +Najpierw inicjalizujemy funkcję generatora z `i` równym `10`. Wywołujemy funkcję generatora za pomocą metody `next()`. Przy pierwszym wywołaniu funkcji generatora, `i` jest równe `10`. Funkcja napotyka pierwsze słowo kluczowe `yield`: zwraca wartość `i`. Generator jest teraz "wstrzymany", a wartość `10` zostaje zarejestrowana. + +Następnie ponownie wywołujemy funkcję za pomocą metody `next()`. Kontynuuje ona tam, gdzie zatrzymała się poprzednio, wciąż z `i` równym `10`. Teraz napotyka następne słowo kluczowe `yield` i zwraca `i * 2`. `i` jest równe `10`, więc zwraca `10 * 2`, czyli `20`. Wynikiem jest `10, 20`. + +
++ +#### Odpowiedź: B + +Kiedy przekazujemy wiele 'promise' do metody `Promise.race`, rozwiązuje ona/odrzuca _pierwszą_ 'promise'. Do metody `setTimeout` przekazujemy timer: 500ms dla `firstPromise` i 100ms dla `secondPromise`. Oznacza to, że `secondPromise` zostanie rozwiązana jako pierwsza z wartością `'two'`. `res` przechowuje teraz wartość `'two'`, która jest wyświetlona w konsoli. + +
+
+
+#### Odpowiedź: D
+
+Najpierw deklarujemy zmienną `person` z wartością obiektu, który ma właściwość `name`.
+
+
+
+Następnie deklarujemy zmienną o nazwie `members`. Ustawiamy pierwszy element tej tablicy równy wartości zmiennej `person`. Obiekty oddziałują na siebie poprzez _referencję_, gdy ustawiamy je równe sobie. Kiedy przypisujesz referencję z jednej zmiennej do drugiej, tworzysz _kopię_ tej referencji. (Zauważ, że nie mają one _tej samej_ referencji!).
+
+
+
+Następnie ustawiamy zmienną `person` równą `null`.
+
+
+
+Modyfikujemy tylko wartość zmiennej `person`, a nie pierwszy element w tablicy, ponieważ ten element ma inną (skopiowaną) referencję do obiektu. Pierwszy element w `members` wciąż posiada referencję do oryginalnego obiektu. Kiedy wyświetlamy tablicę `members`, pierwszy element nadal przechowuje wartość obiektu, który jest wyświetlany.
+
+
+ +#### Odpowiedź: B + +Za pomocą pętli `for-in` możemy iterować po kluczach obiektów, w tym przypadku `name` i `age`. Klucze obiektów są łańcuchami (jeśli nie są symbolami). W każdej pętli ustawiamy wartość `item` równą bieżącemu kluczowi, który iterujemy. Najpierw `item` jest równy `name`. Następnie, `item` jest równy `age`. + +
++ +#### Odpowiedź: B + +Asocjatywność operatorów to kolejność, w jakiej kompilator ocenia wyrażenia, od lewej do prawej lub od prawej do lewej. Dzieje się tak tylko wtedy, gdy wszystkie operatory mają _takie samo_ pierwszeństwo. Mamy tylko jeden typ operatora: `+`. Dla dodawania, asocjatywność jest od lewej do prawej. + +`3 + 4` jest obliczane jako pierwsze. Wynikiem jest liczba `7`. + +`7 + '5'` skutkuje `"75"` z powodu przymusu. JavaScript konwertuje liczbę `7` na ciąg znaków, patrz pytanie 15. Możemy połączyć dwa ciągi znaków za pomocą operatora `+`. "7" + "5"` daje w wyniku "75"`. + +
++ +#### Odpowiedź: C + +Zwracana jest tylko pierwsza liczba w łańcuchu. W oparciu o _radix_ (drugi argument w celu określenia typu liczby, którą chcemy przetworzyć: podstawa 10, szesnastkowy, ósemkowy, binarny itp.), `parseInt` sprawdza, czy znaki w łańcuchu są prawidłowe. Gdy napotka znak, który nie jest prawidłową liczbą w radix, zatrzymuje parsowanie i ignoruje następujące znaki. + +`*` nie jest prawidłową liczbą. Przetwarza tylko `"7"` na dziesiętne `7`. `num` posiada teraz wartość `7`. + +
++ +#### Odpowiedź: C + +Podczas mapowania tablicy, wartość `num` jest równa elementowi, nad którym aktualnie wykonywana jest pętla. W tym przypadku elementami są liczby, więc warunek instrukcji if `typeof num == "number"` zwraca `true`. Funkcja map tworzy nową tablicę i wstawia do niej wartości zwrócone przez funkcję. + +Nie zwracamy jednak żadnej wartości. Gdy nie zwracamy wartości z funkcji, funkcja zwraca `undefined`. Dla każdego elementu w tablicy wywoływany jest blok funkcji, więc dla każdego elementu zwracamy `undefined`. + +
++ +#### Odpowiedź: A + +Argumenty są przekazywane przez _wartość_, chyba że ich wartość jest obiektem, wtedy są przekazywane przez _referencję_. Argument `birthYear` jest przekazywany przez wartość, ponieważ jest ciągiem znaków, a nie obiektem. Kiedy przekazujemy argumenty przez wartość, tworzona jest _kopia_ tej wartości (patrz pytanie 46). + +Zmienna `birthYear` posiada referencję do wartości `"1997"`. Argument `year` również posiada referencję do wartości `"1997"`, ale nie jest to ta sama wartość, do której odnosi się `birthYear`. Kiedy aktualizujemy wartość `year` ustawiając `year` na `"1998"`, aktualizujemy tylko wartość `year`. Wartość `birthYear` jest wciąż równa `1997`. + +Wartość `person` jest obiektem. Argument `member` posiada (skopiowaną) referencję do _tego samego_ obiektu. Gdy zmodyfikujemy właściwość obiektu, do którego odwołuje się `member`, wartość `person` również zostanie zmodyfikowana, ponieważ oba mają odwołanie do tego samego obiektu. Właściwość `name` obiektu `person` jest teraz równa wartości `"Lydia"`. + +
++ +#### Odpowiedź: D + +Za pomocą instrukcji `throw` możemy tworzyć niestandardowe błędy. Za pomocą tej instrukcji można rzucać wyjątki string, number, boolean lub object. W tym przypadku, naszym wyjątkiem jest ciąg znaków `'Hello world!".` + +Za pomocą instrukcji `catch` możemy określić, co należy zrobić, jeśli wyjątek zostanie rzucony w bloku `try`. Wyjątkiem może być: string `'Hello world!'`. `e` jest teraz równe temu ciągowi, który wyświetlamy w konsoli. Skutkuje to `'Oh an error: Hello world!'`. + +
++ +#### Odpowiedź: B + +Kiedy zwracasz właściwość, wartość właściwości jest równa _zwróconej_ wartości, a nie wartości ustawionej w funkcji konstruktora. Zwracamy ciąg `"Maserati"`, więc `myCar.make` jest równe `"Maserati"`. + +
++ +#### Odpowiedź: A + +`let x = (y = 10);` jest w rzeczywistości skrótem od: + +```javascript +y = 10; +let x = y; +``` + +Kiedy ustawiamy `y` równe `10`, w rzeczywistości dodajemy właściwość `y` do globalnego obiektu (`window` w przeglądarce, `global` w Node). W przeglądarce, `window.y` jest teraz równe `10`. + +Następnie deklarujemy zmienną `x` z wartością `y`, która wynosi `10`. Zmienne zadeklarowane za pomocą słowa kluczowego `let` są _block scoped_ i są definiowane tylko w bloku, w którym zostały zadeklarowane; w tym przypadku natychmiast wywołane wyrażenie funkcji (IIFE). Kiedy używamy operatora `typeof`, operand `x` nie jest zdefiniowany: próbujemy uzyskać dostęp do `x` poza blokiem, w którym został zadeklarowany. Oznacza to, że `x` nie jest zdefiniowane. Wartości, które nie zostały przypisane lub zadeklarowane są typu "undefined". `console.log(typeof x)` zwraca `"undefined"`. + +Jednakże, utworzyliśmy globalną zmienną `y` podczas ustawiania `y` równego `10`. Wartość ta jest dostępna w dowolnym miejscu naszego kodu. Zmienna `y` jest zdefiniowana i przechowuje wartość typu `"number"`. `console.log(typeof y)` zwraca `"number"`. + +
++ +#### Odpowiedź: A + +Możemy usuwać właściwości z obiektów za pomocą słowa kluczowego `delete`, również na prototypie. Usuwając właściwość z prototypu, nie jest ona już dostępna w łańcuchu prototypów. W tym przypadku funkcja `bark` nie jest już dostępna w prototypie po `delete Dog.prototype.bark`, a mimo to wciąż próbujemy uzyskać do niej dostęp. + +Kiedy próbujemy wywołać coś, co nie jest funkcją, rzucany jest `TypeError`. W tym przypadku `TypeError: pet.bark is not a function`, ponieważ `pet.bark` jest `undefined`. + +
++ +#### Odpowiedź: D + +Obiekt `Set` jest zbiorem _unikalnych_ wartości: wartość może wystąpić tylko raz w zbiorze. + +Przekazaliśmy iterowalne `[1, 1, 2, 3, 4]` ze zduplikowaną wartością `1`.Ponieważ nie możemy mieć dwóch takich samych wartości w zbiorze, jedna z nich jest usuwana. Wynikiem jest `{1, 2, 3, 4}`. + +
++ +#### Odpowiedź: C + +Zaimportowany moduł jest _tylko do odczytu_: nie można modyfikować zaimportowanego modułu. Tylko moduł, który go eksportuje może zmienić jego wartość. + +Kiedy próbujemy zwiększyć wartość `myCounter`, wyrzuca błąd: `myCounter` jest tylko do odczytu i nie może być modyfikowany. + +
++ +#### Odpowiedź: A + +Operator `delete` zwraca wartość logiczną: `true` po pomyślnym usunięciu, w przeciwnym razie zwróci `false`. Jednakże, zmienne zadeklarowane ze słowem kluczowym `var`, `const` lub `let` nie mogą być usunięte za pomocą operatora `delete`. + +Zmienna `name` została zadeklarowana ze słowem kluczowym `const`, więc jej usunięcie nie powiedzie się: Zwracane jest `false`. Kiedy ustawiliśmy wartość `age` równą `21`, w rzeczywistości dodaliśmy właściwość o nazwie `age` do obiektu globalnego. W ten sposób można pomyślnie usunąć właściwości z obiektów, również z obiektu globalnego, więc `delete age` zwraca `true`. + +
+
+
+#### Odpowiedź: C
+
+Możemy rozpakować wartości z tablic lub właściwości z obiektów poprzez destrukturyzację. Na przykład:
+
+```javascript
+[a, b] = [1, 2];
+```
+
+
+
+Wartość `a` wynosi teraz `1`, a wartość `b` wynosi teraz `2`.To, co faktycznie zrobiliśmy w pytaniu, to:
+
+```javascript
+[y] = [1, 2, 3, 4, 5];
+```
+
+
+
+Oznacza to, że wartość `y` jest równa pierwszej wartości w tablicy, którą jest liczba `1`.Kiedy logujemy `y`, zwracana jest wartość `1`.
+
+
+ +#### Odpowiedź: B + +Możliwe jest łączenie obiektów za pomocą operatora rozprzestrzeniania `...`.Umożliwia on tworzenie kopii par klucz/wartość jednego obiektu i dodawanie ich do innego obiektu. W tym przypadku tworzymy kopie obiektu `user` i dodajemy je do obiektu `admin`. Obiekt `admin` zawiera teraz skopiowane pary klucz/wartość, czego wynikiem jest `{ admin: true, name: "Lydia", age: 21 }`. + +
++ +#### Odpowiedź: B + +Za pomocą metody `defineProperty` możemy dodawać nowe właściwości do obiektu lub modyfikować istniejące. Kiedy dodajemy właściwość do obiektu za pomocą metody `defineProperty`, są one domyślnie _niewyliczalne_. Metoda `Object.keys` zwraca wszystkie _wyliczalne_ nazwy właściwości z obiektu, w tym przypadku tylko `"name"`. + +Właściwości dodane przy użyciu metody `defineProperty` są domyślnie niezmienne. Możesz nadpisać to zachowanie używając właściwości `writable`, `configurable` i `enumerable`. W ten sposób metoda `defineProperty` daje dużo większą kontrolę nad właściwościami dodawanymi do obiektu. + +
++ +#### Odpowiedź: A + +Drugim argumentem `JSON.stringify` jest _replacer_. Zamiennik może być funkcją lub tablicą i pozwala kontrolować, co i w jaki sposób wartości powinny być łańcuchowane. + +Jeśli zamiennik jest _tablicą_, tylko nazwy właściwości zawarte w tablicy zostaną dodane do łańcucha JSON. W tym przypadku tylko właściwości o nazwach `"level"` i `"health"` są uwzględnione, `"username"` jest wykluczone. `data` jest teraz równa `"{"level":19, "health":90}"`. + +Jeśli zamiennik jest _funkcją_, funkcja ta jest wywoływana na każdej właściwości obiektu, który stringujesz. Wartość zwrócona z tej funkcji będzie wartością właściwości, gdy zostanie ona dodana do łańcucha JSON. Jeśli wartość jest `undefined`, właściwość ta zostanie wykluczona z łańcucha JSON. + +
++ +#### Odpowiedź: A + +Operator jednoargumentowy `++` _najpierw zwraca_ wartość operandu, _potem zwiększa_ wartość operandu. Wartość `num1` to `10`, ponieważ funkcja `increaseNumber` najpierw zwraca wartość `num`, czyli `10`, a dopiero potem zwiększa wartość `num`. + +`num2` jest równe `10`, ponieważ przekazaliśmy `num1` do `increasePassedNumber`.`number` jest równe `10` (wartość `num1`). Ponownie, operator jednoargumentowy `++` _najpierw zwraca_ wartość operandu, _następnie zwiększa_ wartość operandu. Wartość `liczba` wynosi `10`, więc `liczba2` jest równa `10`. + +
++ +#### Odpowiedź: C + +W ES6 możemy inicjować parametry z wartością domyślną. Wartość parametru będzie wartością domyślną, jeśli żadna inna wartość nie została przekazana do funkcji lub jeśli wartość parametru jest `"undefined". W tym przypadku, rozkładamy właściwości obiektu `value` na nowy obiekt, więc `x` ma domyślną wartość `{ number: 10 }`. + +Domyślny argument jest obliczany w _call time_! Za każdym razem, gdy wywołujemy funkcję, tworzony jest _nowy_ obiekt. Wywołujemy funkcję `multiply` dwa pierwsze razy bez przekazywania wartości: `x` ma wartość domyślną `{ number: 10 }`. Następnie rejestrujemy pomnożoną wartość tej liczby, która wynosi `20`. + +Za trzecim razem, gdy wywołujemy multiply, przekazujemy argument: obiekt o nazwie `value`. Operator `*=` jest w rzeczywistości skrótem od `x.number = x.number * 2`: modyfikujemy wartość `x.number` i rejestrujemy pomnożoną wartość `20`. + +Za czwartym razem ponownie przekazujemy obiekt `value`. `x.number` zostało wcześniej zmodyfikowane do `20`, więc `x.number *= 2` loguje `40`. + +
+s + +#### Odpowiedź: D + +Pierwszym argumentem, który otrzymuje metoda `reduce` jest _accumulator_, w tym przypadku `x`. Drugim argumentem jest _bieżąca wartość_, `y`. Za pomocą metody reduce wykonujemy funkcję wywołania zwrotnego na każdym elemencie tablicy, co ostatecznie może skutkować jedną wartością. W tym przykładzie nie zwracamy żadnych wartości, po prostu rejestrujemy wartości akumulatora i wartości bieżącej. + +Wartość akumulatora jest równa poprzednio zwróconej wartości funkcji zwrotnej. Jeśli nie przekażesz opcjonalnego argumentu `initialValue` do metody `reduce`, akumulator jest równy pierwszemu elementowi przy pierwszym wywołaniu. + +Przy pierwszym wywołaniu, wartość akumulatora (`x`) wynosi `1`, a wartość bieżąca (`y`) wynosi `2`. Nie wracamy z funkcji zwrotnej, rejestrujemy akumulator i bieżącą wartość: `1` i `2` są rejestrowane. + +Jeśli nie zwrócisz wartości z funkcji, zwróci ona `undefined`. Przy następnym wywołaniu, akumulatorem jest `undefined`, a bieżącą wartością jest `3`. `undefined` i `3` są rejestrowane. + +Przy czwartym wywołaniu ponownie nie wracamy z funkcji zwrotnej. Akumulator jest ponownie `undefined`, a aktualna wartość to `4`. `undefined` i `4` są rejestrowane. + +
++ +#### Odpowiedź: B + +W klasie pochodnej nie można uzyskać dostępu do słowa kluczowego `this` przed wywołaniem `super`. Jeśli spróbujesz to zrobić, zostanie wyświetlony ReferenceError: 1 i 4 wyrzuci błąd referencji. + +Za pomocą słowa kluczowego `super` wywołujemy konstruktor klasy nadrzędnej z podanymi argumentami. Konstruktor rodzica otrzymuje argument `name`, więc musimy przekazać `name` do `super`. + +Klasa `Labrador` otrzymuje dwa argumenty, `name` ponieważ rozszerza klasę `Dog`, oraz `size` jako dodatkową właściwość klasy `Labrador`. Oba muszą być przekazane do funkcji konstruktora na `Labrador`, co jest zrobione poprawnie przy użyciu konstruktora 2. + +
++ +#### Odpowiedź: B + +Ze słowem kluczowym `import`, wszystkie zaimportowane moduły są _pre-parsed_. Oznacza to, że zaimportowane moduły są uruchamiane _najpierw_, a kod w pliku, który importuje moduł jest wykonywany _potem_. + +Jest to różnica pomiędzy `require()` w CommonJS i `import`! +Dzięki `require()` można ładować zależności na żądanie podczas wykonywania kodu. Jeśli użylibyśmy `require` zamiast `import`, w konsoli zostałoby wyświetlone `running index.js`, `running sum.js`, `3`. + +
++ +#### Odpowiedź: A + +Każdy Symbol jest całkowicie unikalny. Celem argumentu przekazywanego do Symbolu jest nadanie Symbolowi opisu. Wartość Symbolu nie zależy od przekazanego argumentu. Testując równość, tworzymy dwa zupełnie nowe symbole: pierwszy `Symbol('foo')` i drugi `Symbol('foo')`. Te dwie wartości są unikalne i nie są sobie równe, `Symbol('foo') == Symbol('foo')` zwraca `false`. + +
++ +#### Odpowiedź: C + +Za pomocą metody `padStart` możemy dodać dopełnienie na początku ciągu znaków. Wartością przekazywaną do tej metody jest _całkowita_ długość łańcucha wraz z dopełnieniem. Ciąg `"Lydia Hallie"` ma długość `12`. Metoda `name.padStart(13)` wstawia 1 spację na początku łańcucha, ponieważ 12 + 1 to 13. + +Jeśli argument przekazany do metody `padStart` jest mniejszy niż długość tablicy, dopełnienie nie zostanie dodane. + +
++ +#### Odpowiedź: A + +Za pomocą operatora `+` można łączyć ciągi znaków. W tym przypadku łączymy ciąg `"🥑"` z ciągiem `"💻"`, otrzymując `"🥑💻"`. + +
++ +#### Odpowiedź: C + +Funkcja generatora "wstrzymuje" swoje wykonanie, gdy widzi słowo kluczowe `yield`. Najpierw musimy pozwolić funkcji na wygenerowanie ciągu "Do you love JavaScript?", co można zrobić poprzez wywołanie `game.next().value`. + +Każda linia jest wykonywana, dopóki nie znajdzie pierwszego słowa kluczowego `yield`. W pierwszej linii funkcji znajduje się słowo kluczowe `yield`: wykonywanie zatrzymuje się wraz z pierwszym yield! Oznacza to, że zmienna `answer` nie jest jeszcze zdefiniowana! + +Kiedy wywołamy `game.next("Yes").value`, poprzedni `yield` zostanie zastąpiony wartością parametrów przekazanych do funkcji `next()`, w tym przypadku `"Yes``. Wartość zmiennej `answer` jest teraz równa `"Yes"`. Warunek instrukcji if zwraca `false`, a `JavaScript loves you back ❤️` zostaje zalogowany. + +
++ +#### Odpowiedź: C + +`String.raw` zwraca ciąg znaków, w którym znaki specjalne (`\n`, `\v`, `\t` itd.) są ignorowane! Backslashe mogą być problemem, ponieważ można skończyć z czymś takim jak:`` const path = `C:\Documents\Projects\table.html` `` + +Co skutkowałoby: + +`"C:DocumentsProjects able.html"`Z `String.raw`, po prostu zignorowałby ucieczkę i wyświetliłby: + +`C:\Documents\Projects\table.html`. + +W tym przypadku ciąg to `Hello\nworld`, który zostanie wyświetlony. + +
++ +#### Odpowiedź: C + +Funkcja asynchroniczna zawsze zwraca obietnicę. Funkcja `await` wciąż musi czekać na rozwiązanie obietnicy: oczekująca obietnica zostanie zwrócona, gdy wywołamy `getData()` w celu ustawienia `data` równym tej obietnicy. + +Jeśli chcielibyśmy uzyskać dostęp do rozwiązanej wartości `"I made it"`, moglibyśmy użyć metody `.then()` na `data`:`data.then(res => console.log(res))`. + +To wyświtliłoby w konsoli `"Udało mi się!"`. + +
++ +#### Odpowiedź: B + +Metoda `.push()` zwraca _długość_ nowej tablicy! Poprzednio tablica zawierała jeden element (string `"banan"`) i miała długość `1`. Po dodaniu stringa `"apple"` do tablicy, tablica zawiera dwa elementy i ma długość `2`. Jest to zwracane przez funkcję `addToList`. Metoda `push` modyfikuje oryginalną tablicę. + +Jeśli chciałeś zwrócić _array_ z funkcji, a nie _length of the array_, powinieneś był zwrócić `list` po dodaniu do niej `item`. + +
++ +#### Odpowiedź: B + +`Object.freeze` uniemożliwia dodawanie, usuwanie lub modyfikowanie właściwości obiektu (chyba że wartością właściwości jest inny obiekt). + +Kiedy tworzymy zmienną `shape` i ustawiamy ją jako równą zamrożonemu obiektowi `box`, `shape` również odnosi się do zamrożonego obiektu. Możesz sprawdzić czy obiekt jest zamrożony używając `Object.isFrozen`. W tym przypadku, `Object.isFrozen(shape)` zwróciłby true, ponieważ zmienna `shape` posiada referencję do zamrożonego obiektu. + +Ponieważ `shape` jest zamrożony, a wartość `x` nie jest obiektem, nie możemy modyfikować właściwości `x`.`x` jest nadal równe `10`, a `{ x: 10, y: 20 }` zostaje wyświetlone w konsoli. + +
++ +#### Answer: C + +`String.raw` retorna um texto onde os escape (`\n`, `\v`, `\t` etc.) são ignorados! As barras invertidas podem ser um problema, pois você pode acabar com algo como: + +`` caminho const = `C:\Documents\Projects\table.html` `` + +O que resultaria em: + +`"C:DocumentsProjectstable.html"` + +Com `String.raw`, ele simplesmente ignoraria o escape e imprimiria: + +`C:\Documents\Projects\table.html` + +Neste caso, a string é `Hello\nworld`, que é registrada. + +
++ +#### Resposta: C + +Uma função assíncrona sempre retorna uma promise. O `await` ainda tem que esperar que a promise seja resolvida: uma promise pendente é retornada quando chamamos `getData()` para definir `data` igual a ela. + +Se quiséssemos ter acesso ao valor resolvido `"I made it"`, poderíamos ter usado o método `.then()` em `data`: + +`data.then(res => console.log(res))` + +Isso teria registrado `"Consegui!"` + +
++ +#### Answer: B + +O método `.push()` retorna o _length_ do novo array! Anteriormente, a matriz continha um elemento (a string `"banana"`) e tinha um comprimento de `1`. Depois de adicionar a string `"apple"` ao array, o array contém dois elementos e tem um comprimento de `2`. Isso é retornado da função `addToList`. + +O método `push` modifica o array original. Se você quisesse retornar o _array_ da função ao invés do _tamanho do array_, você deveria ter retornado `list` depois de enviar `item` para ele. + +
++ +#### Answer: B + +`Object.freeze` torna impossível adicionar, remover ou modificar propriedades de um objeto (a menos que o valor da propriedade seja outro objeto). + +Quando criamos a variável `shape` e a definimos igual ao objeto congelado `box`, `shape` também se refere a um objeto congelado. Você pode verificar se um objeto está congelado usando `Object.isFrozen`. Neste caso, `Object.isFrozen(shape)` retorna true, pois a variável `shape` tem uma referência a um objeto congelado. + +Como `shape` está congelado, e como o valor de `x` não é um objeto, não podemos modificar a propriedade `x`. `x` ainda é igual a `10`, e `{ x: 10, y: 20 }` é registrado. + +
++ +#### Answer: D + +Quando descompactamos a propriedade `name` do objeto do lado direito, atribuímos seu valor `"Lydia"` a uma variável com o nome `myName`. + +Com `{ name: myName }`, informamos ao JavaScript que queremos criar uma nova variável chamada `myName` com o valor da propriedade `name` no lado direito. + +Quando tentamos mostrar o conteúdo de `name`, uma variável que não está definida, recebemos o erro `ReferenceError`. + +
++ +#### Answer: A + +Uma função pura é uma função que _sempre_ retorna o mesmo resultado, se os mesmos argumentos forem passados. + +A função `sum` sempre retorna o mesmo resultado. Se passarmos `1` e` 2`, ele _sempre_ retornará `3` sem efeitos colaterais. Se passarmos `5` e `10`, ele _sempre_ retornará `15`, e assim por diante. Esta é a definição de uma função pura. + +
++ +#### Answer: C + +A função `add` é uma função _memoized_ (memorizada). Com a memorização, podemos armazenar em cache os resultados de uma função para acelerar sua execução. Nesse caso, criamos um objeto `cache` que armazena os valores retornados anteriormente. + +Se chamarmos a função `addFunction` novamente com o mesmo argumento, ela primeiro verifica se já obteve esse valor em seu cache. Se for o caso, o valor dos caches será retornado, o que economiza tempo de execução. Caso contrário, se não estiver armazenado em cache, ele calculará o valor e o armazenará posteriormente. + +Chamamos a função `addFunction` três vezes com o mesmo valor: na primeira chamada, o valor da função quando `num` é igual a `10` ainda não é armazenado em cache. A condição da instrução if `num in cache` retorna `false`, e o bloco else é executado: `Calculated! 20` é registrado e o valor do resultado é adicionado ao objeto de cache. `cache` agora se parece com` {10:20} `. + +Na segunda vez, o objeto `cache` contém o valor que é retornado para `10`. A condição da instrução if `num in cache` retorna `true`, e `'From cache! 20'` é registrado. + +Na terceira vez, passamos `5 * 2` para a função que é avaliada como `10`. O objeto `cache` contém o valor que é retornado para `10`. A condição da instrução if `num in cache` retorna `true`, e `'From cache! 20'` é registrado. + +
++ +#### Answer: A + +Com um loop _for-in_, podemos iterar sobre propriedades **enumeráveis**. Em um array, as propriedades enumeráveis são as "chaves" dos elementos do array, que na verdade são seus índices. Você pode ver uma matriz como: + +`{0:" ☕ ", 1:" 💻 ", 2:" 🍷 ", 3:" 🍫 "}` + +Onde as chaves são as propriedades enumeráveis. `0`` 1` `2`` 3` são registrados. + +Com um loop _for-of_, podemos iterar sobre **iteráveis**. Um array é um iterável. Quando iteramos sobre o array, a variável "item" é igual ao elemento sobre o qual está iterando no momento, `" ☕ "` `" 💻 "` `" 🍷 "` `" 🍫 "` são registrados. + +
++ +#### Answer: C + +Os elementos da matriz podem conter qualquer valor. Números, strings, objetos, outras matrizes, valores nulos, booleanos, indefinidos e outras expressões, como datas, funções e cálculos. + +O elemento será igual ao valor retornado. `1 + 2` retorna` 3`, `1 * 2` retorna` 2` e `1 / 2` retorna` 0,5`.
+ +- [🇸🇦 العربية](./ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](./de-DE/README.md) +- [🇪🇸 Español](./es-ES/README-ES.md) +- [🇫🇷 Français](./fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](./id-ID/README.md) +- [🇮🇹 Italiano](./it-IT/README.md) +- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](./ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](./nl-NL/README.md) +- [🇵🇱 Polski](./pl-PL/README.md) +- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) +- [🇷🇺 Русский](./ru-RU/README.md) +- [🇽🇰 Shqip](./sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](./th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](./uk-UA/README.md) +- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) +- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) + +
++ +#### Răspuns: D + +În interiorul funcției, mai întâi declarăm variabila `name` cu cuvântul cheie `var`. Acest lucru înseamnă că variabila este hoisted (spațiul de memorie este configurat în faza de creare) cu valoarea implicită `undefined`, până când ajungem efectiv la linia în care definim variabila. Nu am definit încă variabila pe linia în care încercăm să înregistrăm variabila `name`, așa că aceasta păstrează încă valoarea `undefined`. + +Variabilele create cu cuvântul cheie `let` (și `const`) sunt hoisted, dar, spre deosebire de `var`, nu sunt inițializate. Acestea nu sunt accesibile înainte de linia în care le declarăm (initializăm). Aceasta se numește zona moartă temporală (temporal dead zone). Atunci când încercăm să accesăm variabilele înainte de a fi declarate, JavaScript aruncă o excepție de tip `ReferenceError`. + +
++ +#### Răspuns: C + +Datorită cozii de evenimente din JavaScript, funcția de callback `setTimeout` este apelată _după_ ce bucla a fost executată. Deoarece variabila `i` din prima buclă a fost declarată folosind cuvântul cheie `var`, această valoare a fost globală. În timpul buclei, am incrementat valoarea lui `i` cu `1` de fiecare dată, folosind operatorul unary `++`. Până când funcția de callback `setTimeout` a fost invocată, `i` era egal cu `3` în primul exemplu. + +În cea de-a doua buclă, variabila `i` a fost declarată folosind cuvântul cheie `let`: variabilele declarate cu cuvântul cheie `let` (și `const`) sunt cu scop la nivel de bloc (un bloc este orice între `{ }`). În fiecare iterație, `i` va avea o valoare nouă, iar fiecare valoare este în cadrul buclei. + +
++ +#### Răspuns: B + +Rețineți că valoarea lui `diameter` este o funcție obișnuită, în timp ce valoarea lui `perimeter` este o funcție arrow. + +Cu funcțiile arrow, cuvântul cheie `this` se referă la contextul său curent de încadrare, spre deosebire de funcțiile obișnuite! Acest lucru înseamnă că atunci când apelăm `perimeter`, acesta nu se referă la obiectul formei, ci la încadrarea sa curentă (de exemplu, fereastra). + +Nu există nicio valoare `radius` pe acel obiect, ceea ce returnează `NaN`. + +
++ +#### Răspuns: A + +Operatorul unary plus încearcă să convertească un operand într-un număr. `true` este `1`, și `false` este `0`. + +Șirul de caractere `'Lydia'` este o valoare adevărată. Ceea ce întrebăm de fapt, este "este această valoare adevărată falsă?". Acest lucru returnează `false`. + +
++ +#### Răspuns: A + +În JavaScript, toate cheile obiectelor sunt șiruri de caractere (cu excepția simbolurilor). Chiar dacă nu le _tipizăm_ ca șiruri de caractere, ele sunt întotdeauna convertite în șiruri de caractere în fundal. + +avaScript interpretează (sau dezambalează) instrucțiunile. Atunci când folosim notația cu paranteze pătrate, vede prima paranteză pătrată de deschidere `[` și continuă până când găsește paranteza pătrată de închidere `]`. Doar atunci va evalua instrucțiunea. + +`mouse[bird.size]`: Întâi evaluează `bird.size`, care este `"small"`. `mouse["small"]` returnează `true` + +Cu toate acestea, cu notația cu punct, acest lucru nu se întâmplă. `mouse` nu are o cheie numită `bird`, ceea ce înseamnă că `mouse.bird` este `undefined`. Apoi, cerem `size` folosind notația cu punct: `mouse.bird.size`. Deoarece `mouse.bird` este `undefined`, de fapt cerem `undefined.size`. Acest lucru nu este valid și va arunca o eroare similară cu `Cannot read property "size" of undefined` (Nu se poate citi proprietatea "size" a unei valori nedefinite). + +
+
+
+#### Răspuns: A
+
+În JavaScript, toate obiectele interacționează prin _referință_ atunci când sunt setate ca egale între ele.
+
+Mai întâi, variabila `c` deține o valoare care face referire la un obiect. Ulterior, atribuim variabilei `d` aceeași referință pe care o are `c` la obiect.
+
+
+
+Când modifici un obiect, le modifici pe toate.
+
+
+ +#### Răspuns: C + +`new Number()` este un constructor de funcții încorporat. Deși arată ca un număr, nu este într-adevăr un număr: are o mulțime de funcționalități suplimentare și este un obiect. + +Atunci când folosim operatorul `==` (operatorul de egalitate), acesta verifică doar dacă au aceeași _valuare_. Ambele au valoarea `3`, șa că returnează `true`. + +Cu toate acestea, atunci când folosim operatorul `===` (operatorul de egalitate strictă), atât valoarea, cât _și_ tipul trebuie să fie la fel. Nu sunt: `new Number()` nu este un număr, este un **object**. Ambele returnează `false.` + +
++ +#### Răspuns: D + +Funcția `colorChange` este statică. Metodele statice sunt concepute să existe doar pe constructorul în care sunt create și nu pot fi transmise către niciun copil sau apelate pe instanțele clasei. Deoarece `freddie` este o instanță a clasei Chameleon, funcția nu poate fi apelată pe aceasta. Se aruncă o eroare de tip `TypeError`. + +
++ +#### Răspuns: A + +Se afișează obiectul, deoarece tocmai am creat un obiect gol pe obiectul global! Atunci când am greșit și am scris `greeting` în loc de `greetign`, interpretorul JavaScript a văzut efectiv acest lucru ca: + +1. `global.greetign = {}` în Node.js +2. `window.greetign = {}`, `frames.greetign = {}` și `self.greetign` în browser-e. +3. `self.greetign` în web workers. +4. `globalThis.greetign` în toate mediile. + +Pentru a evita acest lucru, putem folosi `"use strict"`. Acest lucru se asigură că ai declarat o variabilă înainte de a-i atribui o valoare. + +
++ +#### Răspuns: A + +Acest lucru este posibil în JavaScript, deoarece funcțiile sunt obiecte! (Totul, în afară de tipurile primitive, sunt obiecte) + +O funcție este un tip special de obiect. Codul pe care îl scrii tu însuți nu este funcția efectivă. Funcția este un obiect cu proprietăți. Această proprietate este invocabilă. + +
++ +#### Răspuns: A + +În JavaScript, funcțiile sunt obiecte și, prin urmare, metoda `getFullName` este adăugată obiectului constructor al funcției în sine. Din acest motiv, putem apela `Person.getFullName()`, dar `member.getFullName` aruncă o eroare de tip `TypeError`. + +Dacă doriți ca o metodă să fie disponibilă pentru toate instanțele obiectului, trebuie să o adăugați la proprietatea prototype: + +```js +Person.prototype.getFullName = function () { + return `${this.firstName} ${this.lastName}`; +}; +``` + +
++ +#### Răspuns: A + +Pentru `sarah`, nu am folosit cuvântul cheie `new`. Când folosim `new`, `this` se referă la noul obiect gol pe care îl creăm. Cu toate acestea, dacă nu adăugăm `new`, `this` se referă la **obiectul global**! + +Am spus că `this.firstName` este egal cu `"Sarah"` și `this.lastName` este egal cu `"Smith"`. Ceea ce am făcut de fapt este să definim `global.firstName = 'Sarah'` și `global.lastName = 'Smith'`. `sarah` în sine rămâne `undefined`, deoarece nu returnăm o valoare din funcția `Person`. + +
+
+
+#### Răspuns: D
+
+În timpul fazei de **capturing**, evenimentul trece prin elementele părinte până la elementul țintă. Apoi ajunge la elementul **target**, și începe **bubbling**.
+
+
+
+
+ +#### Răspuns: B + +Toate obiectele au prototipuri, cu excepția **obiectului de bază**. Obiectul de bază este obiectul creat de utilizator sau un obiect creat folosind cuvântul cheie `new`. Obiectul de bază are acces la unele metode și proprietăți, cum ar fi `.toString`. Acesta este motivul pentru care puteți utiliza metode JavaScript încorporate! Toate aceste metode sunt disponibile în prototip. Deși JavaScript nu le poate găsi direct în obiectul dvs., merge în jos pe lanțul prototip și le găsește acolo, ceea ce le face accesibile pentru dvs. + +
++ +#### Răspuns: C + +JavaScript este un limbaj **dinamic tipizat**: nu specificăm tipurile variabilelor. Valorile pot fi convertite automat în alt tip fără să știți, ceea ce se numește _coerție de tip implicită_. **Coerția** este conversia dintr-un tip în altul. + +În acest exemplu, JavaScript convertește numărul `1` într-un șir de caractere, pentru ca funcția să aibă sens și să returneze o valoare. În timpul adunării unui tip numeric (`1`) și unui tip șir de caractere (`'2'`), numărul este tratat ca un șir de caractere. Putem concatena șiruri de caractere, așa cum facem cu `"Hello" + "World"`, deci ceea ce se întâmplă aici este `"1" + "2"` care returnează `"12"`. + +
++ +#### Răspuns: C + +Operatorul unary **postfix** `++`: + +1. Returnează valoarea (aceasta returnează `0`) +2. Incrementează valoarea (numărul este acum `1`) + +Operatorul unary **prefix** `++`: + +1. Incrementează valoarea (numărul este acum `2`) +2. Returnează valoarea (aceasta returnează `2`) + +Aceasta returnează `0 2 2`. + +
++ +#### Răspuns: B + +Dacă utilizați șiruri template etichetate, valoarea primului argument este întotdeauna un șir de valori. Argumentele rămase primesc valorile expresiilor transmise! + +
++ +#### Răspuns: C + +Când se testează egalitatea, primitivele sunt comparate în funcție de valoarea lor, în timp ce obiectele sunt comparate în funcție de _referința_ lor. JavaScript verifică dacă obiectele au o referință către aceeași locație în memorie. + +Cele două obiecte pe care le comparăm nu au aceeași referință: obiectul pe care l-am trecut ca parametru se referă la o altă locație în memorie decât obiectul pe care l-am folosit pentru a verifica egalitatea. + +Acesta este motivul pentru care ambele `{ age: 18 } === { age: 18 }` și `{ age: 18 } == { age: 18 }` returnează `false`. + +
++ +#### Răspuns: C + +Parametrul rest (`...args`) ne permite să "colectăm" toate argumentele rămase într-un array. Un array este un obiect, așa că `typeof args` returnează `"object"` + +
++ +#### Răspuns: C + +Cu `"use strict"`, puteți asigura că nu declarați accidental variabile globale. Niciodată nu am declarat variabila `age`, și deoarece folosim `"use strict"`, va arunca o eroare de referință. Dacă nu am fi folosit `"use strict"`, ar fi funcționat, deoarece proprietatea `age` ar fi fost adăugată la obiectul global. + +
++ +#### Răspuns: A + +`eval` evaluează codul care este trecut ca un șir de caractere. Dacă este o expresie, așa cum este în acest caz, evaluează expresia. Expresia este `10 * 10 + 5`. Aceasta returnează numărul `105`. + +
++ +#### Răspuns: B + +Datele stocate în `sessionStorage` sunt eliminate după închiderea _filei_. + +Dacă ați fi folosit `localStorage`, datele ar fi rămas acolo pentru totdeauna, cu excepția cazului în care, de exemplu, este invocată comanda `localStorage.clear()`. + +
++ +#### Răspuns: B + +Cu cuvântul cheie `var`, puteți declara mai multe variabile cu același nume. Variabila va reține apoi cea mai recentă valoare. + +Nu puteți face acest lucru cu `let` sau `const` deoarece acestea sunt cu scop de bloc. + +
++ +#### Răspuns: C + +Toate cheile obiectelor (cu excepția simbolurilor) sunt șiruri de caractere în culise, chiar dacă nu le tastați ca șiruri de caractere. De aceea `obj.hasOwnProperty('1')` returnează de asemenea `true`. + +Acest lucru nu funcționează în același fel pentru un set. Nu există `'1'` în setul nostru: `set.has('1')` returnează `false`. Acesta are tipul numeric `1`, `set.has(1)` returnează `true`. + +
++ +#### Răspuns: C + +Dacă aveți două chei cu același nume, cheia va fi înlocuită. Va rămâne totuși în prima sa poziție, dar cu ultima valoare specificată. + +
++ +#### Răspuns: A + +Contextul de execuție de bază este contextul global de execuție: este ceea ce este accesibil peste tot în codul dvs. + +
++ +#### Răspuns: C + +Instrucțiunea `continue` sare peste o iterație dacă o anumită condiție returnează `true`. + +
++ +#### Răspuns: A + +`String` este un constructor încorporat, la care putem adăuga proprietăți. Am adăugat doar o metodă la prototipul său. Șirurile primitive sunt convertite automat într-un obiect șir, generat de funcția prototip a șirului. Prin urmare, toate șirurile (obiecte de șir) au acces la acea metodă! + +
++ +#### Răspuns: B + +Cheile obiectului sunt convertite automat în șiruri de caractere. Încercăm să setăm un obiect ca cheie pentru obiectul `a`, cu valoarea `123`. + +Cu toate acestea, când transformăm în șir un obiect, acesta devine `"[object Object]"`. Deci ceea ce spunem aici este că `a["[object Object]"] = 123`. Apoi, putem încerca să facem același lucru din nou. `c` este un alt obiect pe care îl transformăm implicit în șir. Așadar, `a["[object Object]"] = 456`. + +Apoi, afișăm înregistrarea `a[b]`, care de fapt este `a["[object Object]"]`. Am setat doar asta la `456`, deci returnează `456`. + +
+
+
+#### Răspuns: B
+
+Avem o funcție `setTimeout` și am invocat-o mai întâi. Cu toate acestea, a fost înregistrată în ultimul rând.
+
+Acest lucru se datorează faptului că în browsere, nu avem doar motorul de execuție, avem și ceva numit `WebAPI`.`WebAPI` ne oferă funcția `setTimeout` de exemplu, și DOM-ul.
+
+După ce _callback_-ul este trimis către WebAPI, funcția `setTimeout` în sine (dar nu și callback-ul!) este scos din stivă.
+
+
+
+Acum, `foo` este invocată, iar`"First"` este înregistrat.
+
+
+
+`foo` este scoasă din stivă, iar `baz` este invocată. Se înregistrează `"Third"`.
+
+
+
+WebAPI-ul nu poate adăuga pur și simplu lucruri în stivă atunci când este gata. În schimb, împinge funcția de callback într-o structură numită _coadă_.
+
+
+
+Aici începe să lucreze un event loop. Un **event loop** se uită la stivă și la coada de sarcini. Dacă stiva este goală, ia primul lucru din coadă și-l adaugă în stivă.
+
+
+
+`bar` este invocată, `"Second"` este înregistrat și este scos din stivă.
+
+
+ +#### Răspuns: C + +Cel mai profund element înglobat care a cauzat evenimentul este ținta evenimentului. Puteți opri propagarea acestuia prin `event.stopPropagation` + +
++ Click here! +
++ +#### Răspuns: A + +Dacă facem clic pe `p`, vom vedea două înregistrări: `p` și `div`. În timpul propagării evenimentului, există 3 faze: capturare, țintă și propagare. În mod implicit, gestionarii de evenimente sunt executați în faza de propagare (cu excepția cazului în care setați `useCapture` la `true`). Aceștia se execută de la cel mai profund element înglobat către exterior. + +
++ +#### Răspuns: D + +Cu ambele metode, putem transmite obiectul la care dorim să se refere cuvântul cheie `this`. Cu toate acestea, `.call` este de asemenea _executat imediat_! + +`.bind.` returnează o _copie_ a funcției, dar cu un context legat! Nu este executat imediat. + +
++ +#### Răspuns: B + +Funcția `sayHi` returnează valoarea returnată de expresia funcției invocate imediat (IIFE). This function returned `0`, care este de tip `"number"`. + +Informație utilă: `typeof` poate returna următoarele valori: `undefined`, `boolean`, `number`, `bigint`, `string`, `symbol`, `function` și `object`. Notați că `typeof null` returnează `"object"`. + +
++ +#### Răspuns: A + +Există 8 valori considerate falsy: + +- `undefined` +- `null` +- `NaN` +- `false` +- `''` (șir de caractere gol) +- `0` +- `-0` +- `0n` (BigInt(0)) + +Constructorii de funcții, cum ar fi `new Number` și `new Boolean` sunt considerați truthy. + +
++ +#### Răspuns: B + +`typeof 1` returnează `"number"`. +`typeof "number"` returnează `"string"` + +
++ +#### Răspuns: C + +Când setați o valoare pentru un element într-un array care depășește lungimea array-ului, JavaScript creează ceea ce se numește "slot-uri goale" (empty slots). Acestea au de fapt valoarea `undefined`, dar veți vedea ceva de genul: + +`[1, 2, 3, empty x 7, 11]` + +în funcție de locul în care îl rulați (este diferit pentru fiecare browser, Node.js, etc.) + +
++ +#### Răspuns: A + +Blocul `catch` primește argumentul `x`. Acesta nu este același `x` ca variabila când transmitem argumente. Această variabilă `x` este având domeniu de bloc (block-scoped). + +Mai târziu, setăm această variabilă cu domeniu de bloc la valoarea `1`, și stabilim valoarea variabilei `y`. Acum, înregistrăm în consolă variabila cu domeniu de bloc `x`, care este egală cu `1`. + +În afara blocului `catch`, `x` rămâne `undefined`, și `y` este `2`. Atunci când dorim să afișăm în consolă `console.log(x)` în afara blocului `catch`, acesta returnează `undefined`, și `y` returnează `2`. + +
++ +#### Răspuns: A + +JavaScript are doar tipuri primitive și obiecte. + +Tipurile primitive sunt `boolean`, `null`, `undefined`, `bigint`, `number`, `string`, și `symbol`. + +Ceea ce diferențiază un tip primitiv de un obiect este faptul că tipurile primitive nu au proprietăți sau metode. Cu toate acestea, veți observa că `'foo'.toUpperCase()` se evaluează la `'FOO'` și nu duce la o eroare `TypeError`. Acest lucru se întâmplă pentru că atunci când încercați să accesați o proprietate sau o metodă pe un tip primitiv, cum ar fi un șir de caractere (string), JavaScript va înconjura implicit tipul primitiv folosind una dintre clasele de înveliș, adică `String`, și apoi va renunța imediat la înveliș după ce expresia se evaluează. Toate tipurile primitive, cu excepția `null` și `undefined` prezintă acest comportament. + +
++ +#### Răspuns: C + +`[1, 2]` este valoarea noastră inițială. Aceasta este valoarea cu care începem și valoarea primului `acc`. În prima rundă, `acc` este `[1,2]`, și `cur` este `[0, 1]`. Le concatenăm, ceea ce duce la rezultatul `[1, 2, 0, 1]`. + +Atunci, `[1, 2, 0, 1]` este `acc` și `[2, 3]` este `cur`. Le concatenăm și obținem `[1, 2, 0, 1, 2, 3]` + +
++ +#### Răspuns: B + +`null` este falsy. `!null` returnează `true`. `!true` returnează `false`. + +`""` este falsy. `!""` returnează `true`. `!true` returnează `false`. + +`1` este truthy. `!1` returnează `false`. `!false` returnează `true`. + +
++ +#### Răspuns: A + +Aceasta returnează un identificator unic. Acest id poate fi utilizat pentru a opri intervalul respectiv cu ajutorul funcției `clearInterval()`. + +
++ +#### Răspuns: A + +Un șir de caractere este un obiect iterabil. Operatorul de răspândire (spread operator) mapează fiecare caracter dintr-un obiect iterabil la un element separat. + +
++ +#### Răspuns: C + +Funcțiile regulate nu pot fi oprite în mijlocul execuției după invocare. Cu toate acestea, o funcție generator poate fi "oprită" în mijloc și ulterior poate continua de la locul unde s-a oprit. De fiecare dată când o funcție generator întâlnește un cuvânt cheie `yield`, funcția furnizează valoarea specificată după el. Notați că funcția generator în acest caz nu _returnează_ the valoarea, ci _furnizează_ valoarea. + +Mai întâi, inițializăm funcția generator cu `i` egal cu `10`. Invocăm funcția generator folosind metoda `next()`. Prima dată când invocăm funcția generator, `i` este egal cu `10`. Aceasta întâlnește primul cuvânt cheie `yield`: furnizează valoarea lui `i`. Generatorul este acum "pauzat", și se înregistrează valoarea `10`. + +Apoi, invocăm din nou funcția cu metoda `next()`. Ea începe să continue de unde s-a oprit anterior, încă cu `i` egal cu `10`. Acum, întâlnește următorul cuvânt cheie `yield`, și furnizează `i * 2`. `i` este egal cu `10`, așa că returnează `10 * 2`, adică `20`. Acest lucru duce la rezultatul `10, 20`. + +
++ +#### Răspuns: B + +Atunci când transmitem mai multe promisiuni metodei `Promise.race`, ea rezolvă/rejectează _prima_ promisiune care se rezolvă/rejectează. Pentru metoda `setTimeout`, transmitem un cronometru: 500ms pentru prima promisiune (`firstPromise`), și 100ms pentru a doua promisiune (`secondPromise`). Acest lucru înseamnă că `secondPromise` se rezolvă primul cu valoarea `'two'`. `res` conține acum valoarea `'two'`, care se înregistrează în consolă. + +
+
+
+#### Răspuns: D
+
+În primul rând, declarăm o variabilă `person` cu valoarea unui obiect care are o proprietate `name`.
+
+
+
+Apoi, declarăm o variabilă numită `members`. Setăm primul element al acestui array egal cu valoarea variabilei `person`. Obiectele interacționează prin _referință_ atunci când le setăm egale între ele. Atunci când atribuiți o referință de la o variabilă la alta, faceți o _copie_ a acelei referințe. (notați că acestea nu au _aceași_ referință!)
+
+
+
+Apoi, setăm variabila `person` egală cu `null`.
+
+
+
+Noi modificăm doar valoarea variabilei `person` nu și primul element din array, deoarece acel element are o referință diferită (copiată) la obiect. Primul element din `members` încă păstrează referința sa la obiectul original. Când înregistrăm în consolă array-ul `members` primul element păstrează valoarea obiectului, care este afișată în consolă.
+
+
+ +#### Răspuns: B + +Cu un ciclu `for-in` putem itera prin cheile obiectului, în acest caz `name` și `age`. În interior, cheile obiectului sunt șiruri de caractere (dacă nu sunt de tip Symbol). În fiecare iterație, setăm valoarea lui `item` egală cu cheia curentă pe care o parcurge. Mai întâi, `item` este egal cu `name`, și este înregistrat în consolă. Apoi, `item` este egal cu `age`, care este, de asemenea, înregistrat în consolă. + +
++ +#### Răspuns: B + +Asociativitatea operatorilor este ordinea în care compilatorul evaluează expresiile, fie de la stânga la dreapta, fie de la dreapta la stânga. Acest lucru se întâmplă doar dacă toți operatorii au aceeași precedență. În cazul nostru, avem doar un tip de operator: `+`. Pentru adunare, asociativitatea este de la stânga la dreapta. + +`3 + 4` este evaluat mai întâi. Acest lucru duce la numărul `7`. + +`7 + '5'` duce la rezultatul `"75"` datorită coerției. JavaScript convertește numărul `7` într-un șir de caractere, așa cum am discutat în întrebarea 15. Putem concatena două șiruri de caractere folosind operatorul `+`. `"7" + "5"` rezultă în `"75"`. + +
++ +#### Răspuns: C + +Este returnat doar primul număr din șir. Bazat pe _radix_ (al doilea argument pentru a specifica în ce tip de număr dorim să-l parsăm: bază 10, hexazecimal, octal, binar, etc.), `parseInt` verifică dacă caracterele din șir sunt valide. Odată ce întâlnește un caracter care nu este un număr valid în baza specificată, oprește parsarea și ignoră caracterele ulterioare. + +`*` nu este un număr valid. Parsează doar `"7"` în numărul zecimal `7`. Acum, `num` conține valoarea `7`. + +
++ +#### Răspuns: C + +Când se parcurge array-ul, valoarea lui `num` este egală cu elementul prin care parcurge în acel moment. În acest caz, elementele sunt numere, astfel că condiția din instrucțiunea `typeof num === "number"` returnează `true`. Funcția map creează un nou array și introduce valorile returnate de funcție. + +Cu toate acestea, nu returnăm o valoare. Atunci când nu returnăm o valoare din funcție, funcția returnează `undefined`. Pentru fiecare element din array, blocul funcției este apelat, deci pentru fiecare element returnăm `undefined`. + +
++ +#### Răspuns: A + +Argumentele sunt transmise prin _valoare_, cu excepția cazului în care valoarea lor este un obiect, caz în care sunt transmise prin _referință_. `birthYear` este transmis prin valoare, deoarece este un șir de caractere (string), nu un obiect. Atunci când transmitem argumente prin valoare, se creează o _copie_ a acelei valori (consultați întrebarea 46). + +Variabila `birthYear` are o referință la valoarea `"1997"`. Argumentul `year` are, de asemenea, o referință la valoarea `"1997"`, dar nu este aceeași valoare la care se referă `birthYear`. Atunci când actualizăm valoarea lui `year` prin setarea lui `year` egal cu `"1998"`, actualizăm doar valoarea lui `year`. `birthYear` rămâne în continuare egal cu `"1997"`. + +Valoarea lui `person` este un obiect. Argumentul `member` are o referință (copiată) către _același_ obiect. Atunci când modificăm o proprietate a obiectului la care se referă `member` valoarea lui `person` va fi de asemenea modificată, deoarece ambele au o referință la același obiect. Proprietatea `name` a lui `person` este acum egală cu valoarea `"Lydia"`. + +
++ +#### Răspuns: D + +Cu instrucțiunea `throw` putem crea erori personalizate. Cu această instrucțiune, puteți arunca excepții. O excepție poate fi un șir de caractere, un număr, un boolean sau un obiect. În acest caz, excepția noastră este șirul `'Hello world!'`. + +Cu instrucțiunea `catch` putem specifica ce să facem dacă o excepție este aruncată în blocul `try`. O excepție este aruncată: șirul `'Hello world!'`. `e` este acum egal cu acel șir, pe care îl înregistrăm. Acest lucru duce la rezultatul `'Oh an error: Hello world!'`. + +
++ +#### Răspuns: B + +Atunci când o funcție constructor este apelată cu cuvântul cheie `new`, aceasta creează un obiect și stabilește cuvântul cheie `this` să se refere la acel obiect. În mod implicit, dacă funcția constructor nu returnează explicit nimic, va returna obiectul creat recent. + +În acest caz, funcția constructor `Car` returnează în mod explicit un obiect nou cu proprietatea `make` setată la `"Maserati"`, ceea ce suprascrie comportamentul implicit. Prin urmare, atunci când este apelat `new Car()` obiectul _returnat_ este atribuit lui `myCar`, ceea ce duce la rezultatul `"Maserati"` atunci când se accesează `myCar.make`. + +
++ +#### Răspuns: A + +`let x = (y = 10);` este de fapt o prescurtare pentru + +```javascript +y = 10; +let x = y; +``` + +Când setăm `y` egal cu `10`, adăugăm de fapt o proprietate `y` la obiectul global (`window` într-un browser, `global` în Node). Într-un browser, `window.y` este acum egal cu `10`. + +Apoi, declarăm o variabilă `x` cu valoarea `y`, care este `10`. Variabilele declarate cu cuvântul cheie `let` au domeniu de bloc _block scoped_, ele sunt definite doar în blocul în care sunt declarate; în cazul de față, în funcția expresie invocată imediat (IIFE). Atunci când folosim operatorul `typeof` operandul `x` nu este definit: încercăm să accesăm `x` în afara blocului în care este declarat. Acest lucru înseamnă că `x` nu este definit. Valorile care nu au primit o valoare sau nu au fost declarate sunt de tip `"undefined"`. `console.log(typeof x)` returnează `"undefined"`. + +Cu toate acestea, am creat o variabilă globală `y` atunci când am setat `y` egal cu `10`. Această valoare este accesibilă oriunde în codul nostru. `y` este definită și deține o valoare de tip `"number"`. `console.log(typeof y)` returnează `"number"`. + +
++ +#### Răspuns: A + +Putem șterge proprietăți din obiecte folosind cuvântul cheie `delete` inclusiv de pe prototip. Prin ștergerea unei proprietăți de pe prototip, aceasta nu mai este disponibilă în lanțul prototipului. În acest caz, funcția `bark` nu mai este disponibilă pe prototip după `delete Dog.prototype.bark`, dar încercăm totuși să o accesăm. + +Când încercăm să apelăm ceva care nu este o funcție, este aruncată o excepție `TypeError`. În acest caz, se generează eroarea `TypeError: pet.bark is not a function`, deoarece `pet.bark` este `undefined`. + +
++ +#### Răspuns: D + +Obiectul `Set` este o colecție de valori unice: o valoare poate apărea doar o singură dată într-un set. + +m transmis iterable-ul `[1, 1, 2, 3, 4]` cu o valoare duplicată `1`. Deoarece nu putem avea două valori identice într-un set, una dintre ele este eliminată. Acest lucru duce la rezultatul `{1, 2, 3, 4}`. + +
++ +#### Răspuns: C + +Un modul importat este _doar pentru citire_: nu puteți modifica modulul importat. Doar modulul care le exportă poate schimba valorile acestora. + +Când încercăm să incrementăm valoarea lui `myCounter`, apare o eroare: `myCounter` este doar pentru citire și nu poate fi modificat. + +
++ +#### Răspuns: A + +Operatorul `delete` returnează o valoare booleană: `true` în cazul ștergerii reușite, în caz contrar va returna `false`. Cu toate acestea, variabilele declarate cu cuvintele cheie `var`, `const` sau `let` nu pot fi șterse folosind operatorul `delete`. + +Variabila `name` a fost declarată cu cuvântul cheie `const` așa că ștergerea sa nu reușește: se returnează `false`. Atunci când setăm `age` egal cu `21`, de fapt am adăugat o proprietate numită `age` la obiectul global. În acest fel, puteți șterge cu succes proprietăți din obiecte, inclusiv din obiectul global, așa că `delete age` returnează `true`. + +
+
+
+#### Răspuns: C
+
+Putem dezasambla (unpack) valori din array-uri sau proprietăți din obiecte prin destructurare. De exemplu:
+
+```javascript
+[a, b] = [1, 2];
+```
+
+
+
+Valoarea lui `a` este acum `1`, iar valoarea lui `b` este acum `2`. Ceea ce am făcut în întrebare este:
+
+```javascript
+[y] = [1, 2, 3, 4, 5];
+```
+
+
+
+Acest lucru înseamnă că valoarea lui `y` este egală cu prima valoare din array, care este numărul `1`. Când înregistrăm în consolă `y`, se returnează `1`.
+
+
+ +#### Răspuns: B + +Este posibil să combinăm obiecte folosind operatorul de răspândire`...`. Acesta vă permite să creați copii ale perechilor cheie/valoare dintr-un obiect și să le adăugați la alt obiect. În acest caz, creăm copii ale obiectului `user` și le adăugăm la obiectul `admin`. Obiectul `admin` conține acum perechile cheie/valoare copiate, ceea ce duce la rezultatul `{ admin: true, name: "Lydia", age: 21 }`. + +
++ +#### Răspuns: B + +Cu metoda `defineProperty` putem adăuga noi proprietăți la un obiect sau să modificăm cele existente. Atunci când adăugăm o proprietate la un obiect folosind metoda `defineProperty` aceasta nu este, în mod implicit, _nu enumerabilă_. Metoda `Object.keys` returnează toate numele de proprietăți _enumerabile_ dintr-un obiect, în acest caz doar `"name"`. + +Proprietățile adăugate folosind metoda `defineProperty` sunt, în mod implicit, imutabile (nu pot fi schimbate). Puteți anula acest comportament folosind proprietățile `writable`, `configurable` și `enumerable` În acest fel, metoda `defineProperty` vă oferă un control mai mare asupra proprietăților pe care le adăugați la un obiect. + +
++ +#### Răspuns: A + +Al doilea argument al funcției `JSON.stringify` este _replacer-ul_. Replacer-ul poate fi fie o funcție, fie un array, și vă permite să controlați ce și cum ar trebui să fie serializate (convertite în șir de caractere) valorile. + +Dacă replacer-ul este un _array_, în șirul JSON vor fi incluse doar numele de proprietăți care sunt prezente în array. În acest caz, doar proprietățile cu numele `"level"` și `"health"` sunt incluse, în timp ce `"username"` este exclus. Astfel, `data` devine egal cu `"{"level":19, "health":90}"`. + +Dacă replacer-ul este o _funcție_, această funcție este apelată pentru fiecare proprietate din obiectul pe care îl serializați. Valoarea returnată de această funcție va fi valoarea proprietății atunci când este adăugată în șirul JSON. Dacă valoarea este `undefined`, această proprietate este exclusă din șirul JSON. + +
++ +#### Răspuns: A + +Operatorul unary `++` _returnează mai întâi_ valoarea operandului și _apoi incrementează_ valoarea operandului. Valoarea lui `num1` este `10`, deoarece funcția `increaseNumber` returnează mai întâi valoarea lui `num`, care este `10`, și numai apoi incrementează valoarea lui `num`. + +`num2` este `10`, deoarece am transmis `num1` către funcția `increasePassedNumber`. `number` ieste egal cu `10`(valoarea lui `num1`). Iarăși, operatorul unary `++` _returnează mai întâi_ valoarea operandului și _apoi incrementeazăs_ valoarea operandului. Valoarea lui `number` este `10`, așa că `num2` este egal cu `10`. + +
++ +#### Răspuns: C + +În ES6, putem inițializa parametri cu o valoare implicită. Valoarea parametrului va fi valoarea implicită, dacă nu a fost furnizată nicio altă valoare funcției sau dacă valoarea parametrului este `"undefined"`. În acest caz, răspândim proprietățile obiectului `value` într-un obiect nou, astfel încât `x` are valoarea implicită `{ number: 10 }`. + +Argumentul implicit este evaluat la _momentul apelului_! De fiecare dată când apelăm funcția, se creează un obiect _nou_. Invocăm funcția `multiply` primele două ori fără a furniza o valoare: `x` are valoarea implicită `{ number: 10 }`. Apoi înregistrăm în consolă valoarea înmulțită a acelui număr, care este `20`. + +A treia oară când apelăm `multiply`, furnizăm un argument: obiectul numit `value`. Operatorul `*=` este, de fapt, o prescurtare pentru `x.number = x.number * 2`: modificăm valoarea lui`x.number`, și înregistrăm în consolă valoarea înmulțită, care este `20`. + +A patra oară, trecem din nou obiectul `value`. `x.number` a fost modificat anterior la `20`, deci `x.number *= 2` înregistrează `40`. + +
++ +#### Răspuns: D + +Primul argument pe care îl primește metoda `reduce` este _acumulator-ul_, `x` în acest caz. Al doilea argument este _valoarea curentă_, `y`. Cu metoda `reduce`, executăm o funcție de apel pe fiecare element din array, ceea ce poate duce în cele din urmă la o singură valoare. + +În acest exemplu, nu returnăm nicio valoare, ci doar înregistrăm valorile accumulatorului și valorii curente. + +Valoarea accumulatorului este egală cu valoarea returnată anterior de funcția de apel. Dacă nu furnizați argumentul opțional `initialValue` metodei `reduce`, accumulatorul este egal cu primul element la prima apelare. + +La prima apelare, accumulatorul (`x`) este `1`, iar valoarea curentă (`y`) este `2`. Nu returnăm din funcția de apel, ci înregistrăm valorile accumulatorului și valoarea curentă: se înregistrează `1` și `2`. + +Dacă nu returnați o valoare dintr-o funcție, aceasta va returna `undefined`. OLa următoarea apelare, accumulatorul este `undefined`, iar valoarea curentă este `3`. Se înregistrează `undefined` și `3`. + +La a patra apelare, din nou nu returnăm din funcția de apel. Accumulatorul este din nou `undefined`, iar valoarea curentă este `4`. Se înregistrează `undefined` și `4`. + +
++ +#### Răspuns: B + +Într-o clasă derivată, nu puteți accesa cuvântul cheie `this` înainte de a apela `super`. Dacă încercați să faceți acest lucru, va arunca o ReferenceError: 1 și 4 ar arunca o eroare de referință. + +Cu cuvântul cheie `super`, apelăm constructorul clasei părinte cu argumentele date. Constructorul părintelui primește argumentul `name`, deci trebuie să transmitem `name` la `super`. + +Clasa `Labrador` primește doi argumente, `name` deoarece extinde clasa `Dog`, și `size` ca o proprietate suplimentară în clasa `Labrador`. Ambele trebuie să fie transmise funcției constructor din clasa `Labrador`, ceea ce se face corect utilizând constructorul 2. + +
++ +#### Răspuns: B + +Cu cuvântul cheie `import`, toate modulele importate sunt _preparate în prealabil_. Acest lucru înseamnă că modulele importate sunt executate _mai întâi_, codul din fișierul care importă modulul este executat _după accea_. + +Acesta este un diferență între `require()` în CommonJS și `import`! Cu `require()`, puteți încărca dependențele la cerere în timp ce codul este în curs de desfășurare. Dacă am fi folosit `require` în loc de `import`, ar fi fost înregistrate în consolă mesajele `running index.js`, `running sum.js`, `3`. + +
++ +#### Răspuns: A + +Fiecare Symbol este complet unic. Scopul argumentului furnizat către Symbol este de a oferi Symbolului o descriere. Valoarea Symbolului nu depinde de argumentul furnizat. În timp ce testăm egalitatea, creăm două simboluri complet noi: primul `Symbol('foo')`, și al doilea `Symbol('foo')`. Aceste două valori sunt unice și nu sunt egale între ele, `Symbol('foo') === Symbol('foo')` returnează `false`. + +
++ +#### Răspuns: C + +Cu metoda `padStart` putem adăuga umplutură la începutul unui șir. Valoarea transmisă acestei metode este lungimea _totală_ a șirului împreună cu umplutura. Șirul `"Lydia Hallie"` are o lungime de `12`. `name.padStart(13)` introduce 1 spațiu la începutul șirului, deoarece 12 + 1 este 13. + +Dacă argumentul transmis metodei `padStart` este mai mic decât lungimea șirului, nu va fi adăugată nicio umplutură. + +
++ +#### Răspuns: A + +Cu operatorul `+`, puteți concatena șiruri. În acest caz, concatenăm șirul `"🥑"` cu șirul `"💻"`, rezultând `"🥑💻"`. + +
++ +#### Răspuns: C + +O funcție generator "pauzează" execuția când întâlnește cuvântul cheie `yield`. Mai întâi, trebuie să permitem funcției să emită șirul "Do you love JavaScript?", ceea ce poate fi făcut apelând `game.next().value`. + +Fiecare linie este executată până când găsește primul cuvânt cheie `yield`. Există un cuvânt cheie `yield` pe prima linie din funcție: execuția se oprește cu primul `yield`. _Acest lucru înseamnă că variabila `answer` nu este definită încă!_ + +Când apelăm `game.next("Yes").value`, cuvântul cheie `yield` anterior este înlocuit cu valoarea parametrilor transmiși funcției `next()`, `"Yes"` în acest caz. Valoarea variabilei `answer` este acum egală cu `"Yes"`. Condiția declarației if returnează `false`, și `JavaScript loves you back ❤️` este înregistrat în consolă. + +
++ +#### Răspuns: C + +`String.raw` returnează un șir în care escape-urile (`\n`, `\v`, `\t` etc.) sunt ignorate! Backslash-urile pot fi o problemă, deoarece puteți ajunge cu ceva similar cu: + +`` const path = `C:\Documents\Projects\table.html` `` + +Acest lucru ar rezulta în: + +`"C:DocumentsProjects able.html"` + +Cu `String.raw`, acesta ar ignora pur și simplu escape-ul și ar afișa: + +`C:\Documents\Projects\table.html` + +În acest caz, șirul este `Hello\nworld`, care este înregistrat în consolă. + +
++ +#### Răspuns: C + +O funcție `async` întotdeauna returnează o promisiune. Instrucțiunea `await` încă trebuie să aștepte ca promisiunea să se rezolve: o promisiune în așteptare este returnată atunci când apelăm `getData()` pentru a o atribui variabilei `data`. + +Dacă dorim să avem acces la valoarea rezolvată `"I made it"`, am putea folosi metoda `.then()` pe `data`: + +`data.then(res => console.log(res))` + +Acest lucru ar fi înregistrat `"I made it!"` + +
++ +#### Răspuns: B + +Metoda`.push()` returnează _lungimea_ noului șir! Înainte, șirul conținea un element (șirul `"banana"`) și avea o lungime de `1`. După adăugarea șirului `"apple"` în șir, șirul conține două elemente și are o lungime de `2`. Aceasta este valoarea returnată de funcția `addToList`. + +Metoda `push` modifică șirul original. Dacă doreați să returnați _șirul_ din funcție în loc de _lungimea șirului_, ar fi trebuit să returnați `list` după ce ați adăugat `item` la el. + +
++ +#### Răspuns: B + +`Object.freeze` face imposibilă adăugarea, eliminarea sau modificarea proprietăților unui obiect (cu excepția cazului în care valoarea proprietății este un alt obiect). + +Când creăm variabila `shape` și o setăm egală cu obiectul înghețat `box`, `shape` de asemenea se referă la un obiect înghețat. Puteți verifica dacă un obiect este înghețat folosind `Object.isFrozen`. În acest caz, `Object.isFrozen(shape)` ar returna true, deoarece variabila `shape` are o referință către un obiect înghețat. + +Deoarece `shape` este înghețat și deoarece valoarea lui`x` nu este un obiect, nu putem modifica proprietatea `x`. `x` rămâne egal cu `10`, și `{ x: 10, y: 20 }` este afișat în consolă. + +
++ +#### Răspuns: D + +Folosind [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) cu sintaxa de mai jos putem extrage valori din array-uri sau proprietăți din obiecte în variabile distincte: + +```javascript +const { firstName } = { firstName: 'Lydia' }; +// ES5 version: +// var firstName = { firstName: 'Lydia' }.firstName; + +console.log(firstName); // "Lydia" +``` + +De asemenea, o proprietate poate fi extras dintr-un obiect și atribuită unei variabile cu un nume diferit decât proprietatea obiectului: + +```javascript +const { firstName: myName } = { firstName: 'Lydia' }; +// ES5 version: +// var myName = { firstName: 'Lydia' }.firstName; + +console.log(myName); // "Lydia" +console.log(firstName); // Uncaught ReferenceError: firstName is not defined +``` + +Prin urmare, `firstName` nu există ca variabilă, astfel încât încercarea de a accesa valoarea sa va genera o eroare `ReferenceError`. + +**Notă:** Fiți conștienți de proprietățile în `global scope` (spațiul global): + +```javascript +const { name: myName } = { name: 'Lydia' }; + +console.log(myName); // "lydia" +console.log(name); // "" ----- Browser e.g. Chrome +console.log(name); // ReferenceError: name is not defined ----- NodeJS + +``` + +În cazul în care JavaScript nu poate găsi o variabilă în _cadrul curent_, acesta urcă pe [Scope chain](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch3.md) și o caută. Dacă ajunge la nivelul superior al cadrului, adică la **spațiul global**, și tot nu o găsește, va arunca o excepție `ReferenceError`. + +- În **Browser-e** cum ar fi _Chrome_, `name` este o _proprietate de spațiu global depășită_. În acest exemplu, codul rulează în _spațiul global_ și nu există o variabilă locală definită de utilizator pentru `name`, așa că caută _variabilele/proprietățile_ predefinite în spațiul global, care în cazul browser-elor înseamnă că caută în obiectul `window` de unde extrage valoarea [window.name](https://developer.mozilla.org/en-US/docs/Web/API/Window/name) care este egală cu un **șir gol**. + +- În **NodeJS**, nu există o astfel de proprietate pe obiectul `global` așadar încercarea de a accesa o variabilă inexistentă va genera o [ReferenceError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined). + +
++ +#### Răspuns: A + +O funcție pură este o funcție care _întotdeauna_ returnează același rezultat, dacă aceleași argumente sunt furnizate. + +Funcția `sum` întotdeauna returnează același rezultat. Dacă îi furnizăm `1` și `2`, va returna _întotdeauna_ `3` fără efecte secundare. Dacă îi furnizăm `5` și `10`, va returna _întotdeauna_ `15`, și tot așa. Aceasta este definiția unei funcții pure. + +
++ +#### Răspuns: C + +Funcția `add` este o funcție _memoizată_. Cu ajutorul memoizării, putem să memorăm rezultatele unei funcții pentru a accelera execuția ulterioară. În acest caz, creăm un obiect `cache` care stochează valorile returnate anterior. + +Dacă apelăm din nou funcția `addFunction` cu același argument, funcția verifică mai întâi dacă a primit deja acea valoare în memoria sa cache. Dacă acest lucru este adevărat, se va returna valoarea din cache, economisind timp de execuție. Dacă nu este în cache, funcția va calcula valoarea și o va memora ulterior. + +Apelăm funcția `addFunction` de trei ori cu aceeași valoare: în prima invocare, valoarea funcției când `num` este egal cu `10` nu este încă în cache. Condiția instrucțiunii `num in cache` returnează `false`, iar blocul `else` este executat: se afișează `Calculated! 20` iar valoarea rezultatului este adăugată în obiectul de cache. Acum, `cache` arată astfel `{ 10: 20 }`. + +A doua oară, obiectul `cache` conține valoarea care este returnată pentru `10`. Condiția instrucțiunii `num in cache` returnează `true`, și se afișează `'From cache! 20'`. + +A treia oară, trecem `5 * 2` funcției, care este evaluat la `10`. Obiectul `cache` conține valoarea care este returnată pentru `10`. Condiția instrucțiunii `num in cache` returnează `true`, și se afișează `'From cache! 20'`. + +
++ +#### Răspuns: A + +Cu o buclă _for-in_, putem itera peste proprietățile **enumerabile**. Într-un șir, proprietățile enumerate sunt "cheile" elementelor din șir, care sunt de fapt indexurile lor. Puteți vedea un șir ca: + +`{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}` + +Unde cheile sunt proprietățile enumerate. `0` `1` `2` `3` sunt afișate. + +Cu o buclă _for-of_, putem itera peste obiecte **iterabile**. Un șir este un obiect iterabil. Când iterăm peste șir, variabila "item" este egală cu elementul pe care îl parcurge în acel moment, sunt afișate `"☕"` `"💻"` `"🍷"` `"🍫"`. + +
++ +#### Răspuns: C + +Elementele dintr-un șir pot stoca orice valoare. Numere, șiruri, obiecte, alte șiruri, null, valori booleane, undefined și alte expresii precum date, funcții și calculații. + +Elementul va fi egal cu valoarea returnată. `1 + 2` returnează `3`, `1 * 2` returnează `2`, și `1 / 2` returnează `0.5`. + +
++ +#### Răspuns: B + +În mod implicit, argumentele au valoarea `undefined`, cu excepția cazului în care s-a transmis o valoare funcției. În acest caz, nu am transmis o valoare pentru argumentul `name`. `name` este egal cu `undefined` iar acesta este afișat. + +În ES6, putem suprascrie această valoare implicită `undefined` cu parametri impliciti. De exemplu: + +`function sayHi(name = "Lydia") { ... }` + +În acest caz, dacă nu am fi furnizat o valoare sau am fi furnizat `undefined`, `name` ar fi fost întotdeauna egal cu șirul `Lydia`. + +
++ +#### Răspuns: B + +Valoarea cuvântului cheie `this` depinde de locul în care este utilizat. Într-o **metodă**, cum ar fi metoda `getStatus`, cuvântul cheie `this` se referă la _obiectul la care aparține metoda_. Metoda aparține obiectului `data`, deci `this` se referă la obiectul `data`. Când înregistrăm `this.status`, se înregistrează proprietatea `status` de pe obiectul `data` care este `"🥑"`. + +Cu metoda `call` putem schimba obiectul la care se referă cuvântul cheie `this`. În **funcții**, cuvântul cheie `this` se referă la _obiectul la care aparține funcția_. Am declarat funcția `setTimeout` pe _obiectul global_, deci în interiorul funcției `setTimeout`, cuvântul cheie `this` se referă la _obiectul global_. Pe obiectul global există o variabilă numită status cu valoarea `"😎"`. Când înregistrați `this.status`, se înregistrează `"😎"`. + +
++ +#### Răspuns: A + +Am setat variabila `city` egală cu valoarea proprietății numită `city` pe obiectul `person`. Nu există o proprietate pe acest obiect numită `city`, astfel că variabila `city` are valoarea `undefined`. + +Rețineți că nu facem referire la obiectul `person` în sine! Pur și simplu am setat variabila `city` egală cu valoarea curentă a proprietății `city` de pe obiectul `person`. + +Apoi, am setat `city` egal cu șirul de caractere `"Amsterdam"`. Acest lucru nu schimbă obiectul `person` nu există o referință la acel obiect. + +Atunci când se afișează obiectul `person` se va afișa obiectul original, nealterat. + +
++ +#### Răspuns: C + +Variabilele declarate cu cuvintele cheie `const` și `let` au _domeniu de vizibilitate la nivel de bloc_. Un bloc poate fi definit între parantezele acolade (`{ }`). În acest caz, parantezele acolade ale instrucțiunilor if/else. Nu puteți face referire la o variabilă în afara blocului în care a fost declarată, va fi generată o eroare de tip ReferenceError. + +
++ +#### Răspuns: C + +Valoarea lui `res` în al doilea `.then` este egală cu valoarea returnată de `.then` anterior. Puteți continua să înșirați `.then`-uri în acest fel, unde valoarea este pasată către următorul manipulator. + +
++ +#### Răspuns: A + +Cu `!!name`, determinăm dacă valoarea lu `name` este adevărată sau falsă. Dacă `name` este adevărat, ceea ce dorim să testăm, `!name` returnează `false`. `!false` (practic, ceea ce este `!!name`) returnează `true`. + +Prin setarea lui `hasName` egal cu `name`, se face ca `hasName` să fie egal cu valoarea pe care ați furnizat-o funcției `getName`, nu cu valoarea booleană `true`. + +`new Boolean(true)` returnează un obiect încapsulator, nu valoarea booleană în sine. + +`name.length` returnează lungimea argumentului furnizat, nu dacă acesta este `true`. + +
++ +#### Răspuns: B + +Pentru a obține un caracter la un anumit index dintr-un șir de caractere, puteți utiliza notația cu paranteze pătrate. Primul caracter din șir are indexul 0, și așa mai departe. În acest caz, dorim să obținem elementul cu indexul 0, adică caracterul `"I'`, care va fi afișat în jurnal. + +Rețineți că această metodă nu este suportată în IE7 și versiunile anterioare. În acest caz, utilizați `.charAt()`. + +
++ +#### Răspuns: B + +Puteți seta valoarea implicită a unui parametru la valoarea altui parametru al funcției, atâta timp cât acestea sunt definite _înainte_ de parametrul cu valoarea implicită. Am transmis valoarea `10` funcției `sum`. Dacă funcția `sum` primește doar un argument, înseamnă că valoarea pentru `num2` nu este transmisă, iar valoarea lui `num1` este egală cu valoarea transmisă `10` în acest caz. Valoarea implicită a lui `num2` este valoarea lui `num1`, care este `10`. `num1 + num2` returnează `20`. + +Dacă încercați să setați valoarea implicită a unui parametru egală cu un parametru care este definit _după_ (în dreapta), valoarea parametrului nu a fost încă inițializată, ceea ce va genera o eroare. + +
++ +#### Răspuns: A + +Cu sintaxa `import * as name`, importăm _toate exporturile_ din fișierul `module.js` în fișierul `index.js` sub forma unui nou obiect numit `data`. În fișierul `module.js` există două exporturi: exportul implicit și un export cu nume. Exportul implicit este o funcție care returnează șirul de caractere `"Hello World"`, iar exportul cu nume este o variabilă numită `name` care are valoarea șirului de caractere `"Lydia"`. + +Obiectul `data` are o proprietate `default` pentru exportul implicit, iar celelalte proprietăți au numele exporturilor cu nume și valorile lor corespunzătoare. + +
++ +#### Răspuns: C + +Clasele sunt o sintaxă mai simplă pentru constructorii de funcții. Echivalentul clasei `Person` sub forma unui constructor de funcții ar fi: + +```javascript +function Person(name) { + this.name = name; +} +``` + +Apelarea unui constructor de funcții cu `new` duce la crearea unei instanțe a obiectului `Person`, iar cuvântul cheie `typeof` returnează `"object"` pentru o astfel de instanță. `typeof member` returnează `"object"`. + +
++ +#### Răspuns: D + +Metoda `.push` returnează _lungimea nouă_ a array-ului, nu array-ul însuși! Prin setarea `newList` egal cu `[1, 2, 3].push(4)`, am setat `newList` egal cu noua lungime a array-ului: `4`. + +Apoi, încercăm să folosim metoda `.push` pe `newList`. Deoarece `newList` este o valoare numerică `4`, nu putem folosi metoda `.push` se va genera o eroare de tip TypeError. + +
++ +#### Răspuns: D + +Funcțiile obișnuite, cum ar fi funcția `giveLydiaPizza` au o proprietate `prototype` care este un obiect (obiectul prototip) cu o proprietate `constructor`. Cu toate acestea, funcțiile arrow, cum ar fi funcția `giveLydiaChocolate`, nu au această proprietate `prototype`. `undefined` este returnat atunci când încearca să acceseze proprietatea `prototype` folosind `giveLydiaChocolate.prototype`. + +
++ +#### Răspuns: A + +`Object.entries(person)` returnează un array de array-uri imbricate, care conțin cheile și obiectele: + +`[ [ 'name', 'Lydia' ], [ 'age', 21 ] ]` + +Folosind bucla `for-of` putem itera prin fiecare element din array, în acest caz, subarray-urile. Putem dezasambla subarray-urile instantaneu în bucla `for-of`, folosind `const [x, y]`. Astfel, `x` este egal cu primul element din subarray, iar `y` este egal cu al doilea element din subarray. + +Primul subarray este `[ "name", "Lydia" ]`, cu `x` egal cu `"name"`, și `y` egal cu `"Lydia"`, care sunt afișate în jurnal. +Al doilea subarray este `[ "age", 21 ]`, cu `x` egal cu `"age"`, și `y` egal cu `21`, care sunt afișate în jurnal. + +
++ +#### Răspuns: D + +`...args` este un parametru rest. Valoarea parametrului rest este un array care conține toate argumentele rămase și **poate fi doar ultimul parametru**! În acest exemplu, parametrul rest era al doilea parametru. Acest lucru nu este posibil și va genera o eroare de sintaxă. + +```javascript +function getItems(fruitList, favoriteFruit, ...args) { + return [...fruitList, ...args, favoriteFruit]; +} + +getItems(['banana', 'apple'], 'pear', 'orange'); +``` + +Exemplul de mai sus funcționează. Acesta returnează array-ul `[ 'banana', 'apple', 'orange', 'pear' ]` + +
++ +#### Răspuns: B + +În JavaScript, nu _trebuie_ să scriem explicit semnul punct și virgulă (`;`) totuși motorul JavaScript le adaugă automat după instrucțiuni. Acest lucru se numește **Inserția Automată a Semnelor de Punct și Virgulă**. O instrucțiune poate fi, de exemplu, variabile sau cuvinte cheie precum `throw`, `return`, `break`, etc. + +Aici, am scris o instrucțiune `return` și o altă valoare `a + b` pe o _linie nouă_. Cu toate acestea, deoarece este o linie nouă, motorul JavaScript nu știe că este de fapt valoarea pe care am dorit să o returnăm. În schimb, a adăugat automat un punct și virgulă după `return`. Puteți vedea acest lucru ca: + +```javascript +return; +a + b; +``` + +Acest lucru înseamnă că `a + b` nu este niciodată atins, deoarece o funcție se oprește din executare după cuvântul cheie `return`. Dacă nu se returnează nicio valoare, așa cum se întâmplă aici, funcția returnează `undefined`. Rețineți că nu există inserție automată a semnelor de punct și virgulă după instrucțiunile `if/else`! + +
++ +#### Răspuns: B + +Putem seta clasele egale cu alte clase sau constructori de funcții. În acest caz, am setat `Person` egal cu `AnotherPerson`. Numele în acest constructor este `Sarah`, astfel încât proprietatea `Person` de pe noua instanță `member` este `"Sarah"`. + +
++ +#### Răspuns: D + +Un simbol nu este _enumerabil_. Metoda `Object.keys` returnează toate proprietățile cheie _enumerabil_ ale unui obiect. Simbolul nu va fi vizibil, și va fi returnat un array gol. Atunci când se afișează întregul obiect, vor fi vizibile toate proprietățile, inclusiv cele care nu sunt enumerate. + +Asta este una dintre multele calități ale unui simbol: pe lângă faptul că reprezintă o valoare complet unică (ceea ce previne coliziunile accidentale de nume pe obiecte, de exemplu, atunci când lucrați cu două biblioteci care doresc să adauge proprietăți la același obiect), puteți "ascunde" proprietăți pe obiecte în acest fel (deși nu în întregime. Încă puteți accesa simbolurile folosind metoda `Object.getOwnPropertySymbols()`). + +
++ +#### Răspuns: A + +Funcția `getList` primește un array ca argument. Între parantezele funcției `getList` dezasamblăm acest array imediat. Puteți vedea acest lucru ca: + +`[x, ...y] = [1, 2, 3, 4]` + +Cu ajutorul parametrului rest `...y`, punem toți "parametrii rămași" într-un array. Parametrii rămași în acest caz sunt `2`, `3` și `4`. Valoarea lui `y` este un array care conține toți parametrii rămași. Valoarea lui `x` este egal cu `1` în acest caz, deci când afișăm `[x, y]`, va fi afișat `[1, [2, 3, 4]]`. + +Funcția `getUser` primește un obiect ca argument. Cu funcțiile arrow, nu _trebuie_ să scriem acolade dacă dorim să returnăm doar o valoare. Cu toate acestea, dacă doriți să returnați instantaneu un _obiect_ dintr-o funcție arrow, trebuie să-l scrieți între paranteze. Altfel, tot ce este între acolade va fi interpretat ca o instrucțiune bloc. În acest caz, codul dintre acolade nu este un cod JavaScript valid, așa că se va genera o eroare de sintaxă `SyntaxError`. + +Funcția următoare ar fi returnat un obiect: + +`const getUser = user => ({ name: user.name, age: user.age })` + +
++ +#### Răspuns: C + +Variabila `name` conține o valoare de tip șir de caractere (string), care nu este o funcție și, prin urmare, nu poate fi invocată. + +TypeError-urile sunt generate atunci când o valoare nu este de tipul așteptat. JavaScript e aștepta ca `name` să fie o funcție, deoarece încercăm să o apelăm. Cu toate acestea, era de tip șir de caractere (string), așa că a generat o eroare de tip TypeError: name nu este o funcție! + +SyntaxError-urile sunt generate atunci când ați scris ceva care nu este JavaScript valid, de exemplu, atunci când ați scris cuvântul `return` ca `retrun`. +ReferenceError-urile sunt generate atunci când JavaScript nu poate găsi o referință la o valoare la care încercați să accesați. + +
++ +#### Răspuns: B + +`[]` este o valoare adevărată (truthy). Cu operatorul `&&` valoarea din partea dreaptă va fi returnată dacă valoarea din partea stângă este adevărată. În acest caz, valoarea din partea stângă, `[]` este adevărată, astfel că se va returna `"Im'`. + +`""` este o valoare falsă (falsy). Dacă valoarea din partea stângă este falsă, nu se returnează nimic. `n't` nu va fi returnat. + +
++ +#### Răspuns: C + +Cu operatorul `||` utem returna primul operand adevărat (truthy). Dacă toate valorile sunt false, se va returna ultimul operand. + +`(false || {} || null)`: obiectul go `{}` este o valoare adevărată (truthy). Aceasta este prima (și singura) valoare adevărată, care este returnată. `one` este egal cu `{}`. + +`(null || false || "")`: toate operanzii sunt valori false. Acest lucru înseamnă că ultimul operand `""` este returnat. `two` este egal cu `""`. + +`([] || 0 || "")`: array-ul gol `[]` este o valoare adevărată (truthy). Aceasta este prima valoare adevărată, care este returnată. `three` este egal cu `[]`. + +
++ +#### Răspuns: D + +Cu o promisiune, spunem în principiu _Vreau să execut această funcție, dar o pun deoparte pentru moment în timp ce rulează, deoarece acest lucru poate dura ceva timp. Doar atunci când o anumită valoare este rezolvată (sau respinsă), și atunci când stiva de apeluri este goală, doresc să folosesc această valoare._ + +Putem obține această valoare atât cu `.then` cât și cu cuvântul cheie `await` într-o funcție `async`. Cu toate că putem obține valoarea unei promisiuni cu ambele metode `.then` și `await`, ele funcționează puțin diferit. + +În `firstFunction`, am pus (într-un fel) funcția `myPromise` deoparte în timp ce aceasta se executa, dar am continuat să executăm restul codului, care este `console.log('second')` în acest caz. Apoi, funcția a fost rezolvată cu șirul `I have resolved`, care a fost apoi înregistrat în jurnal după ce s-a constatat că stiva de apeluri era goală. + +Cu cuvântul cheie `await` în `secondFunction`, efectiv pauzăm execuția unei funcții asincrone până când valoarea a fost rezolvată înainte de a trece la următoarea linie. + +Acest lucru înseamnă că a așteptat ca `myPromise` să fie rezolvat cu valoarea `I have resolved`, și doar după ce s-a întâmplat acest lucru, s-a trecut la următoarea linie: a fost înregistrat `second`. + +
++ +#### Răspuns: C + +Operatorul `+` nu este folosit doar pentru adunarea valorilor numerice, ci îl putem utiliza și pentru concatenarea șirurilor de caractere. Ori de câte ori motorul JavaScript observă că una sau mai multe valori nu sunt de tip număr, va converti numărul într-un șir de caractere. + +Primul operand este `1`, care este o valoare numerică. `1 + 2` returnează numărul 3. + +Cu toate acestea, al doilea operand este un șir de caractere `"Lydia"`. `"Lydia"` este un șir de caractere și `2` este un număr: `2` este convertit într-un șir de caractere. `"Lydia"` și `"2"` sunt concatenate, rezultând șirul de caractere `"Lydia2"`. + +`{ name: "Lydia" }` este un obiect. Niciun număr, niciun obiect nu este un șir de caractere, astfel că sunt convertite în șiruri. Ori de câte ori convertim un obiect regulat în șir de caractere, devine `"[object Object]"`. `"[object Object]"` concatenat cu `"2"` devine `"[object Object]2"`. + +
+
+
+#### Răspuns: C
+
+Putem pasa orice tip de valoare dorim către `Promise.resolve`, fie o promisiune, fie o valoare non-promisiune. Metoda în sine returnează o promisiune cu valoarea rezolvată (`
+ +#### Răspuns: B + +Obiectele sunt pasate prin referință. Atunci când verificăm obiecte pentru egalitate strictă (`===`), comparăm referințele lor. + +Am setat valoarea implicită pentru `person2` egală cu obiectul `person` și am pasat obiectul `person` ca valoare pentru `person1`. + +Acest lucru înseamnă că ambele valori au o referință către aceeași locație în memorie, astfel că sunt egale. + +Blocul de cod din instrucțiunea `else` se execută, și este înregistrat mesajul`They are the same!`. + +
++ +#### Răspuns: D + +În JavaScript, avem două moduri de a accesa proprietăți pe un obiect: notare cu paranteze pătrate sau notare cu punct. În acest exemplu, folosim notarea cu punct (`colorConfig.colors`) în loc de notarea cu paranteze pătrate (`colorConfig["colors"]`). + +Cu notarea cu punct, JavaScript încearcă să găsească proprietatea pe obiect cu exact același nume. În acest exemplu, JavaScript încearcă să găsească o proprietate numită `colors` pe obiectul `colorConfig`. Nu există o proprietate numită `colors`, așa că acest lucru returnează `undefined`. Apoi, încercăm să accesăm valoarea primului element folosind `[1]`. Nu putem face acest lucru pe o valoare care este `undefined`, astfel că se generează o eroare de tip `TypeError`: `Cannot read property '1' of undefined`. + +JavaScript interpretează (sau deschide) declarațiile. Atunci când folosim notația cu paranteze pătrate, vede prima paranteză deschisă `[` și continuă până găsește paranteza de închidere `]`. Abia atunci va evalua declarația. Dacă am fi folosit `colorConfig[colors[1]]`, ar fi returnat valoarea proprietății `red` pe obiectul `colorConfig`. + +
++ +#### Răspuns: A + +În culise, emoji-urile sunt reprezentate ca coduri Unicode. Codurile Unicode pentru emoji-ul inimii sunt `"U+2764 U+FE0F"`. Acestea sunt întotdeauna aceleași pentru aceleași emoji-uri, așa că comparăm două șiruri identice între ele, ceea ce returnează + +
++ +#### Răspuns: D + +Cu metoda `splice` mmodificăm array-ul original prin ștergerea, înlocuirea sau adăugarea de elemente. În acest caz, am eliminat 2 elemente de la indexul 1 (am eliminat `'🥑'` și `'😍'`) și am adăugat emoji-ul ✨ în locul lor. + +`map`, `filter` și `slice` returnează un nou array, `find` returnează un element, ia `reduce` returnează o valoare redusă. + +
++ +#### Răspuns: A + +Am setat valoarea proprietății `favoriteFood` pe obiectul `info` egal cu șirul de caractere cu emoji-ul de pizza, `'🍕'`. Un șir de caractere este un tip de date primitiv. În JavaScript, tipurile de date primitive nu interacționează prin referință. + +În JavaScript, tipurile de date primitive (tot ceea ce nu este obiect) interacționează prin _valoare_. În acest caz, am setat valoarea proprietății `favoriteFood` pe obiectul `info` egală cu valoarea primului element din array-ul `food` care este un șir de caractere cu emoji-ul de pizza în acest caz (`'🍕'`). Un șir de caractere este un tip de date primitiv și interacționează prin valoare (vedeți [blogpost](https://www.theavocoder.com/complete-javascript/2018/12/21/by-value-vs-by-reference) meu dacă doriți să aflați mai multe). + +Apoi, schimbăm valoarea proprietății `favoriteFood` pe obiectul `info`. Array-ul `food` nu s-a schimbat, deoarece valoarea `favoriteFood` era doar o _copie_ a valorii primului element din array și nu are o referință la aceeași locație în memorie ca elementul din `food[0]`. Când înregistrăm array-ul `food`, acesta rămâne neschimbat, `['🍕', '🍫', '🥑', '🍔']`. + +
++ +#### Răspuns: A + +Cu metoda `JSON.parse()` putem parsa un șir JSON într-o valoare JavaScript. + +```javascript +// Transformarea unui număr într-un JSON valid, apoi parsarea șirului JSON într-o valoare JavaScript: +const jsonNumber = JSON.stringify(4); // '4' +JSON.parse(jsonNumber); // 4 + +// Transformarea unei valori de tip array într-un JSON valid, apoi parsarea șirului JSON într-o valoare JavaScript: +const jsonArray = JSON.stringify([1, 2, 3]); // '[1, 2, 3]' +JSON.parse(jsonArray); // [1, 2, 3] + +// Transformarea unui obiect într-un JSON valid, apoi parsarea șirului JSON într-o valoare JavaScript: +const jsonArray = JSON.stringify({ name: 'Lydia' }); // '{"name":"Lydia"}' +JSON.parse(jsonArray); // { name: 'Lydia' } +``` + +
++ +#### Răspuns: D + +Fiecare funcție are propriul său _context de execuție_ (sau _domeniu_). Funcția `getName` caută mai întâi în propriul său context (domeniu) pentru a vedea dacă conține variabila `name` pe care încercăm să o accesăm. În acest caz, funcția `getName` conține propria sa variabilă `name` declarăm variabila `name` cu cuvântul cheie `let`, și cu valoarea `'Sarah'`. + +Variabilele declarate cu cuvântul cheie `let` (și `const`) sunt hoisted, dar, spre deosebire de `var`, nu sunt inițializate. Ele nu sunt accesibile înainte de linia în care le declarăm (inițializăm). Acest lucru se numește "zona temporală moartă" (temporal dead zone). Atunci când încercăm să accesăm variabilele înainte de a fi declarate, JavaScript aruncă o eroare de tip `ReferenceError`. + +Dacă nu am fi declarat variabila `name` în interiorul funcției `getName` motorul JavaScript ar fi căutat în josul lanțului de _domenii_. Domeniul exterior are o variabilă numită `name` cu valoarea `Lydia`. În acest caz, ar fi afișat `Lydia`. + +```javascript +let name = 'Lydia'; + +function getName() { + console.log(name); +} + +getName(); // Lydia +``` + +
++ +#### Răspuns: C + +Cu cuvântul cheie `yield`, cedăm valorile într-o funcție generator. Cu cuvântul cheie `yield*`, putem ceda valori dintr-o altă funcție generator sau dintr-un obiect iterabil (de exemplu, un array). + +În `generatorOne`, folosim cuvântul cheie `yield` pentru a ceda intrega mulțime `['a', 'b', 'c']`. Valoarea proprietății `value` a obiectului returnat de metoda `next` pe obiectul `one` (`one.next().value`) este egală cu întregul array `['a', 'b', 'c']`. + +```javascript +console.log(one.next().value); // ['a', 'b', 'c'] +console.log(one.next().value); // undefined +``` + +În `generatorTwo`, folosim cuvântul cheie `yield*`. Acest lucru înseamnă că prima valoare cedată din `two`, este egală cu prima valoare cedată din iterator. Iteratorul este mulțimea `['a', 'b', 'c']`. Prima valoare cedată este `a`, așa că prima dată când apelăm `two.next().value`, este returnată valoarea `a`. + +```javascript +console.log(two.next().value); // 'a' +console.log(two.next().value); // 'b' +console.log(two.next().value); // 'c' +console.log(two.next().value); // undefined +``` + +
++ +#### Răspuns: A + +Expresiile din șirurile șablon (template literals) sunt evaluate mai întâi. Acest lucru înseamnă că șirul va conține valoarea returnată de expresie, funcția imediat invocată `(x => x)('I love')` în acest caz. Trecem valoarea `'I love'` ca argument către funcția arrow `x => x`. `x` este egal cu `'I love'`, care este returnată. Aceasta duce la rezultatul `I love to program`. + +
++ +#### Răspuns: C + +În mod normal, atunci când setăm obiecte egal cu `null`, acele obiecte sunt _colectate de gunoi_ (garbage collected), deoarece nu mai există nicio referință către acel obiect. Cu toate acestea, deoarece funcția de callback din `setInterval` este o funcție arrow (și, prin urmare, legată de obiectul `config`), funcția de callback încă menține o referință la obiectul `config`. +Atâta timp cât există o referință, obiectul nu va fi colectat de gunoi (garbage collected). +Deoarece aceasta este o intervală de timp, setarea lui `config` la `null` sau `delete` lui `config.alert` nu va colecta intervalul de gunoi și intervalul va continua să fie apelat. +Pentru a-l opri și a-l elimina din memorie, trebuie să folosiți `clearInterval(config.alert)`. +Deoarece acest lucru nu a fost făcut, funcția de callback a `setInterval` va fi în continuare invocată la fiecare 1000 ms (1 secundă). + +
++ +#### Răspuns: B + +Când adăugăm o pereche cheie/valoare folosind metoda `set`, cheia va fi valoarea primului argument transmis funcției `set`, iar valoarea va fi cea de-a doua valoare transmisă funcție `set`. Cheia în acest caz este _funcția_ `() => 'greeting'`, iar valoarea `'Hello world'`. `myMap` este acum `{ () => 'greeting' => 'Hello world!' }`. + +1 este incorect pentru că cheia nu este `'greeting'` ci `() => 'greeting'`. +3 este incorect pentru că creăm o nouă funcție prin transmiterea ei ca parametru către metoda `get`. Obiectele interacționează prin _referință_. Funcțiile sunt obiecte, motiv pentru care două funcții nu sunt niciodată strict egale, chiar dacă sunt identice: ele au o referință către un loc diferit în memorie. + +
++ +#### Răspuns: C + +Ambele funcții `changeAge` și `changeAgeAndName` au un parametru implicit, și anume un obiect _nou_ creat `{ ...person }`. Acest obiect conține copii ale tuturor cheilor/valorilor din obiectul `person`. + +În primul rând, apelăm funcția `changeAge` și transmitem obiectul `person` ca argument. Această funcție crește valoarea proprietății `age` cu 1. `person` devine `{ name: "Lydia", age: 22 }`. + +Apoi, apelăm funcția `changeAgeAndName`, însă nu transmitem un parametru. În schimb, valoarea lui `x` este egală cu un obiect _nou_: `{ ...person }`. Deoarece este un obiect nou, acesta nu afectează valorile proprietăților din obiectul `person`. `person` rămâne egal cu `{ name: "Lydia", age: 22 }`. + +
++ +#### Răspuns: C + +Cu operatorul spread `...`, putem _răspândi_ obiecte iterabile în elemente individuale. Funcția `sumValues` primește trei argumente: `x`, `y` și `z`. `...[1, 2, 3]` va rezulta în `1, 2, 3`, pe care le transmitem funcției `sumValues`. + +
++ +#### Răspuns: B + +Cu operandul `+=` incrementăm valoarea lui `num` cu `1`. Inițial, `num` avea valoarea `1`, deci `1 + 1` este `2`. Elementul de pe al doilea index în mulțimea `list` este 🥰, `console.log(list[2])` va afișa 🥰. + +
++ +#### Răspuns: B + +Cu operatorul de verificare opțională `?.`, nu mai este necesar să verificăm explicit dacă valorile mai profunde încorporate sunt valide sau nu. Dacă încercăm să accesăm o proprietate pe o valoare `undefined` sau `null` valoarea (_nullish_), expresia face un scurtcircuit și returnează `undefined`. + +`person.pet?.name`: `person` are o proprietate numită `pet`: `person.pet` nu este `nullish`. Are o proprietate numită `name`, și returnează `Mara`. +`person.pet?.family?.name`: `person` are o proprietate numită `pet`: `person.pet` nu este `nullish`. `pet` _nu_ are o proprietate numită `family`, `person.pet.family` este `nullish`. Expresia returnează `undefined`. +`person.getFullName?.()`: `person` are o proprietate `getFullName`: `person.getFullName()` nu este `nullish` și poate fi invocată, care returnează `Lydia Hallie`. +`member.getLastName?.()`: variabila `member` nu există, prin urmare se va genera o excepție de tip `ReferenceError` gets thrown! + +
++ +#### Răspuns: B + +Am trecut condiția `groceries.indexOf("banana")` în instrucțiunea `if`. `groceries.indexOf("banana")` returnează `0`, care este o valoare falsă. Deoarece condiția din instrucțiunea `if` este falsă, se execută codul din blocul `else`, și `We don't have to buy bananas!` se afișează. + +
++ +#### Răspuns: D + +Metoda `language` este un `setter`. Setter-urile nu rețin o valoare reală; scopul lor este să _modifice_ proprietăți. Atunci când apelați o metodă `setter`, aceasta va returna `undefined`. + +
++ +#### Răspuns: C + +`typeof name` returnează `"string"`. Șirul de caractere `"string"` este o valoare adevărată (truthy), așa că `!typeof name` returnează valoarea booleană `false`. `false === "object"` și `false === "string"` ambele returnează `false`. + +(Dacă dorim să verificăm dacă tipul este (ne)egal cu un anumit tip, ar trebui să folosim `!==` în loc de `!typeof`) + +
++ +#### Răspuns: A + +Funcția `add` returnează o funcție arrow, care returnează o altă funcție arrow, care la rândul ei returnează o altă funcție arrow (încă sunteți cu mine?). Prima funcție primește un argument `x` cu valoarea `4`. Apelăm a doua funcție, care primește un argument `y` cu valoarea `5`. Apoi apelăm a treia funcție, care primește un argument `z` cu valoarea `6`. Când încercăm să accesăm valorile `x`, `y` și `z` în ultima funcție arrow, motorul JavaScript urcă lanțul de domenii pentru a găsi valorile pentru `x` și `y` în consecință. Aceasta returnează `4` `5` `6`. + +
++ +#### Răspuns: C + +Funcția generator `range` returnează un obiect asincron cu promisiuni pentru fiecare element din intervalul pe care îl transmitem: `Promise{1}`, `Promise{2}`, `Promise{3}`. Setăm variabila `gen` egală cu obiectul asincron, după care facem o buclă peste el folosind o buclă `for await ... of`. Setăm variabila `item` eegală cu valorile promisiunilor returnate: mai întâi `Promise{1}`, apoi `Promise{2}`, apoi `Promise{3}`. Deoarece _așteptăm_ valoarea lui `item`, adică promisiunea rezolvată, _valorile_ rezolvate ale promisiunilor sunt returnate: `1`, `2`, apoi `3`. + +
++ +#### Răspuns: D + +`myFunc` așteaptă ca argument un obiect cu proprietățile `x`, `y` și `z`. Deoarece transmitem doar trei valori numerice separate (1, 2, 3) în loc de un obiect cu proprietățile `x`, `y` și `z` ({x: 1, y: 2, z: 3}), `x`, `y` și `z` primesc valoarea lor implicită, care este `undefined`. + +
++ +#### Răspuns: B + +Cu metoda `Intl.NumberFormat` putem formata valorile numerice în orice locație. Formatez valoarea numerică `130` pentru locația `en-US` ca o `unitate` în `mile-per-hour`, ceea ce rezultă în `130 mph`. Valoarea numerică `300` pentru locația `en-US` ca `monedă` în `USD` rezultă în `$300.00`. + +
++ +#### Răspuns: B + +Prin destrucțurarea obiectelor, putem extrage valorile din obiectul din partea dreaptă și le atribui valorii cu același nume de proprietate din obiectul din partea stângă. În acest caz, atribuim valoarea "💀" lui `spookyItems[3]`. Acest lucru înseamnă că modificăm array-ul `spookyItems`, adăugăm "💀" la el. La afișarea în consolă a lui `spookyItems`, se va afișa `["👻", "🎃", "🕸", "💀"]`. + +
++ +#### Răspuns: C + +Cu metoda `Number.isNaN` puteți verifica dacă valoarea pe care o transmiteți este o _valoare numerică_ și este egală cu `NaN`. `name` nu este o valoare numerică, așa că `Number.isNaN(name)` returnează `false`. `age` este o valoare numerică, dar nu este egală cu `NaN`, astfel că `Number.isNaN(age)` returnează `false`. + +Cu metoda `isNaN` puteți verifica dacă valoarea pe care o transmiteți nu este un număr. `name` nu este un număr, așa că `isNaN(name)` returnează `true`. `age` este un număr, astfel că `isNaN(age)` returnează `false`. + +
++ +#### Răspuns: D + +Variabilele declarate cu cuvântul cheie `const` nu pot fi referite înainte de inițializare: acest lucru se numește _zona temporală moartă_ (temporal dead zone). În funcția `getInfo`, variabila`randomValue` este de domeniu în domeniul funcțional al funcției `getInfo`. Pe linia în care dorim să afișăm valoarea `typeof randomValue`, variabila `randomValue` nu este încă inițializată: se va genera o eroare de tip `ReferenceError`! Motorul nu a căutat în josul lanțului de domenii deoarece am declarat variabila `randomValue` în funcția `getInfo`. + +
++ +#### Răspuns: C + +În blocul `try` înregistrăm valoarea așteptată a variabilei `myPromise`: `"Woah some cool data"`. Deoarece nu s-au generat erori în blocul `try` codul din blocul `catch` nu se execută. Codul din blocul `finally` se execută _întotdeauna_, și se va afișa `"Oh finally!"`. + +
++ +#### Răspuns: B + +Cu metoda `flat` putem crea un nou array aplatizat. Adâncimea array-ului aplatizat depinde de valoarea pe care o transmitem. În acest caz, am transmis valoarea `1` (care nu era necesară, deoarece aceasta este valoarea implicită), ceea ce înseamnă că vor fi concatenate doar array-urile de pe primul nivel de adâncime. `['🥑']` și `['✨', '✨', ['🍕', '🍕']]`. Concatenarea acestor două array-uri rezultă în `['🥑', '✨', '✨', ['🍕', '🍕']]`. + +
+
+
+#### Răspuns: D
+
+`counterOne` este o instanță a clasei `Counter`. Clasa `Counter` conține o proprietate `count` în constructorul său și o metodă `increment`. Mai întâi, am invocat metoda `increment` de două ori, apelând `counterOne.increment()`. În prezent, `counterOne.count` este `2`.
+
+
+
+Apoi, creăm o nouă variabilă `counterTwo`, și o setăm egală cu `counterOne`. Deoarece obiectele interacționează prin referință, creăm doar o nouă referință către același loc în memorie la care indică `counterOne`. Deoarece au același loc în memorie, orice modificări făcute asupra obiectului la care `counterTwo` are o referință se aplică și la `counterOne`. În prezen, `counterTwo.count` este `2`.
+
+Apelăm `counterTwo.increment()`, ceea ce setează `count` la `3`. Apoi, afișăm valoarea lui `counterOne`, ceea ce va afișa `3`.
+
+
+
+
+ +#### Răspuns: C + +În primul rând, apelăm `funcOne`. Pe prima linie a lui `funcOne`, apelăm funcția _asincronă_ `setTimeout`, din care funcția de apel se trimite către API-ul Web. (vezi articolul meu despre bucla evenimentelor aici.) + +Apoi apelăm promisiunea `myPromise` care este o operațiune _asincronă_. + +Ambele promisiuni și întârzierile (timeout) sunt operațiuni asincrone, iar funcția continuă să ruleze în timp ce finalizează promisiunea și gestionează apelul de întârziere `setTimeout`. Acest lucru înseamnă că se va afișa mai întâi `Last line 1!`, deoarece aceasta nu este o operațiune asincronă. + +Deoarece stiva de apel nu este încă goală, funcția `setTimeout` și promisiunea din `funcOne` nu pot fi adăugate încă la stiva de apel. + +În `funcTwo`, variabila `res` primește o `Promise` pentru că `Promise.resolve(Promise.resolve('Promise'))` este echivalent cu `Promise.resolve('Promise')` deoarece rezolvarea unei promisiuni rezolvă doar valoarea acesteia. Cuvântul cheie `await` din această linie oprește execuția funcției până când primește rezoluția promisiunii și apoi continuă să ruleze sincron până la finalizare, așa că sunt afișate `Promise 2!` apoi `Last line 2!` iar apelul `setTimeout` este trimis către API-ul Web. + +Apoi stiva de apel este goală. Promisiunile sunt _microtask-uri_ astfel că sunt rezolvate în primul rând atunci când stiva de apel este goală, așa că se afișează `Promise 1!`. + +Acum, deoarece `funcTwo` pa fost scoasă din stiva de apel, stiva de apel este goală. Callback-urile așteptând în coadă (`() => console.log("Timeout 1!")` din `funcOne`, și `() => console.log("Timeout 2!")` din `funcTwo`) sunt adăugate pe stivă unul câte unul. Primul callback afișează `Timeout 1!`, și este eliminat din stivă. Apoi, al doilea callback afișează `Timeout 2!`, și este eliminat din stivă. + +
++ +#### Răspuns: C + +Cu asteriscul `*`, importăm toate valorile exportate din acel fișier, atât exporturile implicite, cât și cele numite. Dacă avem următorul fișierȘ + +```javascript +// info.js +export const name = 'Lydia'; +export const age = 21; +export default 'I love JavaScript'; + +// index.js +import * as info from './info'; +console.log(info); +``` + +Acesta ar fi rezultatul înregistrărilor: + +```javascript +{ + default: "I love JavaScript", + name: "Lydia", + age: 21 +} +``` + +Pentru exemplul cu funcția `sum`, înseamnă că valoarea importată `sum` arată în felul următor: + +```javascript +{ default: function sum(x) { return x + x } } +``` + +Putem invoca această funcție, apelând `sum.default` + +
++ +#### Răspuns: C + +Cu un obiect Proxy, putem adăuga comportament personalizat unui obiect pe care îl transmitem ca al doilea argument. În acest caz, transmitem obiectul `handler` care conține două proprietăți: `set` și `get`. `set` este invocată ori de câte ori _set_ (setăm) valori de proprietate, `get` este invocată ori de câte ori _get_ (accesăm) valori de proprietate. + +Primul argument este un obiect gol `{}`, care este valoarea lui `person`. La acest obiect, se adaugă comportamentul personalizat specificat în obiectul `handler`. Dacă adăugăm o proprietate la obiectul `person`, `set` va fi invocată. Dacă accesăm o proprietate a obiectului `person`, `get` va fi invocată. + +În primul rând, am adăugat o nouă proprietate `name` la obiectul proxy (`person.name = "Lydia"`). `set` este invocată și înregistrează mesajul `"Added a new property!"`. + +Then, we access a property value on the proxy object, the `get` property on the handler object got invoked. `"Accessed a property!"` gets logged. + +
++ +#### Răspuns: A + +Cu `Object.seal` putem preveni _adăugarea_ de noi proprietăți sau _eliminarea_ proprietăților existente. + +Cu toate acestea, puteți încă să modificați valoarea proprietăților existente. + +
++ +#### Răspuns: C + +Metoda `Object.freeze` _îngheață_ un obiect. Nu se pot adăuga, modifica sau elimina proprietăți. + +Cu toate acestea, aceasta îngheață obiectul doar în mod _superficial_, ceea ce înseamnă că numai proprietățile _directe_ ale obiectului sunt înghețate. Dacă proprietatea este un alt obiect, cum ar fi `address` în acest caz, proprietățile de pe acel obiect nu sunt înghețate și pot fi modificate. + +
++ +#### Răspuns: A + +În primul rând, am apelat `myFunc()` fără a transmite niciun argument. Deoarece nu am transmis argumente, `num` și `value` au primit valorile lor implicite: `num` este `2`, și `value` este valoarea returnată de funcția `add`. Funcției `add` îi transmitem `num` ca argument, care avea valoarea `2`. `add` returnează `4`, care este valoarea lui `value`. + +Apoi, am apelat `myFunc(3)` și am transmis valoarea `3` ca valoare pentru argumentul `num`. Nu am transmis un argument pentru `value`. Deoarece nu am transmis o valoare pentru argumentul `value` acesta a primit valoarea implicită: valoarea returnată de funcția `add`. Funcției `add`, îi transmitem `num`, care are valoarea `3`. `add` returnează `6`, care este valoarea lui `value`. + +
++ +#### Răspuns: D + +În ES2020, putem adăuga variabile private în clase folosind simbolul `#`. Nu putem accesa aceste variabile în afara clasei. Atunci când încercăm să înregistrăm `counter.#number`, se aruncă o eroare de sintaxă (SyntaxError): nu putem accesa această variabilă în afara clasei `Counter`! + +
++ +#### Răspuns: B + +Pentru a itera prin `membrii` din fiecare element din array-ul `members` trebuie să transmitem `teams[i].members` către funcția generator `getMembers`. Funcția generator returnează un obiect generator. Pentru a itera prin fiecare element din acest obiect generator, trebuie să folosim `yield*`. + +Dacă am fi scris `yield`, `return yield`, sau `return`, întreaga funcție generator ar fi fost returnată prima dată când am apelat metoda `next`. + +
++ +#### Răspuns: C + +Funcția `addHobby` primește două argumente, `hobby` și `hobbies` cu valoarea implicită a array-ului `hobbies` din obiectul `person`. + +În primul rând, apelăm funcția `addHobby`, și transmitem `"running"` ca valoare pentru `hobby` și un array gol ca valoare pentru `hobbies`. Deoarece transmitem un array gol ca valoare pentru `hobbies`, `"running"` este adăugat la acest array gol. + +Apoi, apelăm funcția `addHobby` și transmitem `"dancing"` ca valoare pentru `hobby`. Nu am transmis o valoare pentru `hobbies`, astfel că aceasta primește valoarea implicită, adică proprietatea `hobbies` din obiectul `person`. Adăugăm hobby-ul `dancing` în array-ul `person.hobbies`. + +În final, apelăm funcția `addHobby`, și transmitem `"baking"` ca valoare pentru `hobby`, și array-ul `person.hobbies` ca valoare pentru `hobbies`. Adăugăm hobby-ul `baking` în array-ul `person.hobbies`. + +După adăugarea lui `dancing` și `baking`, valoarea lui `person.hobbies` este `["coding", "dancing", "baking"]` + +
++ +#### Răspuns: B + +Creăm variabila `pet` care este o instanță a clasei `Flamingo`. Când instantiem această instanță, `constructor` din clasa `Flamingo` este apelat. Mai întâi, se înregistrează `"I'm pink. 🌸"` după care apelăm `super()`. `super()` apelează constructorul clasei părinte, `Bird`. Constructorul din clasa `Bird` este apelat și înregistrează `"I'm a bird. 🦢"`. + +
++ +#### Răspuns: D + +Cuvântul cheie `const` înseamnă pur și simplu că nu putem _redeclara_ valoarea acelei variabile, aceasta este _numai pentru citire_ (read-only). Cu toate acestea, valoarea în sine nu este imutabilă. Proprietățile din array-ul `emojis` pot fi modificate, de exemplu, prin adăugarea de valori noi, prin decuparea lor sau prin setarea lungimii array-ului la 0. + +
++ +#### Răspuns: C + +Obiectele nu sunt iterabile în mod implicit. Un obiect devine iterabil atunci când protocolul iterator este prezent. Putem adăuga acest protocol manual prin adăugarea simbolului iterator `[Symbol.iterator]`, care trebuie să returneze un obiect generator, de exemplu, prin definirea unei funcții generator `*[Symbol.iterator]() {}`. Această funcție generator trebuie să furnizeze `Object.values` ale obiectulu `person` pentru a obține array-ul `["Lydia Hallie", 21]`: `yield* Object.values(this)`. + +
++ +#### Răspuns: C + +Condiția `if` din interiorul buclei `forEach` verifică dacă valoarea lui `num` este adevărată (truthy) sau falsă (falsy). Deoarece primul număr din array-ul `nums` este `0`, o valoare falsă, blocul de cod al instrucțiunii `if` nu va fi executat. `count` se incrementează doar pentru celelalte 3 numere din array-ul `nums`, adică `1`, `2` și `3`. Deoarece `count` se incrementează cu `1` de 3 ori, valoarea lui `count` este `3`. + +
++ +#### Răspuns: D + +Simbolul `?` ne permite să accesăm opțional proprietăți mai adânc în obiecte. Încercăm să înregistrăm elementul de pe indexul `1` din sub-array-ul de pe indexul `1` al array-ului `fruits`. Dacă sub-array-ul de pe indexul `1` din array-ul `fruits` nu există, va returna pur și simplu `undefined`. Dacă sub-array-ul de pe indexul `1` din array-ul `fruits` există, dar acest sub-array nu are un element pe indexul `1` va returna, de asemenea, `undefined`. + +În primul rând, încercăm să înregistrăm al doilea element din sub-array-ul`['🍍']` din `[['🍊', '🍌'], ['🍍']]`. Acest sub-array conține doar un singur element, ceea ce înseamnă că nu există niciun element pe indexul `1`, și va returna `undefined`. + +Apoi, apelăm funcția `getFruits` fără a transmite o valoare ca argument, ceea ce înseamnă că `fruits` are implicit o valoare de `undefined`. Deoarece facem o verificare condițională pentru accesarea elementului de pe indexul `1` al `fruits`, aceasta va returna `undefined` deoarece acest element de pe indexu `1` nu există. + +În cele din urmă, încercăm să înregistrăm al doilea element din sub-array-ul `['🍊', '🍌']` din `['🍍'], ['🍊', '🍌']`. Elementul de pe indexul `1` în acest sub-array este `🍌`, are este înregistrat. + +
++ +#### Răspuns: A + +Am setat variabila `calc` gal cu o nouă instanță a clasei `Calc`. Apoi, am creat o altă instanță nouă a clasei `Calc`, și am apelat metoda `increase` pe această instanță. Deoarece proprietatea `count` se află în constructorul clasei `Calc`, proprietatea `count` nu este partajată în prototipul clasei `Calc`. Acest lucru înseamnă că valoarea lui `count` nu a fost actualizată pentru instanța către care arată `calc` astfel încât `count` rămâne `0`. + +
++ +#### Răspuns: B + +Funcția `updateUser` actualizează valorile proprietăților `email` și `password` ale obiectului `user`, dacă aceste valori sunt transmise funcției, după care funcția returnează obiectul `user`. Valoarea returnată a funcției `updateUser` este obiectul `user`, ceea ce înseamnă că valoarea lui `updatedUser` este o referință către același obiect `user` la care face referință și `user`. `updatedUser === user` este egal cu `true`. + +
++ +#### Răspuns: C + +În primul rând, apelăm metoda `slice` pe array-ul `fruit`. Metoda `slice` nu modifică array-ul original, ci returnează valoarea pe care a tăiat-o din array: emoji-ul de banană. +Apoi, apelăm metoda `splice` pe array-ul `fruit`. Metoda `splice` modifică array-ul original, ceea ce înseamnă că array-ul `fruit` acum conține `['🍊', '🍎']`. +În cele din urmă, apelăm metoda `unshift` pe array-u `fruit`, care modifică array-ul original prin adăugarea valorii furnizate, în acest caz, ‘🍇’ ca prim element în array. Array-ul `fruit` acum conține `['🍇', '🍊', '🍎']`. + +
++ +#### Răspuns: B + +Cheile obiectelor sunt convertite în șiruri de caractere. + +Deoarece valoarea lui `dog` este un obiect, `animals[dog]` înseamnă de fapt că creăm o nouă proprietate numită `"object Object"` egală cu noul obiect. `animals["object Object"]` este acum egal cu `{ emoji: "🐶", name: "Mara"}`. + +`cat` este, de asemenea, un obiect, ceea ce înseamnă că `animals[cat]` înseamnă de fapt că suprascriem valoarea lui `animals["object Object"]` cu noile proprietăți ale pisicii. + +Înregistrarea `animals[dog]`, sau mai exact `animals["object Object"]` deoarece convertirea obiectului `dog` într-un șir rezultă în `"object Object"`, returnează `{ emoji: "🐈", name: "Sara" }`. + +
++ +#### Răspuns: A + +Funcția `updateEmail` este o funcție săgeată și nu este legată de obiectul `user`. Acest lucru înseamnă că cuvântul cheie `this` nu se referă la obiectul `user`, ci se referă la domeniul global în acest caz. Valoarea `email` din obiectul `user` nu se actualizează. Când se înregistrează valoarea `user.email`, se returnează valoarea originală `my@email.com`. + +
++ +#### Răspuns: D + +Metoda `Promise.all` rulează promisiunile transmise în paralel. Dacă o promisiune eșuează, metoda `Promise.all` se _respinge_ cu valoarea promisiunii respinse. În acest caz, `promise3` a fost respinsă cu valoarea `"Third"`. Prindem valoarea respinsă în metoda `catch` lantată în invocarea `runPromises` pentru a prinde orice erori din interiorul funcției `runPromises`. Se înregistrează doar `"Third"` deoarece `promise3` a fost respinsă cu această valoare. + +
++ +#### Răspuns: C + +Metoda `fromEntries` transformă o matrice 2D într-un obiect. Primul element din fiecare submatrice va fi cheia, iar al doilea element din fiecare submatrice va fi valoarea. În acest caz, facem mapare peste matricea `keys` care returnează o matrice în care primul element este elementul din matricea cheilor la indexul curent, iar al doilea element este elementul din matricea valorilor la indexul curent. + +Acest lucru creează o matrice de submatrici care conțin cheile și valorile corecte, rezultând în `{ name: "Lydia", age: 22 }` + +
++ +#### Răspuns: C + +Valoarea implicită a lui `address` este un obiect gol `{}`. Când setăm variabila `member` egală cu obiectul returnat de funcția `createMember`, nu am transmis o valoare pentru `address`, ceea ce înseamnă că valoarea lui `address` este obiectul gol implicit `{}`. Un obiect gol este o valoare adevărată (truthy), ceea ce înseamnă că condiția din expresia ternară `address ? address : null` returnează `true`. Prin urmare, valoarea lui `address` este obiectul gol `{}`. + +
++ +#### Răspuns: B + +Condiția din instrucțiunea `if` verifică dacă valoarea lui `!typeof randomValue` este egală cu `"string"`. Operatorul `!` convertește valoarea la o valoare booleană. Dacă valoarea este adevărată (truthy), valoarea returnată va fi `false`, iar dacă valoarea este falsă (falsy), valoarea returnată va fi `true`. În acest caz, valoarea returnată de `typeof randomValue` este valoarea adevărată (truthy) `"number"`, ceea ce înseamnă că valoarea lui `!typeof randomValue` este valoarea booleană `false`. + +`!typeof randomValue === "string"` întotdeauna returnează `false`, deoarece de fapt verificăm `false === "string"`. Deoarece condiția returnează `false`, blocul de cod al instrucțiunii `else` se execută, iar `Yay it's a string!` este înregistrat. + +
++ +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](../de-DE/README.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](../id-ID/README.md) +- [🇮🇹 Italiano](../it-IT/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](../ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](../nl-NL/README.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) - [🇬🇧 English](../README.md) -- [🇪🇸 Español](./es-ES/README-ES.md) -- [🇫🇷 Français](./fr-FR/README_fr-FR.md) -- [🇮🇩 Indonesia](./id-ID/README.md) -- [🇯🇵 日本語](./ja-JA/README-ja_JA.md) -- [🇰🇷 한국어](./ko-KR/README-ko_KR.md) -- [🇳🇱 Nederlands](./nl-NL/README.md) -- [🇧🇷 Português Brasil](./pt-BR/README_pt_BR.md) -- [🇹🇭 ไทย](./th-TH/README-th_TH.md) -- [🇹🇷 Türkçe](./tr-TR/README-tr_TR.md) -- [🇺🇦 Українська мова](./uk-UA/README.md) -- [🇻🇳 Tiếng Việt](./vi-VI/README-vi.md) -- [🇨🇳 简体中文](./zh-CN/README-zh_CN.md) -- [🇹🇼 繁體中文](./zh-TW/README_zh-TW.md) +- [🇽🇰 Shqip](../sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md) +
+
-Когда ты изменяешь один объект, то изменяются значения всех ссылок, указывающих на этот объект.
+Когда вы изменяете один объект, то изменяются значения всех ссылок, указывающих на этот объект.
@@ -250,7 +264,7 @@ console.log(b === c);
#### Ответ: C
-`new Number()` это встроенный конструктор функции. И хотя он выглядит как число, это не настоящее число: у него есть ряд дополнительных фич и это объект.
+`new Number()` это встроенный конструктор функции. И хотя он выглядит как число, это не настоящее число: у него есть ряд дополнительных особеннстей, и это объект.
Оператор `==` разрешает приведение типов, он проверяет равенство _значений_. Оба значения равны `3`, поэтому возвращается `true`.
@@ -270,13 +284,13 @@ class Chameleon {
return this.newColor;
}
- constructor({ newColor = "green" } = {}) {
+ constructor({ newColor = 'green' } = {}) {
this.newColor = newColor;
}
}
-const freddie = new Chameleon({ newColor: "purple" });
-freddie.colorChange("orange");
+const freddie = new Chameleon({ newColor: 'purple' });
+freddie.colorChange('orange');
```
- A: `orange`
@@ -289,7 +303,7 @@ freddie.colorChange("orange");
#### Ответ: D
-Функция `colorChange` является статичной. Статичные методы не имеют доступа к экземплярам класса. Так как `freddie` это экземпляр, то статичный метод там не доступен. Поэтому выбрасывается ошибка `TypeError`.
+Функция `colorChange` является статической. Статические методы предназначены для работы только в конструкторе, в котором они созданы, и не могут передаваться каким-либо дочерним элементам или вызываться в экземплярах класса. Так как `freddie` является экземпляром класса `Chameleon`, функция не может быть вызвана для него. Будет выдана ошибка `TypeError`.
@@ -313,7 +327,12 @@ console.log(greetign);
#### Ответ: A
-В консоли выведется объект, потому что мы только что создали пустой объект в глобальном объекте! Когда мы вместо `greeting` написали `greetign`, интерпретатор JS на самом деле выполнил `global.greetign = {}` (или `window.greetign = {}` в браузере).
+В консоли выведется объект, потому что мы только что создали пустой объект в глобальном объекте! Когда мы вместо `greeting` написали `greetign`, интерпретатор JS на самом деле увидел:
+
+1. `global.greetign = {}` в Node.js
+2. `window.greetign = {}`, `frames.geetign = {}` и `self.greetign` в браузерах.
+3. `self.greetign` в веб-воркерах.
+4. `globalThis.greetign` во всех окружениях.
Нужно использовать `"use strict"`, чтобы избежать такого поведения. Эта запись поможет быть уверенным в том, что переменная была определена перед тем как ей присвоили значение.
@@ -326,10 +345,10 @@ console.log(greetign);
```javascript
function bark() {
- console.log("Woof!");
+ console.log('Woof!');
}
-bark.animal = "dog";
+bark.animal = 'dog';
```
- A: Ничего, всё в порядке!
@@ -359,7 +378,7 @@ function Person(firstName, lastName) {
this.lastName = lastName;
}
-const member = new Person("Lydia", "Hallie");
+const member = new Person('Lydia', 'Hallie');
Person.getFullName = function () {
return `${this.firstName} ${this.lastName}`;
}
@@ -377,7 +396,9 @@ console.log(member.getFullName());
#### Ответ: A
-Нельзя добавлять свойства конструктору, как обычному объекту. Если нужно добавить фичу всем объектам, то необходимо использовать прототипы. В данном случае
+В JavaScript функции являются объектами, поэтому метод `getFullName` добавляется к самому объекту функции-конструктора. По этой причине мы можем вызвать `Person.getFullName()`, но `member.getFullName` выдает `TypeError`.
+
+Если вы хотите, чтобы метод был доступен для всех экземпляров объекта, вы должны добавить его в свойство прототипа:
```js
Person.prototype.getFullName = function () {
@@ -385,8 +406,6 @@ Person.prototype.getFullName = function () {
}
```
-сделает метод `member.getFullName()` рабочим. В чем тут преимущество? Предположим, что мы добавили этот метод к конструктору. Возможно, не каждому экземпляру `Person` нужен этот метод. Это приведет к большим потерям памяти, т.к. все экземпляры будут иметь это свойство. Напротив, если мы добавим этот метод только к прототипу, у нас будет только одно место в памяти, к которому смогут обращаться все экземпляры!
-
@@ -400,8 +419,8 @@ function Person(firstName, lastName) {
this.lastName = lastName;
}
-const lydia = new Person("Lydia", "Hallie");
-const sarah = Person("Sarah", "Smith");
+const lydia = new Person('Lydia', 'Hallie');
+const sarah = Person('Sarah', 'Smith');
console.log(lydia);
console.log(sarah);
@@ -457,7 +476,7 @@ console.log(sarah);
#### Ответ: B
-Все объекты имеют прототипы, кроме **базового объекта**. Базовый объект имеет доступ до некоторых методов и свойств, таких как `.toString`. Именно поэтому мы можем использовать встроенные методы JavaScript! Все эти методы доступны в прототипе. Если JavaScript не может найти метод непосредственно у объекта, он продолжает поиск по цепочке прототипов пока не найдет.
+Все объекты имеют прототипы, кроме **базового объекта**. Базовый объект — это объект, созданный пользователем, или объект, созданный с использованием ключевого слова `new`. Базовый объект имеет доступ к некоторым методам и свойствам, таким как `.toString`. Вот почему вы можете использовать встроенные методы JavaScript! Все такие способы доступны в прототипе. Хотя JavaScript не может найти метод непосредственно в вашем объекте, он идет вниз по цепочке прототипов и находит его там, что делает его доступным.
@@ -471,7 +490,7 @@ function sum(a, b) {
return a + b;
}
-sum(1, "2");
+sum(1, '2');
```
- A: `NaN`
@@ -538,7 +557,7 @@ function getPersonInfo(one, two, three) {
console.log(three);
}
-const person = "Lydia";
+const person = 'Lydia';
const age = 21;
getPersonInfo`${person} is ${age} years old`;
@@ -553,7 +572,7 @@ getPersonInfo`${person} is ${age} years old`;
#### Ответ: B
-При использовании тегированных шаблонных литералов первым аргументом всегда будет массив строковых значений. Оставшимися аргументами будут значения переданных выражений!
+При использовании [шаблонных строк](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Template_literals) первым аргументом всегда будет массив строковых значений. Оставшимися аргументами будут значения переданных выражений!
@@ -565,9 +584,9 @@ getPersonInfo`${person} is ${age} years old`;
```javascript
function checkAge(data) {
if (data === { age: 18 }) {
- console.log("Ты взрослый!");
+ console.log('Ты взрослый!');
} else if (data == { age: 18 }) {
- console.log("Ты все еще взрослый.");
+ console.log('Ты все еще взрослый.');
} else {
console.log(`Хмм.. Кажется, у тебя нет возраста.`);
}
@@ -627,7 +646,7 @@ getAge(21);
```javascript
function getAge() {
- "use strict";
+ 'use strict';
age = 21;
console.log(age);
}
@@ -655,7 +674,7 @@ getAge();
###### 21. Чему будет равно `sum`?
```javascript
-const sum = eval("10*10+5");
+const sum = eval('10*10+5');
```
- A: `105`
@@ -678,7 +697,7 @@ const sum = eval("10*10+5");
###### 22. Как долго будет доступен cool_secret?
```javascript
-sessionStorage.setItem("cool_secret", 123);
+sessionStorage.setItem('cool_secret', 123);
```
- A: Всегда, данные не потеряются.
@@ -731,12 +750,12 @@ console.log(num);
###### 24. Каким будет результат?
```javascript
-const obj = { 1: "a", 2: "b", 3: "c" };
+const obj = { 1: 'a', 2: 'b', 3: 'c' };
const set = new Set([1, 2, 3, 4, 5]);
-obj.hasOwnProperty("1");
+obj.hasOwnProperty('1');
obj.hasOwnProperty(1);
-set.has("1");
+set.has('1');
set.has(1);
```
@@ -762,7 +781,7 @@ set.has(1);
###### 25. Что будет в консоли?
```javascript
-const obj = { a: "one", b: "two", a: "three" };
+const obj = { a: 'one', b: 'two', a: 'three' };
console.log(obj);
```
@@ -787,7 +806,7 @@ console.log(obj);
- A: Да
- B: Нет
-- C: Это зависит
+- C: Это зависит от ...
@@ -831,12 +850,12 @@ for (let i = 1; i < 5; i++) { ```javascript String.prototype.giveLydiaPizza = () => { - return "Just give Lydia pizza already!"; + return 'Just give Lydia pizza already!'; }; -const name = "Lydia"; +const name = 'Lydia'; -name.giveLydiaPizza(); +console.log(name.giveLydiaPizza()) ``` - A: `"Just give Lydia pizza already!"` @@ -860,8 +879,8 @@ name.giveLydiaPizza(); ```javascript const a = {}; -const b = { key: "b" }; -const c = { key: "c" }; +const b = { key: 'b' }; +const c = { key: 'c' }; a[b] = 123; a[c] = 456; @@ -893,9 +912,9 @@ console.log(a[b]); ###### 30. Каким будет результат? ```javascript -const foo = () => console.log("First"); -const bar = () => setTimeout(() => console.log("Second")); -const baz = () => console.log("Third"); +const foo = () => console.log('First'); +const bar = () => setTimeout(() => console.log('Second')); +const baz = () => console.log('Third'); bar(); foo(); @@ -1002,7 +1021,7 @@ WebAPI не может добавлять содержимое в стек ко ###### 33. Что будет в консоли? ```javascript -const person = { name: "Lydia" }; +const person = { name: 'Lydia' }; function sayHi(age) { console.log(`${this.name} is ${age}`); @@ -1038,7 +1057,7 @@ function sayHi() { return (() => 0)(); } -typeof sayHi(); +console.log(typeof sayHi()); ``` - A: `"object"` @@ -1054,6 +1073,7 @@ typeof sayHi(); Функция `sayHi` возвращает значение, возвращаемое из немедленно вызываемого функционального выражения (IIFE). Результатом является `0` типа `"number"`. Для информации: в JS 8 встроенных типов: `null`, `undefined`, `boolean`, `number`, `string`, `object`, `symbol` и `bigint`. `"function"` не является отдельным типом, т.к. функции являются объектами типа `"object"`. +
+ +#### Ответ: A + +Во-первых, мы вызваем `myFunc()` без передачи каких-либо аргументов. Поскольку мы не передаем аргументы, `num` и `value` получают свои значения по умолчанию: `num` равно `2`, а `value` возвращаемое значение функции `add`. В функцию `add` мы передаем в качестве аргумента `num` со значением `2`. `add` возвращает `4`, что является значением `value`. + +Затем мы вызваем `myFunc(3)` и передаем значение `3` в качестве значения аргумента `num`. Мы не передаем аргумент для `value`. Поскольку мы не передаем значение для аргумента `value`, он получаеи значение по умолчанию: возвращаемое значение функции `add`. В `add` мы передаем `num`, значение которого равно `3`. `add` возвращает `6`, что является значением `value`. + +
++ +#### Ответ: D + +В ES2020 мы можем добавлять приватные переменные в классы с помощью символа `#`. Мы не можем получить доступ к этим переменным вне класса. Когда мы пытаемся записать `counter.#number`, выдается `SyntaxError`: мы не можем получить доступ вне класса `Counter`! + +
++ +#### Ответ: B + +Чтобы выполнить итерацию по `members` в каждом элементе массива `teams`, нам нужно передать `teams[i].members` в функцию генератора `getMembers`. Функция генератора возвращает объект генератора. Чтобы перебрать каждый элемент в этом объекте-генераторе, нам нужно использовать `yield*`. + +Если бы мы написали `yield`, `return yield` или `return`, вся функция генератора была бы возвращена при первом вызове метода `next`. + +
++ +#### Ответ: C + +Функция `addHobby` получает два аргумента, `hobby` и `hobbies`, со значением по умолчанию массива `hobbies` в объекте `person`. + +Во-первых, мы вызываем функцию `addHobby` и передаем `"running"` в качестве значения для `hobby`, а пустой массив в качестве значения для `hobbies`. Так как мы передаем пустой массив в качестве значения для `hobbies`, `"running"` добавляется к этому пустому массиву. + +Затем мы вызываем функцию `addHobby` и передаем `dancing` в качестве значения для `hobby`. Мы не передавали значение для `hobbies`, поэтому оно получает значение по умолчанию, свойство `hobbies` объекта `person`. Мы помещаем хобби `dancing` в массив `person.hobbies`. + +Наконец, мы вызываем функцию `addHobby` и передаем `"baking"` в качестве значения для `hobby`, а массив `person.hobbies` в качестве значения для `hobbies`. Мы помещаем хобби `baking` в массив `person.hobbies`. + +После нажатия `танцы` и `выпечка`, значение `person.hobbies` равно `["coding", "dancing", "baking"]` + +
++ +#### Ответ: B + +Мы создаем переменную `pet`, которая является экземпляром класса `Flamingo`. Когда мы создаем этот экземпляр, вызывается `constructor` для `Flamingo`. Сначала регистрируется `"I'm pink. 🌸"`, после чего мы вызываем `super()`. `super()` вызывает конструктор родительского класса `Bird`. Конструктор в `Bird` вызывается и регистрирует `"I'm a bird. 🦢"`. + +
++ +#### Ответ: D + +Ключевое слово `const` просто означает, что мы не можем _повторно объявить_ значение этой переменной, оно доступно только для чтения. Однако само значение не является неизменным. Свойства массива `emojis` можно изменить, например, добавив новые значения, объединив их или установив длину массива на 0. + +
++ +#### Ответ: C + +По умолчанию объекты не являются итерируемыми. Итерируемым объект становится, если присутствует протокол итератора. Мы можем добавить это вручную, добавив символ итератора `[Symbol.iterator]`, который должен возвращать объект-генератор, например, сделав его функцией-генератором `*[Symbol.iterator]() {}`. Эта функция-генератор должна возвращать `Object.values` объекта `person`, если мы хотим, чтобы он возвращал массив `["Lydia Hallie", 21]`: `yield* Object.values(this)`. + +
++ +#### Ответ: C + +Условие `if` внутри цикла `forEach` проверяет, является ли значение `num` истинным или ложным. Поскольку первое число в массиве `nums` равно `0`, то есть ложное значение, блок оператора `if` не будет выполнен. `count` увеличивается только для остальных 3 чисел в массиве `nums`: `1`, `2` и `3`. Поскольку `count` увеличивается на 1 3 раза, значение `count` равно `3`. + +
++ +#### Ответ: D + +`?` позволяет нам дополнительно получить доступ к более глубоким вложенным свойствам внутри объектов. Мы пытаемся зарегистрировать элемент с индексом `1` в подмассиве с индексом `1` массива `fruits`. Если подмассив с индексом `1` в массиве `fruits` не существует, он просто вернет `undefined`. Если подмассив с индексом `1` в массиве `fruits` существует, но в этом подмассиве нет элемента с индексом `1`, он также вернет значение `undefined`. + +Во-первых, мы пытаемся зарегистрировать второй элемент в `['🍍']` подмассива `[['🍊', '🍌'], ['🍍']]`. Этот подмассив содержит только один элемент, что означает, что в индексе `1` нет элемента, и возвращает значение `undefined`. + +Затем мы вызываем функцию `getFruits` без передачи значения в качестве аргумента, что означает, что `fruits` по умолчанию имеет значение `undefined`. Поскольку мы условно связываем элемент с индексом `1` массива `fruits`, он возвращает значение `undefined`, поскольку этот элемент с индексом `1` не существует. + +Наконец, мы попытаемся зарегистрировать второй элемент в `['🍊', '🍌']` подмассива `['🍍'], ['🍊', '🍌']`. Элемент с индексом `1` в этом подмассиве — `🍌`, который регистрируется. + +
++ +#### Ответ: A + +Мы устанавливаем переменную `calc` равной новому экземпляру класса `Calc`. Затем мы создаем экземпляр нового экземпляра `Calc` и вызываем метод увеличения для этого экземпляра. Поскольку свойство `count` находится в конструкторе класса `Calc`, свойство `count` не используется в прототипе `Calc`. Это означает, что значение `count` не было обновлено для экземпляра, на который указывает `calc`, `count` по-прежнему равен `0`. + +
++ +#### Ответ: B + +Функция `updateUser` обновляет значения свойств `email` и `password` у пользователя, если их значения переданы в функцию, после чего функция возвращает объект `user`. Возвращаемое значение функции `updateUser` — это объект `user`, что означает, что значение `updatedUser` является ссылкой на тот же объект `user`, на который указывает `user`. `updatedUser === user` равно `true`. + +
++ +#### Ответ: C + +Во-первых, мы вызываем метод `slice` для массива фруктов. Метод `slice` не изменяет исходный массив, а возвращает значение, которое было вырезано из массива: банановый смайлик. +Затем мы вызываем метод `splice` для массива фруктов. Метод `splice` изменяет исходный массив, что означает, что массив фруктов теперь состоит из `['🍊', '🍎']`. +Наконец, мы вызываем метод `unshift` для массива `fruit`, который изменяет исходный массив, добавляя предоставленное значение, в данном случае `🍇`, в качестве первого элемента в массиве. Массив фруктов теперь состоит из `['🍇', '🍊', '🍎']`. + +
++ +#### Ответ: B + +Ключи объекта преобразуются в строки. + +Поскольку значение `dog` является объектом, `animals[dog]` на самом деле означает, что мы создаем новое свойство под названием `"object Object"`, равное новому объекту. `animals["object Object"]` теперь равно `{ emoji: "🐶", name: "Mara"}`. + +`cat` также является объектом, что означает, что `animals[cat]` на самом деле означает, что мы перезаписываем значение `animals["object Object"]` новыми свойствами кота. + +Регистрация `animals[dog]`, или фактически `animals["object Object"]`, поскольку преобразование объекта `dog` в строку приводит к `"object Object"`, возвращает `{ emoji: "🐈", name: " Сара"}`. + +
++ +#### Ответ: A + +Функция `updateEmail` представляет собой стрелочную функцию и не привязана к объекту пользователя. Это означает, что ключевое слово `this` не относится к объекту `user`, а в данном случае относится к глобальной области видимости. Значение `email` в объекте `user` не обновляется. При регистрации значения `user.email` возвращается исходное значение `my@email.com`. + +
++ +#### Ответ: D + +Метод `Promise.all` выполняет переданные промисы параллельно. Если одно обещание не выполняется, метод `Promise.all` _отколняется_ со значением отклоненного обещания. В этом случае `promise3` отклонен со значением `"Third"`. Мы перехватываем отклоненное значение в цепочке методов `catch` при вызове `runPromises`, чтобы перехватывать любые ошибки внутри функции `runPromises`. Только `"Third"` регистрируется, так как `promise3` отклонено с этим значением. + +
++ +#### Ответ: C + +Метод `fromEntries` превращает двумерный массив в объект. Первый элемент в каждом подмассиве будет ключом, а второй элемент в каждом подмассиве будет значением. В этом случае мы сопоставляем массив `keys`, который возвращает массив, первый элемент которого является элементом массива ключей текущего индекса, а второй элемент является элементом массива значений текущего индекса. + +Это создает массив подмассивов, содержащих правильные ключи и значения, что приводит к `{ name: "Lydia", age: 22 }` + +
++ +#### Ответ: C + +Значением по умолчанию для `address` является пустой объект `{}`. Когда мы устанавливаем переменную `member` равной объекту, возвращаемому функцией `createMember`, мы не передаем значение для адреса, что означает, что значение адреса является пустым объектом по умолчанию `{}`. Пустой объект является истинным значением, что означает, что условие `address ? address : null` условно возвращает `true`. Значением адреса является пустой объект `{}`. + +
++ +#### Ответ: B + +Условие в операторе `if` проверяет, равно ли значение `!typeof randomValue` "строке". Оператор `!` преобразует значение в логическое значение. Если значение истинно, возвращаемое значение будет "ложным", если значение ложным, возвращаемое значение будет "истинным". В этом случае возвращаемое значение `typeof randomValue` является истинным значением `"number"`, что означает, что значение `!typeof randomValue` является логическим значением `false`. + +`!typeof randomValue === "string"` всегда возвращает `false`, поскольку на самом деле мы проверяем `false === "string"`. Поскольку условие вернуло `false`, запускается блок кода оператора `else`, и в журнал заносится сообщение `Yay it's a string!`. + +
++ +- [🇸🇦 العربية](../ar-AR/README_AR.md) +- [🇪🇬 اللغة العامية](../ar-EG/README_ar-EG.md) +- [🇧🇦 Bosanski](../bs-BS/README-bs_BS.md) +- [🇩🇪 Deutsch](../de-DE/README.md) +- [🇪🇸 Español](../es-ES/README-ES.md) +- [🇫🇷 Français](../fr-FR/README_fr-FR.md) +- [🇮🇩 Indonesia](../id-ID/README.md) +- [🇮🇹 Italiano](../it-IT/README.md) +- [🇯🇵 日本語](../ja-JA/README-ja_JA.md) +- [🇰🇷 한국어](../ko-KR/README-ko_KR.md) +- [🇳🇱 Nederlands](../nl-NL/README.md) +- [🇵🇱 Polski](../pl-PL/README.md) +- [🇧🇷 Português Brasil](../pt-BR/README_pt_BR.md) +- [🇷o Română](../ro-RO/README.ro.md) +- [🇷🇺 Русский](../ru-RU/README.md) +- [🇽🇰 Shqip](./sq-KS/README_sq_KS.md) +- [🇹🇭 ไทย](../th-TH/README-th_TH.md) +- [🇹🇷 Türkçe](../tr-TR/README-tr_TR.md) +- [🇺🇦 Українська мова](../uk-UA/README.md) +- [🇻🇳 Tiếng Việt](../vi-VI/README-vi.md) +- [🇨🇳 简体中文](../zh-CN/README-zh_CN.md) +- [🇹🇼 繁體中文](../zh-TW/README_zh-TW.md) + +
++ +#### Përgjigja: D + +Brenda funksionit, fillimisht deklarojmë variablën `name` me fjalën kyçe `var`. Kjo do të thotë se variabla ngrihet - hoistohet (hapësira e memories caktohet gjatë fazës së krijimit) me vlerën e paracaktuar `undefined`, deri sa të arrijmë në rreshtin ku e definojmë variablën. Nuk kemi definuar ende variablën në rreshtin ku përpiqemi të shfaqim variablën `name`, kështu që ajo ende mban vlerën `undefined`. + +Variablat me fjalën kyçe `let` (dhe `const`) hoistohen, por ndryshe nga `var`, nuk inicializohen. Ato nuk janë të qasshme para rreshtit ku i deklarojmë (inicializojmë) ato. Kjo quhet "zona e vdekur temporale". Kur përpiqemi të iu qasemi variablave para se ato të jenë të deklaruara, JavaScript hedh një `ReferenceError`. + +
++ +#### Përgjigja: C + +Për shkak të ***event queque*** në JavaScript, funksioni callback `setTimeout` thirret pas ekzekutimit të unazës. Pasi që variabla `i` në iterimin e parë u deklarua duke përdorur fjalën kyçe `var`, kjo vlerë ishte globale. Gjatë unazës, ne rritëm vlerën e `i` me `1` çdo herë, duke përdorur operatorin unar `++`. Deri në kohën që funksioni callback `setTimeout` u thirr, `i` ishte e barabartë me `3` në unazën e parë. + +Në unazën e dytë, variabla `i` u deklarua duke përdorur fjalën kyçe `let`: variablat e deklaruara me fjalën kyçe `let` (dhe `const`) janë të qasshme në bllok (një bllok është çdo gjë mes `{ }`). Gjatë çdo iteracioni, `i` do të ketë një vlerë të re, dhe çdo vlerë është e qasshme brenda unazës. + +
++ +#### Përgjigja: B + +Vini re se vlera e `diameter` është një funksion i zakonshëm, ndërsa vlera e `perimeter` është një funksion shigjete (arrow function). + +Në funksionet shigjeta, fjala kyçe `this` referohet në qasjen në rrethinën aktuale përreth saj, ndryshe nga funksionet e zakonshme! Kjo do të thotë se kur ne e thërrasim `perimeter`, ajo nuk referohet tek objekti shape, por tek rrethina e saj (për shembull "window"). + +`radius` nuk ka ndonjë vlerë të caktuar në atë objekt, prandaj do të kemi si rezultat `NaN`. + +
++ +#### Përgjigja: A + +Operatori unar `+` provon të e konvertojë operandin në numër. `true` është `1`, dhe `false` është `0`. + +Vargu i karaktereve (stringu) `'Lydia'` konsiderohet si vlerë `true`. Çfarë ne realisht po pyesim është "a është kjo vlerë e vërtetë e pavërtetë?". Kjo do të kthejë vlerën `false`. + +
++ +#### Përgjigja: A + +Në JavaScript, të gjithë çelësat (keys) e objektit janë stringje (përveç nëse është Symbol). Edhe nëse nuk i _shkruajmë_ si stringje, ato gjithmonë konvertohen në stringje në prapavijë. + +JavaScript interpreton deklarimet. Kur përdorim notacionin e kllapave, ai shikon kllapën e parë hapëse `[` dhe vazhdon derisa të gjejë kllapën mbyllëse `]`. Vetëm atëherë do të vlerësohet deklarata (kthehet vlera e caktuar për atë deklarim). + +`mouse[bird.size]`: Fillimisht gjendet vlera e `bird.size`, e cila është `"small"`. `mouse["small"]` kthen `true` + +Megjithatë, me notacionin pikë, kjo nuk ndodh. `mouse` nuk ka një çelës të quajtur `bird`, që do të thotë se `mouse.bird` është `undefined`. Pastaj, ne kërkojmë "size" duke përdorur notacionin pikë: "mouse.bird.size". Meqenëse `mouse.bird` është `undefined`, ne në fakt po pyesim 'undefined.size'. Kjo nuk është valide dhe do të marrim një gabim të ngjashëm me `Cannot read property "size" of undefined`. + +
+
+
+#### Përgjigja: A
+
+Në JavaScript, të gjitha objektet ndërveprojnë me _referencë_ kur i vendosin me vlera të barabarta me njëri-tjetrin.
+
+Fillimisht, variabla `c` mbanë vlerën për një objekt. Më vonë, ne e caktojmë `d` me të njejtën reference të cilën `c` ka tek objekti.
+
+
+
+Kur e ndryshoni një objekt, i ndryshoni të gjitha objektet.
+
+
+ +#### Përgjigja: C + +`new Number()` është konstruktor i integruar (built-in function). Edhe pse duket si një numër, nuk është në të vërtetë një numër: ai ka një mori karakteristikash shtesë dhe si rrjedhojë është një objekt. + +Kur përdorim operatorin `==` (operatorin i barazimit), ai kontrollon vetëm nëse ka të njëjtën _vlerë_. Të dy kanë vlerën `3`, kështu që kthen `true`. + +Megjithatë, kur përdorim operatorin `===` (operatori i barazisë strikte), të dy vlerat dhe tipi i tyre duhet të jenë të njëjta. Nuk është: `new Number()` nuk është një numër, është një __objekt__. Të dy kthejnë `false`. + +
++ +#### Përgjigja: D + +Funksioni `colorChange` është statik. Metodat statike janë krijuar për të "jetuar" vetëm në konstruktorin në të cilin janë krijuar dhe nuk mund t'i kalohen asnjë fëmije ose të thirren në instancat e klasës. Meqenëse `freddie` është një instancë e klasës Chameleon, funksioni nuk mund të thirret. Në këtë rast do të kthehet `TypeError`. + +
++ +#### Përgjigja: A + +Do të printojë objekt, sepse ne sapo krijuam një objekt bosh në objektin global! Kur e shkruajtëm gabim `greeting` si `greetign`, interpretuesi i JS në fakt e pa këtë si: + +1. `global.greetign = {}` në Node.js +2. `window.greetign = {}`, `frames.greetign = {}` dhe `self.greetign` në shfletues (browser). +3. `self.greetign` në web workers. +4. `globalThis.greetign` në të gjitha mjediset. + +Për të shmangur këtë, ne mund të përdorim `"use strict"`. Kjo siguron që ju të keni deklaruar një variabël përpara se ta vendosni atë të barabartë (inicializoni ndonjë variabël tjetër me vlerën e saj) me ndonjë gjë. + +
++ +#### Përgjigja: A + +Kjo është e mundshme në JavaScript, spese funksionet janë objekte! (Gjithçka, përveç tipeve primitive janë objekte) + +Një funksion është një lloj i veçantë objekti. Kodi që shkruani vetë nuk është funksioni aktual. Funksioni është një objekt me veti. Kjo veti është e pavokueshme. + +
++ +#### Përgjigja: A + +Në JavaScript, funksionet janë objekte dhe për këtë arsye metoda `getFullName` i shtohet vetë objektit të funksionit të konstruktorit. Për këtë arsye, ne mund të thërrasim `Person.getFullName()`, por `member.getFullName` do të kthejë `TypeError`. + +Nëse dëshironi që një metodë të jetë e qasshme për të gjitha instancat e objektit, duhet ta shtoni atë në vetinë e quajtur "prototype": + +```js +Person.prototype.getFullName = function() { + return `${this.firstName} ${this.lastName}`; +}; +``` + +
++ +#### Përgjigja: A + +Për `sarah`, ne nuk përdorëm fjalën kyçe `new`. Kur përdorim `new`, `this` i referohet objektit të ri bosh që krijojmë. Megjithatë, nëse nuk shtoni `new`, `this` i referohet **objektit global**! + +E cekëm se `this.firstName` është `"Sarah"` dhe `this.lastName` është `"Smith"`. Çfarë bëmë realisht është se ne e definuam `global.firstName = 'Sarah'` dhe `global.lastName = 'Smith'`. `sarah` vetë mbetet `undefined`, pasi ne nuk kthejmë ndonjë vlerë nga funksioni `Person`. + +
+
+
+#### Përgjigja: D
+
+Gjatë fazës **capturing** (kapjes), eventi kalon nëpër elementet paraardhëse deri te elementi i synuar. Më pas arrin në elementin **target** (e synuar) dhe fillon **bubbling**.
+
+
+
+
+ +#### Përgjigja: B + +Të gjitha objektet kanë prototipe, me përjashtim të **objektit bazë**. Objekti bazë është objekti i krijuar nga përdoruesi, ose një objekt që krijohet duke përdorur fjalën kyçe "new". Objekti bazë ka qasje në disa metoda dhe veti, të tilla si `.toString`. Kjo është arsyeja pse ju mund të përdorni metoda të integruara të JavaScript! Të gjitha këto metoda janë të disponueshme në prototip. Megjithëse JavaScript nuk mund ta gjejë atë drejtpërdrejt në objektin tuaj, ai zbret në zinxhirin e prototipit dhe e gjen atje, gjë që e bën atë të qasshëm për ju. + +
++ +#### Përgjigja: C + +JavaScript është gjuhë e shkruar në mënyrë dinamike __dynamically typed language__: ne nuk specifikojmë se çfarë tipe janë variablat e caktuara. Vlerat mund të konvertohen automatikisht në një tip tjetër pa e ditur ju dhe ky proces quhet _implicit type coercion_ (shndërrimi i tipit në mënyrë të nënkuptuar). __Coercion__ është shndërrimi nga një tip në një tjetër. + +Në këtë shembull, JavaScript konverton numrin `1` në string, në mënyrë që për funksionin të ketë kuptim dhe të kthejë një vlerë. Përgjatë mbledhjes të një tipi number (`1`) dhe një tipi string (`'2'`), numri trajtohet si string. Ne mund ti bashkojmë stringjet si `"Hello" + "World"`, kështu që ajo që po ndodh këtu është `"1" + "2"` e cila kthen "12"`. + +
++ +#### Përgjigja: C + +**postfiks** operatori unar `++`: + +1. Kthen vlerën (kthen `0`) +2. Rrit vleren (numri tani është `1`) + +**prefiks** operatori unar `++`: + +1. Rrit vlerën (numri tani është `2`) +2. Kthen vlerën (kthen `2`) + +Prandaj rezultati që kthehet është `0 2 2`. + +
++ +#### Përgjigja: B + +Nëse përdorni literale të shabllonit (template literals) të etiketuar, vlera e argumentit të parë është gjithmonë një array vlerash stringu. Argumentet e mbetura marrin vlerat e shprehjeve të vendosura në variablat e dhëna! + +
++ +#### Përgjigja: C + +Kur testojmë barazinë, primitivet krahasohen me _vlerën_ e tyre, ndërsa objektet krahasohen me _referencën_ e tyre. JavaScript kontrollon nëse objektet kanë një referencë në të njëjtin vend në memorie. + +Dy objektet që po krahasojmë nuk e kanë këtë: objekti që kemi vendosur si parametër i referohet një vendndodhjeje të ndryshme në memorie nga objekti që kemi përdorur për të kontrolluar barazinë. + +Kjo tregon pse të dyja: `{ age: 18 } === { age: 18 }` dhe `{ age: 18 } == { age: 18 }` kthen `false`. + +
++ +#### Përgjigja: C + +Parametri "rest" (`...args`) na lejon të "mbledhim" të gjitha argumentet e mbetura në një array. Një array është një objekt, kështu që `typeof args` kthen `“objekt”` + +
++ +#### Përgjigja: C + +Me `"use strict"`, mund të siguroheni se nuk do të deklaroni variabla globale pa qëllim. Ne asnjëherë nuk e kemi deklaruar variablen `age`, dhe pasi ne e përdorim `"use strict"`, do të na kthehet një error reference. Në qoftesë nuk përdorim `"use strict"`, do të kishte funksionuar pasi vetia `age` do të ishte shtuar në objektin global. + +
++ +#### Përgjigja: A + +`eval` vlerëson kodet që i pasohen si string. Nëse është një shprehje, si në këtë rast, ajo vlerëson shprehjen. Shprehja është `10 * 10 + 5`. Kjo kthen numrin '105'. + +
++ +#### Përgjigja: B + +Të dhënat e ruajtura në `sessionStorage` largohen pasi të mbyllet _dritarja_. + +Nëse keni përdorur 'localStorage', të dhënat do të kishin mbetur aty përgjithmonë, përveç nëse për shembull thirret 'localStorage.clear()'. + +
++ +#### Përgjigja: B + +Me fjalën kyçe `var`, mund të deklaroni shumë variabla me të njëjtin emër. Më pas variabla do të mbajë vlerën e fundit të inicializuar në të. + +Ju nuk mund ta bëni këtë me 'let' ose 'const' pasi ato kanë qasje në bllok (block-scoped). + +
++ +#### Përgjigja: C + +Të gjitha çelësat e objektit (përjashto Simbolet) janë stringje në prapavijë, edhe nëse ju vetë nuk e shkruani atë si string. Kjo është arsyeja pse `obj.hasOwnProperty('1')` gjithashtu kthen vlerën true. + +Nuk funksionon në këtë mënyrë për një "set". Nuk ka asnjë `'1'` në set-in tonë: `set.has('1')` kthen `false`. Nëse ka tipin numër `1`, `set.has(1)` kthen `true`. + +
++ +#### Përgjigja: C + +Nëse keni dy çelësa me të njëjtin emër, çelësi do të zëvendësohet. Do të jetë ende në pozitën e parë, por me vlerën e fundit të specifikuar. + +
++ +#### Përgjigja: A + +Konteksti bazë i ekzekutimit është konteksti global i ekzekutimit: është ajo që është e qasshme kudo në kodin tuaj. + +
++ +#### Përgjigja: C + +Deklarata `continue` kalon një iterim nëse një kusht i caktuar kthen `true`. + +
++ +#### Përgjigja: A + +`String` është një konstruktor i integruar, të cilit mund t'i shtojmë veti. Sapo shtuam një metodë në prototipin e saj. Stringjet primitive konvertohen automatikisht në një objekt string, të gjeneruara nga funksioni i prototipit të stringut. Pra, të gjitha vargjet (objektet e stringut) kanë qasje në atë metodë! + +
++ +#### Përgjigja: B + +Çelësat e objekteve konvertohen automatikisht në stringje. Ne po provojmë të vendosim një objekt si çelës për objektin 'a', me vlerën '123'. + +Megjithatë, kur e përdorim "stringify" në një objekt, ai bëhet `"[object Object]"`. Pra, ajo që po themi këtu, është se `a["[object Object]"] = 123`. Pastaj, ne mund të provojmë të bëjmë të njëjtën gjë përsëri. `c` është një objekt tjetër që ne po e "stringify" në mënyrë implicite. Pra, atëherë, `a["[object Object]"] = 456`. + +Pastaj ne e printojmë `a[b]` e cila është `a["[object Object]"]`. We sapo e vendosëm `456` në të, prandaj edhe do të kthejë `456` + +
+
+
+#### Përgjigja: B
+
+Ne kemi një funksion "setTimeout" të cilin e thirrëm së pari. Megjithatë, ai u printua i fundit.
+
+Kjo është për shkak se në browser-a, ne nuk kemi vetëm "runtime" funksionalitet, ne gjithashtu kemi diçka që quhet `WebAPI`. `WebAPI` na jep funksionin `setTimeout` dhe poashtu për shembull DOM.
+
+Pasi _callback_ të vendoset në WebAPI, vetë funksioni "setTimeout" (por jo callback!) del nga pirgu (stack).
+
+
+
+Tani `foo` thirret dhe `"First"` do të printohet.
+
+
+
+`foo` del nga stack, dhe `baz` thirret. `"Third"` do të printohet.
+
+
+
+WebAPI nuk mund të shtojë gjëra në stack sa herë që është gati. Në vend të kësaj, ai vendos callback në diçka që quhet _queue_.
+
+
+
+Këtu fillon të funksionojë event loop. Një **event loop** shikon "stack" dhe "task queue". Nëse "stack" është bosh, ai merr gjënë e parë në radhë dhe e vendos atë në stack.
+
+
+
+`bar` thirret, `"Second"` do të printohet dhe do të largohet nga stack.
+
+
+ +#### Përgjigja: C + +Elementi më thellë i mbivendosur që shkaktoi ngjarjen është objektivi i ngjarjes. Ju mund të ndaloni bubbling me "event.stopPropagation". + +
++ Click here! +
++ +#### Përgjigja: A + +Nëse klikojmë `p`, shohim dy dalje: `p` dhe `div`. Gjatë "event propagation", ekzistojnë 3 faza: kapja, objektivi dhe flluska. Si parazgjedhje, mbajtësit e ngjarjeve (event handlers) ekzekutohen në fazën e flluskimit (përveç nëse e vendosni "useCapture" në "true"). Ai shkon nga elementi më i thellë i mbivendosur jashtë. + +
++ +#### Përgjigja: D + +Në të dy rastet, ne mund të e vendosim objektin si argument varësisht në cilin funksion dëshirojmë të referohemi me fjalën kyçe `this`. Megjithatë, `.call` gjithashtu ekzekutohet menjëherë! + +`.bind.` kthen një _kopje_ të funksionit, por me një kontekst të lidhur! Nuk ekzekutohet menjëherë. + +
++ +#### Përgjigja: B + +Funksioni `sayHi` kthen vlerën e kthyer të shprehjes së funksionit të thirrur menjëherë (IIFE). Ky funksion ktheu `0`, që është i tipit `“numër”`. + +FYI: `typeof` mund të kthejë listën e mëposhtme të vlerave: `undefined`, `boolean`, `number`, `bigint`, `string`, `symbol`, `function` dhe `object`. Vini re se `typeof null` kthen `“object”`. + +
++ +#### Përgjigja: A + +Ekzistojnë këto 8 vlera të cilat paraqesin false: + +- `undefined` +- `null` +- `NaN` +- `false` +- `''` (string i zbrazët) +- `0` +- `-0` +- `0n` (BigInt(0)) + +Konstruktorët e funksioneve, si `new Number` dhe `new Boolean` kthejnë vlerë të vërtetë (truthy). + +
++ +#### Përgjigja: B + +`typeof 1` kthen `"number"`. +`typeof "number"` kthen `"string"` + +
++ +#### Përgjigja: C + +Kur inicializoni një vlerë për një element të vargut (array) i cili e kalon gjatësinë e tij, Javascript-i krijon diçka që quhet "empty slots (vende të zbrazëta)". Këto realisht e kanë vlerën `undefined`, por ju do të shihni diçka si: + +`[1, 2, 3, empty x 7, 11]` + +varësisht ku e ekzekutoni kodin tuaj (dallon për çdo browser, node, etj.) + +
++ +#### Përgjigja: A + +Blloku `catch` merr argumentin `x`. Kjo nuk është e njëjta `x` si variabla kur ne japim argumente. Variabla `x` (në bllokun `catch`) ka shtrirje blloku (është block-scoped). + +Më vonë, ne e inicializojmë këtë variabël me shtrirje blloku të barabartë me `1` dhe inicializojmë vlerën e ndryshores `y`. Tani, ne printojmë ndryshoren me shtrirje blloku `x`, e cila është e barabartë me `1`. + +Jashtë bllokut `catch`, `x` është ende `undefined`, dhe `y` është `2`. Kur dëshirojmë të bëjmë `console.log(x)` jashtë bllokut `catch`, do të kthejë `undefined`, dhe `y` kthen `2`. + +
++ +#### Përgjigja: A + +JavaScript ka vetëm tipe primitive dhe objekte. + +Tipet primitive janë `boolean`, `null`, `undefined`, `bigint`, `number`, `string`, dhe `symbol`. + +Ajo që e dallon një tip primitiv nga një objekt është se primitivët nuk kanë asnjë veti ose metodë; megjithatë, do të vini re se `foo.toUpperCase()` vlerësohet në `'FOO'` dhe nuk rezulton në `TypeError`. Kjo ndodh sepse kur përpiqeni të qasni një veçori ose metodë në një primitive si një string, JavaScript do të mbështjellë në mënyrë implicite tipin primitiv duke përdorur një nga klasat e mbështjellësit, d.m.th. `String`, dhe më pas do ta heqë menjëherë mbështjellësin pasi të vlerësohet shprehja. Të gjithë primitivët përveç `null` dhe `undefined` e shfaqin këtë sjellje. + +
++ +#### Përgjigja: C + +`[1, 2]` është vlera jonë fillestare. Kjo është vlera me të cilën fillojmë, dhe vlera e parë e `acc`. Gjatë iterimit të parë, `acc` është `[1,2]`, dhe `cur` është `[0, 1]`. Ne i bashkojmë ato dhe kjo rezulton në `[1, 2, 0, 1]`. + +Pastaj, `[1, 2, 0, 1]` është `acc` dhe `[2, 3]` është `cur`. I bashkojmë ato dhe marrim `[1, 2, 0, 1, 2, 3]` + +
++ +#### Përgjigja: B + +`null` është false. `!null` kthen `true`. `!true` kthen `false`. + +`""` është false. `!""` kthen `true`. `!true` kthen `false`. + +`1` është e vërtetë (truthy). `!1` kthen `false`. `!false` kthen `true`. + +
++ +#### Përgjigja: A + +Kthen një id unike. Kjo id mund të përdoret për të pastruar intervalin me funksionin `clearInterval()`. + +
++ +#### Përgjigja: A + +Stringu është i iterueshëm. Operatori i përhapjes (spread operator) iteron çdo karakter të një elementi të iterueshëm në një element (në këtë rast array []). + +
++ +#### Përgjigja: C + +Funksionet e rregullta nuk mund të ndalen në mes të ekzekutimit pas thirrjes. Sidoqoftë, funksioni i gjeneratorit (generator function) mund të "ndalohet" në mes të rrugës dhe më vonë të vazhdojë nga vendi ku ndaloi. Sa herë që një funksion gjenerues ndeshet me fjalën kyçe `yield`, funksioni jep vlerën e specifikuar pas saj. Vini re se funksioni i gjeneratorit në atë rast nuk e _kthen_ (return) vlerën, por e _jep_ (yield) vlerën. + +Së pari, ne inicializojmë funksionin e gjeneratorit me `i` të barabartë me `10`. Ne thërrasim funksionin e gjeneratorit duke përdorur metodën `next()`. Herën e parë që thërrasim funksionin e gjeneratorit, `i` është i barabartë me `10`. Ai ndeshet me fjalën kyçe të parë `yield`: jep vlerën e `i`. Gjeneratori tani është `në pauzë` dhe `10` regjistrohet. + +Pastaj, ne e thirrim funksionin përsëri me metodën `next()`. Fillon dhe vazhdon aty ku ka ndaluar më parë, ende me `i` të barabartë me `10`. Tani, ai ndeshet me fjalën kyçe tjetër "yield" dhe jep `i * 2`. `i` është e barabartë me `10`, kështu që kthen `10 * 2`, që është `20`. Kjo rezulton në `10, 20`. + +
++ +#### Përgjigja: B + +Kur i kalojmë premtime (promises) të shumta metodës `Promise.race`, ajo zgjidh/refuzon premtimin _e parë_ që do të zgjidhet/refuzohet. Me metodën `setTimeout`, kalojmë një kohëmatës: 500 ms për premtimin e parë (`firstPromise`) dhe 100 ms për premtimin e dytë (`secondPromise`). Kjo do të thotë se `secondPromise`zgjidhet fillimisht me vlerën `'two'`. `res` tani mban vlerën e `'two'`, e cila printohet. + +
+
+
+#### Përgjigja: D
+
+Së pari, deklarojmë variablën `person` me vlerën e objektit i cili e ka vetinë `name`.
+
+
+
+Më pas, ne deklarojmë një variabël të quajtur `members`. E caktojmë elementin e parë të atij array të barabartë me vlerën e variablës `person`. Objektet ndërveprojnë me _referencë_ kur i vendosin të barabartë me njëri-tjetrin. Kur caktoni një referencë nga një ndryshore në tjetrën, ju bëni një _kopje_ të asaj reference. (vini re se ato nuk kanë të njëjtën referencë!)
+
+
+
+Pastaj e ri-inicializojmë variablën `person` të barabartë me `null`
+
+
+
+Ne po e modifikojmë vetëm vlerën e variblës `person`, dhe jo të elementit të parë ne array, meqenëse ai element ka një referencë të ndryshme (të kopjuar) për objektin. Elementi i parë në `members` ende mban referencën e tij ndaj objektit origjinal. Kur printojmë array `members`, elementi i parë ende mban vlerën e objektit, i cili printohet.
+
+
+ +#### Përgjigja: B + +Me unazën `for-in`, ne mund të iterojmë përgjatë çelësave të objektit, në këtë rast `name` dhe `age`. Në prapavijë, çelësat e objektit janë stringje (në qoftesë nuk janë Symbol). Në çdo unazë, ne vendosim vlerën e `item` të barabartë me çelësin aktual në të cilin po iterohet. Së pari, `item` është i barabartë me `name`, dhe printohet. Pastaj, `item` është e barabartë me `age` dhe printohet. + +
++ +#### Përgjigja: B + +Radha e veprimeve matematikore të operatorit është rendi në të cilin përpiluesi (kompajleri) vlerëson shprehjet, qoftë nga e majta në të djathtë ose nga e djathta në të majtë. Kjo ndodh vetëm nëse të gjithë operatorët kanë përparësinë _të njejtë_. Ne kemi vetëm një lloj operatori: `+`. Për më tepër, radha e veprimeve matematikore është nga e majta në të djathtë. + +`3 + 4` llogaritet së pari. Kjo rezulton në numrin `7`. + +`7 + '5'` rezulton në `"75"` për shkak të shndërrimit të tipit (coercion). JavaScript-i e konverton numrin `7` ne një string, shiko pyetjen 15. Ne mund të i bashkojmë dy stringje duke e përdorur operatorin `+`. `"7"` + `"5"` rezulton në `"75"` + +
++ +#### Përgjigja: C + +Kthehen vetëm numrat e parë në string. Bazuar në _radix (bazë)_ (argumenti i dytë për të specifikuar se në çfarë tipi duam ta parsojmë atë: bazën 10, heksadecimal, oktal, binar, etj.), `parseInt` kontrollon nëse karakteret në string janë të vlefshme. Pasi të ndeshet me një karakter që nuk është një numër i vlefshëm në bazë, ai ndalon parsimin dhe injoron karakteret e ardhshme. + +`*` nuk është numër valid. Parson vetëm `"7"` në decimal `7`. `num` tani mban vlerën `7`. + +
++ +#### Përgjigja: C + +Kur iterojmë (map-ojmë) një array, vlera e `num` është e barabartë me elementin që është duke u iteruar aktualisht. Në këtë rast, elementet janë numra, kështu që kushti i deklaratës if `typeof num === "number"` kthen `true`. Funksioni map krijon një grup të ri dhe fut vlerat e kthyera nga funksioni. + +Megjithatë, ne nuk kthejmë një vlerë. Kur nuk kthejmë një vlerë nga funksioni, funksioni kthen `undefined`. Për çdo element në array, blloku i funksionit thirret, kështu që për secilin element ne kthejmë `undefined`. + +
++ +#### Përgjigja: A + +Argumentet kalohen si _vlerë_, përveç nëse vlera e tyre është një objekt, atëherë ato kalohen si _referencë_. `birthYear` kalohet sipas vlerës, pasi është një string, jo një objekt. Kur kalojmë argumente sipas vlerës, krijohet një _kopje_ e asaj vlere (shih pyetjen 46). + +Variabla `birthYear` ka referencë në vlerën `“1997”`. Argumenti `year` gjithashtu ka referencë në vlerën `"1997"`, por nuk është e njëjta vlerë si `birthYear`. Kur përditësojmë vlerën e `year` duke vendosur `year` të barabartë me `"1998"`, ne po përditësojmë vetëm vlerën e `year`. `birthYear` është ende i barabartë me `"1997"`. + +Vlera e `person` është objekt. Argumenti `member` ka referencë (të kopjuar) për objektin e njejtë. Kur modifikojmë një veti të objektit që `member` ka një referencë, vlera e `person` gjithashtu do të modifikohet, pasi të dy kanë një referencë për të njëjtin objekt. Vetia `name` e `person` tani është e barabartë me vlerën `"Lydia"`. + +
++ +#### Përgjigja: D + +Me deklaratën `throw`, ne mund të krijojmë gabime (error) të personalizuara. Me këtë deklaratë, ju mund të bëni përjashtime. Një përjashtim mund të jetë një string, një numër, një boolean ose një objekt. Në këtë rast, përjashtimi ynë është stringy `'Hello world!'`. + +Me deklaratën `catch`, ne mund të specifikojmë se çfarë të bëjmë nëse një përjashtim hidhet në bllokun `try`. Bëhet një përjashtim: stringu `'Hello world!'`. `e` tani është e barabartë me atë string, të cilin e regjistrojmë. Kjo rezulton në `'Oh an error: Hello world!'`. + +
++ +#### Përgjigja: B + +Kur një konstruktor thirret me fjalën kyçe `new`, ai krijon një objekt dhe vendos fjalën kyçe `this` për t'iu referuar atij objekti. Si parazgjedhje, nëse konstruktori nuk kthen asgjë në mënyrë të qartë, ai do të kthejë objektin e krijuar së fundi. + +Në këtë rast, konstruktori `Car` kthen në mënyrë eksplicite një objekt të ri me `make` të vendosur në `"Maserati"`, i cili mbishkruan sjelljen e paracaktuar. Prandaj, kur thirret `New Car()`, objekti i kthyer i caktohet `myCar`, duke rezultuar në daljen `“Maserati”` kur qaset `myCar.make`. + +
++ +#### Përgjigja: A + +`let x = (y = 10);` është shkurtesë për: + +```javascript +y = 10; +let x = y; +``` + +Kur e vendosim `y` të barabartë me `10`, ne në të vërtetë e shtojmë vetinë `y` në objektin global (`window` në browser, `global` në Node). Në browser, `window.y` është tani e barabartë me `10`. + +Më pas, ne deklarojmë variablën `x` me vlerën `y`, e cila është `10`. Variablat e deklaruara me fjalën kyçe 'let' janë _block scoped_, ato përcaktohen vetëm brenda bllokut ku janë deklaruar; shprehja e funksionit të thirrur menjëherë (IIFE) në këtë rast. Kur përdorim operatorin `typeof`, operandi `x` nuk është i përcaktuar: ne po përpiqemi të qasim `x` jashtë bllokut ku ai është deklaruar. Kjo do të thotë se `x` nuk është përcaktuar. Vlerat e të cilave nuk u është caktuar një vlerë ose nuk janë deklaruar janë të tipit `"undefined"`. `console.log(typeof x)` kthen `"undefined"`. + +Megjithatë, ne krijuam një variabël globale `y` kur vendosëm `y` të barabartë me `10`. Kjo vlerë është e qasshme kudo në kodin tonë. `y` është përcaktuar dhe mban vlerën e tipit `"number"`. `console.log(typeof y)` kthen `"number"`. + +
++ +#### Përgjigja: A + +Ne mund të fshijmë veti nga objektet duke përdorur fjalën kyçe `delete`, gjithashtu në prototip. Duke fshirë një veti në prototip, ajo nuk është më e qasshme në zinxhirin e prototipit. Në këtë rast, funksioni `bark` nuk është më i qasshëm në prototip pas `delete Dog.prototype.bark`, por ne ende provojmë të i qasemi. + +Kur përpiqemi të thërrasim diçka që nuk është funksion, hidhet një 'TypeError'. Në këtë rast `TypeError: pet.bark is not a function`, pasi `pet.bark` është `undefined`. + +
++ +#### Përgjigja: D + +Objekti `Set` është një koleksion vlerash _unike_: një vlerë mund të paraqitet vetëm një herë në një grup (set). + +Vendosëm `[1, 1, 2, 3, 4]` me një vlerë dublikate `1`. Meqenëse nuk mund të kemi dy vlera të njëjta në një "set", njëra prej tyre largohet. Kjo rezulton në `{1, 2, 3, 4}`. + +
++ +#### Përgjigja: C + +Një modul i importuar mund vetëm të i lexohet vlera (_read-only_): nuk mund të modifikohet. Vetëm moduli i cili i importon ato mund të ndërrojë atë vlerë. + +Kur tentojmë të rrisim vlerën e `myCounter`, do të marrim një error: `myCounter` mundet vetëm të lexohet dhe nuk mund të modifikohet. + +
++ +#### Përgjigja: A + +Operatori "delete" kthen një vlerë booleane: `true` në fshirje të suksesshme, përndryshe do të kthejë `false`. Megjithatë, variablat e deklaruara me fjalën kyçe `var`, `const` ose `let` nuk mund të fshihen duke përdorur operatorin `delete`. + +Variabla `name` u deklarua me fjalën kyçe `const`, kështu që fshirja e saj nuk ishte e suksesshme: u kthye `false`. Kur vendosëm `age` të barabartë me `21`, ne në fakt shtuam një veti të quajtur `age` në objektin global. Ju mund të fshini me sukses vetitë nga objektet në këtë mënyrë, gjithashtu edhe objektin global, kështu që `delete age` kthen `true`. + +
+
+
+#### Përgjigja: C
+
+Ne mund të targetojmë vlerat nga vargjet ose vetitë nga objektet përmes destrukturimit. Për shembull:
+
+```javascript
+[a, b] = [1, 2];
+```
+
+
+
+Vlera `a` tani është `1`, dhe vlera `b` tani është `2`. Çfarë ne bëmë në të vërtetë në pyetje, është:
+
+```javascript
+[y] = [1, 2, 3, 4, 5];
+```
+
+
+
+Kjo do të thotë se vlera e `y` është e barabartë me vlerën e parë në array, që është numri `1`. Kur printojmë `y`, do të kthehet `1`.
+
+
+ +#### Përgjigja: B + +Është e mundur të kombinohen objektet duke përdorur operatorin e përhapjes (spread) `...`. Kjo ju lejon të krijoni kopje të çifteve çelës/vlerë të një objekti dhe t'i shtoni ato në një objekt tjetër. Në këtë rast, ne krijojmë kopje të objektit `user` dhe i shtojmë ato në objektin `admin`. Objekti `admin` tani përmban çiftet e kopjuara të çelësit/vlerës, që rezulton në `{ admin: true, emri: "Lydia", mosha: 21 }`. + +
++ +#### Përgjigja: B + +Me metodën `defineProperty`, ne mund të shtojmë veti të reja në një objekt, ose të modifikojmë ato ekzistuese. Kur shtojmë një veti në një objekt duke përdorur metodën `defineProperty`, ato janë si parazgjedhje _not enumerable_. Metoda `Object.keys` kthen të gjithë emrat e vetive _numerable_ nga një objekt, në këtë rast vetëm `"name"`. + +Vetitë e shtuara duke përdorur metodën `defineProperty` janë të pandryshueshme si parazgjedhje. Ju mund ta mbishkruani këtë sjellje duke përdorur veçoritë `writable`, `configurable` dhe `enumerable`. Në këtë mënyrë, metoda `defineProperty` ju jep shumë më tepër kontroll mbi vetitë që po i shtoni një objekti. + +
++ +#### Përgjigja: A + +Argumenti i dytë i "JSON.stringify" është _zëvendësuesi_. Zëvendësuesi mund të jetë ose një funksion ose një array, dhe ju lejon të kontrolloni se çfarë dhe si duhet të konvertohet një vlerë e JavaScript në JSON string. + +Nëse zëvendësuesi është një _array_, vetëm emrat e vetive të përfshira në array do të shtohen në stringun JSON. Në këtë rast, përfshihen vetëm vetitë me emrat `"level"` dhe `"health"`, përjashtohet `"username"`. `data` tani është e barabartë me `"{"level":19, "health":90}"`. + +Nëse zëvendësuesi është një _funksion_, ky funksion thirret në çdo veti në objektin që po e përdorni metodën 'stringify'. Vlera e kthyer nga ky funksion do të jetë vlera e vetive kur të shtohet në vargun JSON. Nëse vlera është `undefined`, kjo veti përjashtohet nga vargu JSON. + +
++ +#### Përgjigja: A + +Operatori unar `++` fillimisht kthen vlerën e operandit, pastaj e rrit vlerën e tij. Vlera e `num1` është `10`, meqenëse funksioni `increaseNumber` fillimisht kthen vlerën e `num`, e cila është `10`, dhe vetëm pastaj e rrit vlerën e `num`. + +`num2` është `10`, pasi ne e kaluam `num1` si argument tek `increasePassedNumber`. `number` është i barabartë me `10`(vlera e `num1`). Përsëri, operatori unar `++` _së pari kthen_ vlerën e operandit, dhe pastaj rrit vlerën e tij. Vlera e `number` është `10`, kështu që `num2` është e barabartë me `10`. + +
++ +#### Përgjigja: C + +Në ES6, ne mund të inicializojmë parametrat me një vlerë të paracaktuar (default). Vlera e parametrit do të jetë vlera e paracaktuar, nëse asnjë vlerë tjetër nuk i është kaluar funksionit, ose nëse vlera e parametrit është `"undefined"`. Në këtë rast, ne i shpërndajmë vetitë e objektit `value` në një objekt të ri, kështu që `x` ka vlerën e paracaktuar të `{ number: 10 }`. + +Argumenti i paracaktuar vlerësohet (llogaritet) në _kohën e thirrjes_! Sa herë që thërrasim funksionin, krijohet një objekt i ri. Ne e thërrasim funksionin `multiply` dy herët e para pa kaluar vlerën: `x` ka vlerën e paracaktuar të `{ number: 10 }`. Më pas printojmë vlerën e shumëzuar të atij numri, që është `20`. + +Herën e tretë që thërrasim funksionin `multiply`, kalojmë një argument: objektin e quajtur `value`. Operatori `*=` është në fakt shkurtesë për `x.number = x.number * 2`: ne e modifikojmë vlerën e `x.number` dhe printojmë vlerën e shumëzuar `20`. + +Herën e katërt, ne e kalojmë përsëri objektin `value`. `x.number` është modifikuar më parë në `20`, kështu që `x.number *= 2` printon `40`. + +
++ +#### Përgjigja: D + +Argumenti i parë që merr metoda `reduce` është _akumulatori_, në këtë rast `x`. Argumenti i dytë është _vlera aktuale_, `y`. Me metodën e reduktimit, ne ekzekutojmë një funksion të kthimit (callback) në çdo element në array, i cili përfundimisht mund të rezultojë në një vlerë të vetme. + +Në këtë shembull, ne nuk jemi duke kthyer ndonjë vlerë, jemi vetëm duke printuar vlerat e akumulatorit dhe vlerën aktuale. + +Vlera e akumulatorit është e barabartë me vlerën e kthyer më parë të funksionit të kthimit (callback). Nëse nuk e kaloni argumentin opsional `initialValue` në metodën `reduce`, akumuluesi është i barabartë me elementin e parë në thirrjen e parë. + +Në thirrjen e parë, akumuluesi (`x`) është `1`, dhe vlera aktuale (`y`) është `2`. Ne nuk kthehemi nga callback, ne printojmë akumuluesin dhe vlerën aktuale: `1` dhe `2` printohen. + +Nëse nuk ktheni një vlerë nga një funksion, ai kthen `undefined`. Në thirrjen tjetër, akumuluesi është `undefined` dhe vlera aktuale është `3`. `undefined` dhe `3` printohet. + +Në thirrjen e katërt, ne përsëri nuk kthehemi nga callback. Akumulatori është përsëri `undefined` dhe vlera aktuale është `4`. `undefined` dhe `4` printohen. + +
++ +#### Përgjigja: B + +Në një klasë të derivuar, ju nuk mund të përdorni fjalën kyçe `this` përpara se të e thirrni `super`. Nëse provoni ta bëni këtë, do të jap `ReferenceError`: 1 dhe 4 do të hedhin një gabim referimi. + +Me fjalën kyçe `super`, ne e thërrasim konstruktorin e asaj klase mëmë me argumentet e dhëna. Konstruktori i prindit merr argumentin `name`, kështu që ne duhet të kalojmë `name` në `super`. + +Klasa `Labrador` merr dy argumente, `name` meqenëse trashëgon klasën 'Dog', dhe `size` si një veti shtesë në klasën `Labrador`. Ata të dy duhet t'i kalojnë konstruktorit në `Labrador`, i cili implementohet saktë duke përdorur konstruktorin 2. + +
++ +#### Përgjigja: B + +Me fjalën kyçe `import`, të gjitha modulet e importuara parsohen fillimisht (_para-parsed_). Kjo do të thotë që modulet e importuara ekzekutohen _të parat_, kodi në file që importon modulin ekzekutohet _më pas_. + +Ky është një dallimi në mes `require()` në CommonJS dhe `import`! Me `require()`, mund të ngarkoni varësitë sipas kërkesës gjatë ekzekutimit të kodit. Nëse do të kishim përdorur `require` në vend të `import`, `running index.js`, `running sum.js`, `3` do të ishte printuar në tastierë. + +
++ +#### Përgjigja: A + +Çdo Symbol është tërësisht unik. Arsyeja e jepjes të argumentit në Symbol është të i jap përshkrim Symbol. Vlera e Symbol nuk është e varur nga argumenti i cili i ipet. Meqenëse po testojmë barazueshmërinë, ne jemi duke krijuar dy Symbol tërësisht të reja: `Symbol('foo')` i parë dhe `Symbol('foo)` i dytë. Të dy janë vlera unike dhe jo të barabarta me njëra tjetrën, `Symbol('foo') === Symbol('foo')` kthen `false`. + +
++ +#### Përgjigja: C + +Me metodën `padStart`, mund të shtojmë mbushje (padding) në fillim të një stringu. Vlera e kaluar në këtë metodë është gjatësia totale e stringut së bashku me mbushjen. Vargu "Lydia Hallie" ka një gjatësi prej `12` karakteresh. `name.padStart(13)` vendos 1 hapësirë në fillim të vargut, sepse 12 + 1 është 13. + +Nëse argumenti i kaluar në metodën `padStart` është më i vogël se gjatësia e array, nuk do të shtohet asnjë mbushje. + +
++ +#### Përgjigja: A + +Me operatorin `+`, ju mund të bashkoni vargjet. Në këtë rast, ne po bashkojmë stringun `"🥑"` me stringun `"💻"`, duke rezultuar në `"🥑💻"`. + +
++ +#### Përgjigja: C + +Një funksion gjenerues (generator function) "pauzon" ekzekutimin e tij kur sheh fjalën kyçe `yield`. Së pari, duhet ta lëmë funksionin të japë vargun "A ju pëlqen JavaScript?", i cili mund të bëhet duke thirrur `game.next().value`. + +Çdo rresht ekzekutohet derisa të gjejë fjalën kyçe të parë "yield". Ekziston një fjalë kyçe `yield` në rreshtin e parë brenda funksionit: ekzekutimi ndalon me yield-in e parë! _Kjo do të thotë se variabla `Përgjigja` nuk është përcaktuar ende!_ + +Kur e thërrasim `game.next("Po").value`, `yield` i mëparshëm zëvendësohet me vlerën e parametrave të kaluar në funksionin `next()`, `"Yes"` në këtë rast. Vlera e ndryshores `Përgjigja` tani është e barabartë me `"Yes"`. Kushti i deklaratës if kthehet `false`, dhe `JavaScript loves you back ❤️` printohet. + +
++ +#### Përgjigja: C + +`String.raw` kthen një varg ku karakteret speciale (`\n`, `\v`, `\t` etj.) injorohen! Vizat e pasme mund të jenë një problem pasi mund të përfundoni me diçka si: + +`const path = `C:\Documents\Projects\table.html`` + +E cila do të rezultonte në: + +`"C:DocumentsProjects able.html"` + +Me `String.raw`, vetëm do e injoronte karakterin special dhe do të printonte: + +`C:\Documents\Projects\table.html` + +Në këtë rast, `Hello\nworld` do të printohet. + +
++ +#### Përgjigja: C + +Një funksion asinkron gjithmonë kthen një "promise". `await` duhet të pres për funksionin "promise" te zgjidhjet: një "promise" në pritje do të kthehet kur e thirrim `getData()` në mënyrë që të vendosim `data` në të. + +Nëse do të dëshironim të kemi qasje në vlerën e zgjidhur `"I made it"` do të kishim përdorur metodën `.then()` në `data`: + +`data.then(res => console.log(res))` + +Kjo do të printonte `"I made it!"` + +
++ +#### Përgjigja: B + +Metoda `.push()` kthen _gjatësinë_ e vargut "array" të ri! Më parë, array përmbante një element (stringun `"banana"`) dhe kishte gjatësinë `1`. Pasi shtuam stringun `"apple"` në array, ai do të përmbajë dy elemente dhe do të ketë gjatësinë `2`. Kjo kthehet nga funksioni `addToList`. + +Metoda `push` modifikon array origjinal. Në qoftëse ju dëshironi të ktheni _array_ nga funksioni në vend të _gjatësisë së vargut_, ateherë ju duhet të ktheni `list` pasi e vendosni `item` në të. + +
++ +#### Përgjigja: B + +`Object.freeze` e bën të pamundur shtimin, largimin ose modifikimin e vetive në një objekt (përveç nëse vlera e një vetie është një objekt tjetër). + +Kur krijojmë ndryshoren `shape` dhe e vendosim të barabartë me objektin e ngrirë `box`, `shape` i referohet gjithashtu një objekti të ngrirë. Ju mund të kontrolloni nëse një objekt është i ngrirë duke përdorur `Object.isFrozen`. Në këtë rast, `Object.isFrozen(shape)` do të kthehej e vërtetë, pasi variabla `shape` ka një referencë për një objekt të ngrirë. + +Meqenëse `shape` është e ngrirë dhe meqenëse vlera e `x` nuk është një objekt, ne nuk mund të modifikojmë vetinë `x`. `x` është ende e barabartë me `10` dhe `{ x: 10, y: 20 }` do të printohet. + +
++ +#### Përgjigja: D + +Duke përdorur [sintaksen e funksioneve destruktuese](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) ne mund të targetojmë vlerat nga vargjet, ose vetitë nga objektet, në variabla të veçanta: + +```javascript +const { firstName } = { firstName: 'Lydia' }; +// versioni i ES5: +// var firstName = { firstName: 'Lydia' }.firstName; + +console.log(firstName); // "Lydia" +``` + +Gjithashtu, një veti mund të targetohet nga një objekt dhe t'i caktohet një variableje me një emër të ndryshëm nga vetia e objektit: + +```javascript +const { firstName: myName } = { firstName: 'Lydia' }; +// versioni i ES5: +// var myName = { firstName: 'Lydia' }.firstName; + +console.log(myName); // "Lydia" +console.log(firstName); // Uncaught ReferenceError: firstName is not defined +``` + +Prandaj, `firstName` nuk ekziston si variabël, kështu që tentimi për të qasur vlerën e saj do të ngrejë një `ReferenceError`. + +**Shënim:** Kujdes nga vetitë e `global scope`: + +```javascript +const { name: myName } = { name: 'Lydia' }; + +console.log(myName); // "lydia" +console.log(name); // "" ----- Browser psh. Chrome +console.log(name); // ReferenceError: name is not defined ----- NodeJS + +``` + +Kurdo që JavaScript nuk mundet të gjejë një varibël në _current scope_, ngrihet në [Scope chain](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch3.md) dhe kërkon për të dhe në qoftëse e arrin nivelin më të lartë të shtrirjes (the top-level scope), të quajtur __Global scope__, dhe ende nuk e gjen do të ngrejë `ReferenceError`. + +- Në __Browsers__ si _Chrome_, `name` është _vetia e shtrirjes globale e vjetëruar_. Në këtë shembull, kodi funksionon brenda _global scope_ dhe nuk ka asnjë variabël lokale të përcaktuar nga përdoruesi për `name`, prandaj ai kërkon _variables/properties_ të paracaktuara në shtrirjen globale, në këtë rast shfletuesve, ai kërkon përmes objektit `window`, dhe do të nxjerrë vlerën [window.name](https://developer.mozilla.org/en-US/docs/Web/API/Window/name) e cila është e barabartë me një varg __bosh__. +- Në __NodeJS__, nuk ka një veçori të tillë në objektin `global`, kështu që përpjekja për të iu qasur një variable joekzistente do të ngrejë një [ReferenceError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined). + +
++ +#### Përgjigja: A + +Një funksion është gjithmonë funksion i pastër nëse sa herë që i kalojmë argumente të njëjta gjithmonë kthen rezultatin e njëjtë. + +Funksioni `sum` _gjithmonë_ kthen të njëjtin rezultat. Nëse i kalojmë `1` dhe `2`, gjithmonë do të kthejë `3` pa ndonjë efekt anësorë. Nëse i kalojmë `5` dhe `10`, gjithmonë do të kthejë `15`, e kështu me radhë. Ky është definicioni i një funksioni të pastër. + +
++ +#### Përgjigja: C + +Funksioni `add` është një funksion _memoized_. Me memoizim, ne mund të ruajmë rezultatet e një funksioni në mënyrë që të përshpejtojmë ekzekutimin e tij. Në këtë rast, ne krijojmë një objekt `cache` që ruan vlerat e kthyera më parë. + +Nëse e thirrim sërish funksionin `addFunction` me të njëjtin argument, ai fillimisht kontrollon nëse e ka marrë tashmë atë vlerë në cache-in e tij. Nëse është kështu, vlera e caches do të kthehet, e cila kursen kohën e ekzekutimit. Përndryshe, nëse nuk është i ruajtur në memorie, ai do të llogarisë vlerën dhe do ta ruajë atë më pas. + +Ne e thirrim funksionin `addFunction` tre herë me të njëjtën vlerë: në thirrjen e parë, vlera e funksionit kur `num`" është e barabartë me `10` nuk është ruajtur ende në memorie. Kushtëzimi if `num in cache` kthen `false`, dhe blloku else ekzekutohet: `Calculated! 20` printohet dhe vlera e rezultatit i shtohet objektit të cache-it. `cache` tani duket si `{ 10: 20 }`. + +Herën e dytë, objekti `cache` përmban vlerën që kthehet për `10`. Kushtëzimi if `num in cache` kthen `true`, dhe `'From cache! 20'` printohet. + +Herën e tretë, ne kalojmë `5 * 2` te funksioni i cili llogaritet si `10`. Objekti `cache` përmban vlerën që kthehet për `10`. Kushtëzimi if `num in cache` kthen `true`, dhe `'From cache! 20' printohet. + +
++ +#### Përgjigja: A + +Me unazën _for-in_, ne mund të iterojmë në vetitë _e numërueshme_. Në një array, vetitë e numërueshmë janë "çelësat" e elementeve të array, të cilët janë në të vërtetë indekset e tij. Mund të shikoni array si: + +`{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}` + +Ku çelësat janë vetitë e numërueshme. `0` `1` `2` `3` printohet. + +Me unazën _for-of_, ne mund të iterojmë mbi __iterables__. Një array është një "iterable". Kur iterojmë mbi array, variabla "item" është e barabartë me elementin mbi të cilin po iterojmë aktualisht, "☕"` `"💻"` `"🍷"` `"🍫"` printohet. + +
++ +#### Përgjigja: C + +Elementet e array mund të mbajnë çfarë vlere. Numra, stringje, objekte, array të tjerë, null, vlera boolean-e, undefined, dhe shprehje të tjera si data, funksione dhe kalkulime. + +Elementi do të jetë i barabartë me vlerën e kthyer. `1 + 2` kthen `3`, `1 * 2` kthen `2` dhe `1 / 2` kthen `0.5`. + +
++ +#### Përgjigja: B + +Paraprakisht, argumentet kane vlerën `undefined`, përveç në qoftëse ndonjë vlerë i kalohet në funksion. Në këtë rast, ne nuk e kaluam ndonjë vlerë për argumentin `name`. `name` është e barabartë me `undefined` e cila edhe printohet. + +Në ES6, ne mund të mbishkruajmë këtë vlerë paraprake `undefined` me parametër të definuar paraprakisht. Për shembull: + +`function sayHi(name = "Lydia") { ... }` + +Në këtë rast, nëse ne nuk kalojmë ndonjë vlerë ose e kalojmë `undefined`, `name` do të ishte gjithmonë i barabartë me stringun `Lydia`. + +
++ +#### Përgjigja: B + +Vlera e fjalës kyçe `this` varet nga vendi ku e përdorni. Në një __metodë__, si metoda `getStatus`, fjala kyçe `this` i referohet _objektit që i përket metoda_. Metoda i përket objektit `data`, kështu që `this` i referohet objektit `data`. Kur printojmë `this.status`, vetia `status` në objektin `data` printohet, që është `"🥑"`. + +Me metodën `call`, ne mund të ndryshojmë objektin të cilit i referohet fjala kyçe `this`. Në __funksione__, fjala kyçe `this` i referohet _objektit të cilit i përket funksioni_. Ne deklaruam funksionin `setTimeout` në objektin _global_, kështu që brenda funksionit `setTimeout`, fjala kyçe `this` i referohet objektit _global_. Në objektin global, ekziston një variabël e quajtur _status_ me vlerën `"😎"`. Kur printoni `this.status`, `"😎"` printohet. + +
++ +#### Përgjigja: A + +0Vendosëm variablën `city` të barabartë me vlerën e vetisë të quajtur `city` në objektin `person.`. Në objekt nuk ka ndonjë veti e cila quhet `city`, kështu që variabla `city` ka vlerën `undefined`. + +Vini re, ne _nuk_ jemi duke iu referuar objektit `person`! Ne vetëm e vendosëm variablën `city` të barabartë me vlerën aktuale të vetisë `city` në objektin `person`. + +Pastaj, ne vendosëm `city` të barabartë me stringun `"Amsterdam"`. Kjo nuk e ndryshon objektin person: nuk ka ndonjë referencë tek ai objekt. + +Kur printojmë objektin `person`. objekti i pamodifikuar kthehet. + +
++ +#### Përgjigja: C + +Variablat e deklaruara me fjalët kyçe `const` dhe `let` janë të qasshme vetëm në bllokun ku shtrihen (_block-scoped_). Një bllok quhet gjithçka që gjendet brenda kllapave gjarpërore (`{ }`). Në këtë rast, kllapat gjarpërore e deklarimeve if/else. Nuk mund të i referencohemi një variable jashtë bllokut ku është deklaruar, sepse do të ngrihet ReferenceError. + +
++ +#### Përgjigja: C + +Vlera e `res` në `.then` të dytë do të jetë e barabartë me vlerën e kthyer në `.then` paraprak. You mund të bëni `.then`-ë të tjerë si në shembull, ku vlera do të kalohet në trajtuesin tjetër. + +
++ +#### Përgjigja: A + +Me `!!name`, ne vendosim në qoftëse vlera e `name` është e vërtetë osë false. Nëse "name" është e vërtetë, për të cilën duam të testojmë, `!name` kthen `false`. `!false` (e cila është vlera të cilën `!!name` ka) kthen `true`. + +Kur vendosim `hasName` të barabartë me `name`, ju vendosni `hasName` të barabartë me çdo vlerë të cilën e kaloni si arguemnt tek funksioni `getName`, jo vlera boolean-e `true`. + +`new Boolean(true)` kthen një mbështjellës së objektit, jo vetë vlerën boolean-e. + +`name.length` kthen gjatësinë e argumentit të kaluar, jo në qoftëse është `true` ose jo. + +
++ +#### Përgjigja: B + +Në mënyrë që të marrim karakterin në një indeks specifik në string, mund të përdorimin notacionin e kllapave të mëdha "[]". Karakteri i parë në string ka indeksin 0, dhe kështu me rradhë. Në këtë rast, ne duam të marrim elementin me indeks 0, karakterin `"I"`, i cili printohet. + +Vini re se kjo metodë nuk suportohet në IE7 e më poshtë. Në këtë rast përdorni `.charAt()`. + +
++ +#### Përgjigja: B + +Ne mund të përcaktojmë një vlerë paraprakisht të barabartë me ndonjë parametër tjetër të funksionit, përderisa ato janë të deinuara përpara vlerës së paradefinuar. Ne e kalojmë vlerën `10` tek funksioni `sum`. Nëse funksioni `sum` pranon vetëm një argument, do të thotë se vlera për `num2` nuk është kaluar, dhe vlera e `num1` është e barabartë me vlerën `10` e cila ka kaluar si argument në këtë rast. Vlera e paradefinuar e `num2` është vlera e `num1`, e cila është `10`. `num1 + num2` kthen `20`. + +Në qoftëse provoni të vendosni një vlerë të paradefinuar të barabartë me një parametër i cili definohet _pastaj_ (në të djathë), vlera e parametrit nuk do të jetë e inicializuar ende, e cila do të kthejë një error. + +
++ +#### Përgjigja: A + +Me sintaksën `import * as name`, ne importojmë _të gjithë eksportet_ nga fajlli `module.js` në `index.js` si një objekt i ri i cili quhet `data` i cili krijohet. Në `module.js`, gjenden dy eksporta: eksporti i paracaktuar dhe një eksport i emërtuar. Eksporti i paracaktuar është funksion i cili kthen stringun `Hello World`, dhe esksporti i emëruar është variabla e quajtur `name` e cila ka vlerën e stringut `"Lydia"`. + +Objekti `data` ka një veti `default` për eksportin e paracaktuar, vetitë e tjera kanë emrat e eksporteve të emëruara dhe vlerat e tyre korrespoduese. + +
++ +#### Përgjigja: C + +Klasat janë si sintaksë që është krijuar për t'i bërë gjërat më të lehta për t'u lexuar ose për t'u shprehur për funksionet e konstruktorëve. Ekuivante e klasës `Person` si funksion kontruktorë do të ishte: + +```javascript +function Person(name) { + this.name = name; +} +``` + +Thirrja e një konstruktori me `new` rezulton në krijimin e një instance të `Person`, `typeof` do të kthejë `"object"` për një instancë. `typeof member` kthen `"object"`. + +
++ +#### Përgjigja: D + +Metoda `.push` kthen _gjatësinë e re_ të array, jo vetë array! Duke vendosur `newList` të barabartë me `[1, 2, 3].push(4)`, e vendosim `newList` të barabartë me gjatësinë e re të array: `4`. + +Pastaj, ne provojmë të përdorim metodën `.push` në `newList`. Meqenëse `newList` është vlera numerike e `4` ne nuk mund të përdorim metodën `.push`: do të ngrihet TypeError. + +
++ +#### Përgjigja: D + +Funskionet e rregullta, të tillë si funksioni `giveLydiaPizza`, kanë vetinë `prototype`, e cila është një objekt (veti e objektit) me veti `constructor`. Funksionet shigjetë (arrow functions) sidoqoftë, të tilla si funskioni `giveLydiaChocolate`, nuk e kanë këtë veti `prototype`. Kur tentojmë të i qasemi vetisë `prototype` duke pëdorur `giveLydiaChocolate.prototype` do të na kthehet `undefined`. + +
++ +#### Përgjigja: A + +`Object.entries(person)` kthen një array me array të ndërthurur, i cili përmban çelësat dhe objektet: + +`[ [ 'name', 'Lydia' ], [ 'age', 21 ] ]` + +Përdorimi i unazës `for-of`, na mundëson iterimin në secilin element në array, dhe nën array në këtë rast. Ne mund të destrukturojmë nën array menjëherë në unazën for-of, duke përdorur `const [x, y]`. `x` është e barabartë me elementin e parë në nën array, `y` është e barabartë me elementin e dytë në nën array. + +Nën array i parë është `["name", "Lydia"]`, me `x` të barabartë me `"name"`, dhe `y` të barabartë me `"Lydia"`, e cila printohet. Nën array i dytë është `["age", 21 ]`, me `x` të barabartë me `"age"`, dhe `y` të barabartë me `21`, e cila printohet. + +
++ +#### Përgjigja: D + +`...args` është "rest" parametër. Vlera e "rest" parametrit është një array i cili përmban të gjitha argumentet e mbetura, **dhe mund të jetë vetëm parametri i fundit**! Në këtë shembull, "rest" parametri ishte parametri i dytë. Kjo nuk është e mundur, dhe do të ngrisë gabim sintaksorë. + +```javascript +function getItems(fruitList, favoriteFruit, ...args) { + return [...fruitList, ...args, favoriteFruit]; +} + +getItems(['banana', 'apple'], 'pear', 'orange'); +``` + +Shembulli i mësipërm funskionon. Do të kthejë array `[ 'banana', 'apple', 'orange', 'pear' ]` + +
++ +#### Përgjigja: B + +Në JavaScript, nuk e duhet të e shkruajmë pikëpresjen `;` në mënyrë eksplicite, sidoqoftë makina e JavaScript prapë i vendos ato pas deklarimeve. Kjo quhet __Automatic Semicolon Insertion__ (vendosja e pikëpresjes automatikisht). Një deklaratë për shembull mund të jetë variabla, ose fjalët kyçe si `throw`, `return`, `break` etj. + +Në këtë rast, ne shkruajtëm deklaratën `return`, dhe vlerën tjetër `a + b` në rresht të ri. Sidoqoftë, meqenëse është rresht i ri, makina nuk e di se në të vërtetë ajo është vlera që ne po dëshirojmë të kthejmë. Në vend se të e llogarisë në atë mënyrë, në mënyrë automatike vendoset `return`. Kjo mund të shikohet edhe si kjo sintaksë: + +```javascript +return; +a + b; +``` + +Kjo do të thotë se `a + b` nuk arrihet asnjëherë, meqenëse funksioni ndalon ekzekutimin pas fjalës kyçe `return`. Nëse asnjë vlerë nuk kthehet si në këtë rast, funksioni kthen `undefined`. Vini re se nuk ka ndonjë përfshirje automatike pas deklarimit `if/else` + +
++ +#### Përgjigja: B + +Ne mund të iu shoqërojmë klasave konstruktorët e tjerë të klasave/funksioneve. Në këtë rast, ne vendosim `Person` të barabartë me `AnotherPerson`. Emri në këtë konstruktor është `Sarah`, kështu që vetia e emrit në instancën e re `Person`, `member` është `“Sarah”`. + +
++ +#### Përgjigja: D + +Një Symbol nuk është i _numërueshëm_. Metoda Object.keys kthen të gjithë çelësat e _numërueshëm në një objekt. Symbol nuk do të jetë i dukshëm, dhe një array i zbrazët do të kthehet. Kur e printojmë objektin në tërësi, të gjitha vetitë janë të dukshme, edhe ato të cilat nuk janë te numërueshme. + +Kjo është vetëm një nga shumë vetitë e symbol, përveç përfaqësimit të një vlere krejtësisht unike (e cila parandalon konflikt në emërtim të objekteve, për shembull kur punoni me 2 librari që duan të shtojnë vetitë në të njëjtin objekt), ju gjithashtu mund të "fshehni" vetitë e objekteve në këtë mënyrë (edhe pse jo plotësisht. Ju mund t'i qaseni simboleve duke përdorur metodën `Object.getOwnPropertySymbols()`). + +
++ +#### Përgjigja: A + +Funksioni `getList` merr një array si argument. Brenda kllapave të funksionit `getList`, ne e destrukturojmë ketë array në mënyrën e duhur. Kjo mund të shihet edhe si: + +`[x, ...y] = [1, 2, 3, 4]` + +Me "rest" parametrin `...y`, ne i vendosim argumentet "e mbetura" në një array. Argumentet e mbetura janë `2`, `3` dhe `4` në këtë rast. Vlera e `y` është një array, i cili i përmban të gjithë parametrat e mbetur. Vlera e `x` është e barabartë me `1` në këtë rast kur e printojmë `[x, y]`, printohet `[1, [2, 3, 4]]`. + +Funskioni `getUser` merr një objekt. Me funksionet shigjetë (arrow function), ne nuk kemi nevojë të shkruajmë kllapat gjarpërore nëse vetëm dëshirojmë të kthejmë një vlerë. Sidoqoftë, nëse dëshironi që në mënyrë instante të ktheni një objekt nga një arrow funksion, mund të e shkruani brenda kllapave të vogla "()", përndryshe çdo gjë mes dy kllapave do të interpretohet si një deklaratë blloku. Në këtë rast kodi në mes të kllapave nuk është kod valid i JavaScript, kështu që do të ngrihet `SyntaxError`. + +Funskioni i meposhtëm do të kthente një objekt: + +`const getUser = user => ({ name: user.name, age: user.age })` + +
++ +#### Përgjigja: C + +Variabla `name` mban vlerën e një stringu, i cili nuk është funksion, prandaj nuk mund të thirret si i tillë. + +TypeErrors do të ngrihen kur një vlerë nuk është e tipit që pritet. JavaScript pret që `name` të jetë një funksion meqenëse po provojmë të e thirrim atë. Sidoqoftë është një string, prandaj do të marrim TypeError: "name" nuk është një funksion. + +SyntaxErrors do të ngrihen kur ne shënojmë diçka e cila nuk është valide në JavaScript, për shembull kur e shënojmë fjalën `return` si `retrun`. +ReferenceErrors ngrihen kur Javascript-i nuk është në gjendje të gjejë referencë tek një vlerë të cilën ne provojmë të i qasemi. + +
++ +#### Përgjigja: B + +`[]` është vlerë "truthy". Me operatorin `&&`, vlera në anën e djathtë do të kthehet nëse vlera në anën e majtë është vlerë "truthy". Në këtë rast, vlera në anën e majtë `[]` është vlerë "truthy" prandaj `"Im"` do të kthehet. + +`""` është vlerë "falsy". Nësë ana e majtë është falsy, asgjë nuk kthehet. `n't` nuk do të kthehet. + +
++ +#### Përgjigja: C + +Me operatorin `||`, ne mund të kthejmë vlerën e parë "truthy" të operandit. Nëse të gjitha vlerat janë "falsy", operandi i fundit do të kthehet. + +`(false || {} || null)`: objekti i zbrazët `{}` është vlerë "truthy". Ky është i pari dhe i vetmi vlerë "truthy", i cili kthehet. `one` është i barabartë me `{}`. + +`(null || false || "")`: të gjithë operandët janë vlera "falsy". Kjo do të thotë se operandi i fundit, `""` do të kthehet. `two` është i barabartë me `""`. + +`([] || 0 || "")`: array i zbrazët `[]` është vlerë "truthy". Kjo është vlera e parë "truthy" e cila kthehet. `three` është e barabartë me `[]`. + +
++ +#### Përgjigja: D + +Me një premtim, në thelb themi _Dëshiroj ta ekzekutoj këtë funksion, por do të e lë mënjanë për momentin ndërsa është duke u ekzekutuar pasi kjo mund të marrë pak kohë. Vetëm kur një vlerë e caktuar zgjidhet (ose refuzohet) dhe kur "call stack" është bosh, unë dua ta përdor këtë vlerë._ + +Ne mund të marrim këtë rezultat me të dy: `.then` dhe fjalën kyçe `await` në `async` funksione. Edhe pse mund të marrim vlerën e 'promise' me të dy `.then` dhe `await` ato funksionojnë pak më ndryshe. + +Në funksionin e parë `firstFunction`, në një mënyrë e vendosim funksionin 'myPromise' mënjanë përgjatë ekzekutimit, por ne e vazhdojmë ekzekutimin e kodit tjetër, i cili në këtë rast është `console.log('second')`. Pastaj, funksioni zgjidhet me stringun `I have resolved`, i cili pastaj printohet pasi që e sheh se call stack është i zbrazët. + +Me fjalën kyçe `secondFunction`, në të vërtetë e pauzojmë ekzekutimin e funksionit async derisa vlera të zgjidhet përpara se të vazhdojmë tek rreshti tjetër. + +Kjo do të thotë se pret për `myPromise` të zgjidhet me vlerën `I have resolved`, dhe pasi ajo të ndodhë ne vazhdojmë ne rreshtin e ardhshëm: `second` do të printohet. + +
++ +#### Përgjigja: C + +Operatori `+` nuk përdoret vetëm vetëm për të mbledhur vlerat numberike, por mund të e përdorim për bashkimin e stringjeve. Sa herë që makina e JavaScript e vëren se një ose më shumë vlera nuk janë numra, e shndërron numrin në string. + +Ne fillim është `1` i cili është vlerë numerike. `1 + 2` kthen numrin 3. + +Megjithatë, vlera e dytë është string `"Lydia"`. `"Lydia"` është string dhe `2` është numër: `2` shndërrohet në string. `"Lydia"` dhe `"2"` bashkohen, dhe kjo rezulton në stringun `"Lydia2"`. + +`{ name: "Lydia"}` është objekt. Nuk është as numër as objekt është string, prandaj i konsideron si stringje të dyja. Sa herë që i konsiderojmë si stringje objektet e zakonshme, behet `"[object Object"]`.`"[object Object"]` bashkohet me `"2"` dhe bëhet `"[object Object]2"`. + +
++ +#### Përgjigja: C + +Ne mund të kalojmë qfarëdo vlere që duam te `Promise.resolve`, 'promise' ose 'jo-promise'. Metoda vetë kthen një 'promise' e cila zgjidhet me vlerën (`fulfilled`). Nëse i kaloni një funksion të zakonshëm, do të zgjidhet një promise me një vlerë të zakonshme. Nëse i kaloni një 'promise' si argument, do të zgjidhjet një promise me vlerën e zgjidhur me vlerën që i kalohet si promise. + +Në këtë rast, ne vetëm i kaluam si argument vlerën numerike `5`. Kthen promise të zgjidhur me vlerë `5`. + +
++ +#### Përgjigja: B + +Objektet vendosen si argumente në bazë të referencës së tyre. Kur i kontrollojmë objektet me operatorin për barazim strikt (`===`), ne po kontorllojmë referencën e tyre. + +Ne e paracaktuam vlerën e `person2` të barabartë me objektin `person`, dhe e kaluam objektin `person` si vlerë të `person1`. + +Kjo do të thotë që të dy vlerat kanë referencë të e njejta hapësirë memorike, dhe kështu ato janë të barabarta. + +Blloku i kodit në deklarimin `else` ekzekutohet dhe `They are the same!` printohet. + +
++ +#### Përgjigja: D + +Në JavaScript, kemi dy mënyra për të iu qasur vetive të një objekti: notacioni me kllapa të mëdha "[]" ose notacioni me pikë ".". Në këtë shembull ne po e perdorim notacionin (`colorConfig.colors`) në vend të notacionit me kllapë (`colorConfig["colors"]`). + +Me notacionin me pikë, JavaScript provon të gjejë veti në objekt me saktësisht të njejtin emër. Në këtë shembull, JavaScript provon të gjejë një veti e cila quhet `colors` në objektin `colorConfig`. Nuk ka ndonjë veti të quajtur `colors`, prandaj kjo do të kthejë `undefined`. Pastaj ne provojmë të i qasemi vlerës së elementit të parë ne array duke përdorur `[1]`. Nuk mund të e bëjmë këtë në vlerën e cila është `undefined`, prandaj do të ngrihet `TypeError`: `Cannot read property '1' of undefined`. + +JavaScript i interpreton deklarimet. Kur përdorim notacionin me kllapa të mëdha, e sheh kllapën hapëse `[` dhe vazhdon kërkon derisa të gjen kllapën mbyllëse `]`. Vetëm atëherë, e llogarit deklarimin. Nëse do të përdornim `colorConfig[colors[1]]`, do të kishte kthyer vlerën e vetisë `red` në objektin `colorConfig`. + +
++ +#### Përgjigja: A + +Në prapavijë, emoji-t janë kode të veçanta. Unikodet për emoji-t e zemrës janë `"U+2764 U+FE0F"`. Këto janë gjithmonë të njëjta për të njëjtat emoji, kështu që ne po krahasojmë dy stringje të barabarta me njëri-tjetrin, gjë që ktheh 'e vërtetë'. + +
++ +#### Përgjigja: D + +Me motodën `splice`, ne modifikojmë array origjinal duke fshirë, zëvendësuar ose shtuar elemente. Në këtë rast, ne larguam 2 gjëra duke filluar nga indeksi 1 ( larguam `'🥑'` dhe `'😍'`) dhe shtuam ✨ në vend të tyre. + +`map`, `filter` dhe `slide` kthen array të ri, `find` kthen një element dhe `reduce` kthen një vlerë të reduktuar. + +
++ +#### Përgjigja: A + +Ne vendosëm vlerën e vetisë `favoriteFood` në objektin `info` të barabartë me stringun me emoji-n e picës, `'🍕'`. Një string është një tip i të dhënave primitive. Në JavaScript, tipet primitive të të dhënave nuk ndërveprojnë me referencë. + +Në JavaScript, tipet primitive të të dhënave (gjithçka që nuk është objekt) ndërveprojnë me _vlerë_. Në këtë rast, ne vendosim vlerën e vetisë `favoriteFood` në objektin `info` të barabartë me vlerën e elementit të parë në array `food`, stringu me emoji-n e picës në këtë rast (`'🍕'`). Një string është një tip i të dhënave primitive dhe ndërvepron sipas vlerës (shikoni [blogpost](https://www.theavocoder.com/complete-javascript/2018/12/21/by-value-vs-by-reference) nëse jeni të interesuar të mësoni më shumë) + +Më pas, ne ndryshojmë vlerën e vetisë `favoriteFood` në objektin `info`. Vargu `food` nuk ka ndryshuar, pasi vlera e `favoriteFood` ishte thjesht një _kopje_ e vlerës së elementit të parë në grup dhe nuk ka një referencë për të njëjtin vend në memorie si elementi në `food[0]`. Kur printojmë 'food', është ende array origjinal, "['🍕", "🍫", "🥑", "🍔"]". + +
++ +#### Përgjigja: A + +Me metodën `JSON.parse()`, ne mund të parsojmë JSON stringun në një vlerë JavaScript-i. + +```javascript +// Stringifimi i një numri në një JSON valid, pastaj parsimi i nje4 stringu në vlerë të JavaScript: +const jsonNumber = JSON.stringify(4); // '4' +JSON.parse(jsonNumber); // 4 + +// Stringifimi i një array në JSON valid, pastaj parsimi i JSON stringut ne një vlerë të JavaScript: +const jsonArray = JSON.stringify([1, 2, 3]); // '[1, 2, 3]' +JSON.parse(jsonArray); // [1, 2, 3] + +// Stringifimi i një objekti në JSON valid, pastaj parsimi i JSON stringut në një vlerë të JavaScript: +const jsonArray = JSON.stringify({ name: 'Lydia' }); // '{"name":"Lydia"}' +JSON.parse(jsonArray); // { name: 'Lydia' } +``` + +
++ +#### Përgjigja: D + +Secili funksion ka _kontekstin e vetë të ekzekutimit_. Funksioni `getName` së pari shikon brenda kontekstit të tij në qoftëse përmban variablën `name` të cilën po provojmë të i qasemi. Në këtë rast, funksioni `getName` përmban variablën e tij `name`: e deklaruam variablën `name` me fjalën kyçe `let`m dhe i inicializuam vlerën `'Sarah'`. + +Variablat me fjalën kyçe `let` (dhe `const`) ngriten (hoistoh-en), por për dallim nga `var` nuk inicializohen. Ato nuk janë të qasshme më herët se rreshti në të cilin janë deklaruar (i kemi deklaruar). Kjo quhet "zona e vdekur e përkohshme" (temporal dead zone). Kur tentojmë të i qasemi variablave përpara se ato të deklarohen, JavaScript hedh `ReferenceError`. + +Nëse nuk do të kishim deklaruar `name` brenda funksionit `getName`, makina e JavaScript do të kishte shikuar poshtë _zingjirit të shtrirjes_. Fusha e jashtme ka variabël të quajtur `name` me vlerë `Lydia`. Në këtë rast, do të kishte printuat `Lydia`. + +```javascript +let name = 'Lydia'; + +function getName() { + console.log(name); +} + +getName(); // Lydia +``` + +
++ +#### Përgjigja: C + +Me fjalën kyçe `yield`, ne i japim vlerat në një funksion gjenerator. Me fjalën kyçe `yield*`, ne mund të nxjerrim vlera nga një funksion tjetër gjenerues, ose objekt i iterueshëm (për shembull një array). + +Në `generatorOne`, ne japim të gjithë array `['a', 'b', 'c']'` duke përdorur fjalën kyçe `yield`. Vlera e vetisë `value` në objektin e kthyer me metodën `next` në `one` (`one.next().value`) është e barabartë me të gjithë grupin `['a', 'b', 'c']`. + +```javascript +console.log(one.next().value); // ['a', 'b', 'c'] +console.log(one.next().value); // undefined +``` + +Në `generatorTwo`, ne përdorim fjalën kyçe `yield*`. Kjo do të thotë se vlera e parë e dhënë e `two`, është e barabartë me vlerën e dhënë në iterimin e parë. Iteratori është grupi `['a', 'b', 'c']`. Vlera e parë e dhënë është `a`, kështu që herën e parë që thërrasim `two.next().value`, kthehet `a`. + +```javascript +console.log(two.next().value); // 'a' +console.log(two.next().value); // 'b' +console.log(two.next().value); // 'c' +console.log(two.next().value); // undefined +``` + +
++ +#### Përgjigja: A + +Shprehjet brenda shablloneve literale vlerësohen së pari. Kjo do të thotë që stringu do të përmbajë vlerën e kthyer të shprehjes, funksionin e thirrur menjëherë `(x => x)('I love')` në këtë rast. Ne e kalojmë vlerën `'I love'` si argument në funksionin e shigjetës `x => x`. `x` është e barabartë me `'I love'`, e cila kthehet. Kjo rezulton në `I love to program`. + +
++ +#### Përgjigja: C + +Zakonisht kur i vendosim objektet të barabarta me `null`, ato objekte mirren nga _garbage collector_ pasi nuk ka më referencë për ato objekte. Megjithatë, meqenëse funksioni callback brenda `setInterval` është një funksion me shigjetë (pra i lidhur me objektin `config`), funksioni callback ende mban një referencë për objektin `config`. +Për sa kohë ka një referencë, objekti nuk do të merret nga 'garbage collector' (menaxhuesi i memories për të u larguar). +Meqenëse ky është një interval, vendosja e `config` në '`null` ose `delete` `config.alert` nuk do të mbledhet nga garbage-collector për intervalin, kështu që intervali do të vazhdojë të thirret. +Për ta hequr nga memoria duhet të e pastrojmë me `clearInterval(config.alert)`. +Meqenëse nuk u fshi, funksioni `setInterval` callback do të vazhdojë të thirret çdo 1000ms (1s). + +
++ +#### Përgjigja: B + +Kur shtoni një çift çelës/vlerë duke përdorur metodën `set`, çelësi do të jetë vlera e argumentit të parë që i kalohet funksionit `set`, dhe vlera do të jetë argumenti i dytë që i kalohet funksionit `set`. Çelësi është _functioni_ `() => 'greeting'` në këtë rast, dhe vlera `'Hello world'`. `myMap` tani është `{ () => 'greeting' => 'Hello world!' }`. + +1 është gabim, pasi çelësi nuk është `'greeting'` por `() => 'greeting'`. +3 është gabim, pasi ne po krijojmë një funksion të ri duke e kaluar atë si parametër në metodën `get`. Objekti ndërvepron me _referencë_. Funksionet janë objekte, prandaj dy funksione nuk janë kurrë rreptësisht të barabarta, edhe nëse janë identike: ato kanë një referencë në një vend të ndryshëm në memorie. + +
++ +#### Përgjigja: C + +Të dy funksionet `changeAge` dhe `changeAgeAndName` kanë një parametër të paracaktuar, përkatësisht një objekt të krijuar rishtazi `{...person}`. Ky objekt ka kopje të të gjithë çelësave/vlerave në objektin `person`. + +Së pari, e thirrim funksionin `changeAge` dhe e kalojmë objektin `person` si argument. Ky funksion rrit vlerën e vetisë `age` për 1. `person` tani është `{ name: "Lydia", age: 22 }`. + +Pastaj, e thirrim funksionin `changeAgeAndName`, sidoqoftë ne nuk e kalojmë një parametër. Në vend të kësaj, vlera e `x` është e barabartë me objektin e ri `{ ...person }`. Meqenëse është një objekt i ri, nuk do të afektojë vlerën e vetive në objektin `person`. `person` ende është e barabartë me `{ name: "Lydia", age: 22 }`. + +
++ +#### Përgjigja: C + +Me operatorin spread `...`, me mund të _përhapim_ iteruesit në elemente individuale. Funksioni `sumValues` merr tre argumente: `x`, `y` dhe `z`. `...[1, 2, 3]` do të rezultojë në `1, 2, 3`, të cilin ia kalojmë funksionit `sumValues`. + +
++ +#### Përgjigja: B + +Me operandin `+=`, ne po rrisim vlerën e `sum` për `1`. `num` kishte vlerën iniciale `1`, kështu `1 + 1` është `2`. Elementi në indeksin e dytë në `list` është 🥰, `console.log(list[2])` printon 🥰. + +
++ +#### Përgjigja: B + +Me operatorin opsional të zinxhirit `?.`, nuk duhet të kontrollojmë më në mënyrë eksplicite nëse vlerat më të thella të ndërthurura janë të vlefshme apo jo. Nëse po provojmë ti qasemi një vetie me një vlerë `undefined` ose `null` (_nullish_), shprehja lidhet me qark të shkurtër dhe kthen `undefined`. + +`person.pet?.name`: `person` ka një veti të quajtur `pet`: `person.pet` nuk është vlerë null. Ka një veti të quajtur `name`, dhe kthen `Mara`. +`person.pet?.family?.name`: `person` ka një veti të quajtur `pet`: `person.pet` nuk është vlerë null. `pet` nuk ka një veti të quajtur `family`, `person.pet.family` është vlerë null. Shprehja kthen `undefined`. +`person.getFullName?.()`: `person` ka një veti të quajtur `getFullName`: `person.getFullName()` nuk është vlerë null dhe mund të thirret, dhe do të kthejë `Lydia Hallie`. +`member.getLastName?.()`: variabla `member` nuk ekziston prandaj `ReferenceError` do të hedhet! + +
++ +#### Përgjigja: B + +Ne e kaluam kushtëzimin `groceries.indexOf("banana")` tek deklarimi if. `groceries.indexOf("banana")` kthen `0`, e cila është vlerë false. Përderisa deklarimi i kushtëzimit if është falsy, kodi në bllokun `else` ekzekutohet, dhe `We don't have to buy bananas!` do të printohet. + +
++ +#### Përgjigja: D + +Metoda `language` është metodë `setter` (vendosëse). Vendosësit nuk mbajë një vlerë aktuale, qêllimi i tyre është të _modifikojnë_ vetitë. Kur e thirrim metodën `setter`, do të kthehet `undefined`. + +
++ +#### Përgjigja: C + +`typeof name` kthen `"string"`. Stringu `"string"` është vlerë truthy, kështu që `!typeof name` kthen vlerën booleane `false`. `false === "object"` dhe `false === "string"` të dy kthejnë `false`. + +(Nëse do të dëshironim të shikojmë në qoftëse tipi ishtë (jo) i barabartë në një tip të caktuar, do të kishim shkruar `!==` në vend të `!typeof`) + +
++ +#### Përgjigja: A + +Funksioni `add` kthen një funksion shigjete, i cili kthen një funksion shigjete, i cili kthen një funksion shigjete. Funksioni i parë merr një argument `x` me vlerën `4`. Ne e thërrasim funksionin e dytë, i cili merr një argument `y` me vlerën `5`. Pastaj thërrasim funksionin e tretë, i cili merr një argument `z` me vlerën `6`. Kur po provojmë të qasemi në vlerën `x`, `y` dhe `z` brenda funksionit të fundit të shigjetës, makina JS shkon lart në zinxhirin e shtrirjes për të gjetur vlerat për `x` dhe `y` përkatësisht. Kjo kthen `4` `5` `6`. + +
++ +#### Përgjigja: C + +Funksioni gjenerator `range` kthen një objekt asinkron me premtimet për çdo elemnt në rangun që ne japim: `Promise{1}`, `Promise{2}`, `Promise{3}`. Ne vendosim variablën `gen` të jetë e barabartë me objektin asinkron, pas të cilit ne e iterojmë mbi të nëpërmjet unazës `for await ... of`. Ne vendosim variablën `item` të jetë e barabartë me vlerat e kthyera të Promise: së pari `Promise{1}`, pastaj `Promise{2}`, pastaj `Promise{3}`. Pasi që po _presim_ vlerën e `item`, premtimet e zgjidhura, vlerat e zgjidhura të premtimit kthehen: `1`, `2`, pastaj `3`. + +
++ +#### Përgjigja: D + +`myFunc` pret një objekt me vetitë `x`, `y` dhe `z` si argumente të tij. Pasi që po japim vetëm tre vlera numerike të ndara (1, 2, 3) në vend të një objekti me vetitë `x`, `y` dhe `z` ({x: 1, y: 2, z: 3}), `x`, `y` dhe `z` kanë vlerën e tyre të parazgjedhur si `undefined`. + +
++ +#### Përgjigja: B + +Me metoden `Intl.NumberFormat`, ne mund të formatojmë vlerat numerike në çdo vend. Ne formatojmë vlerën numerike `130` në vendin `en-US` si një `unit` në `mile-per-hour`, që rezulton në `130 mph`. Vlera numerike `300` në vendin `en-US` si një `currency` në `USD` rezulton në `$300.00`. + +
++ +#### Përgjigja: B + +Duke destrukturuar objektet, ne mund të targetojmë vlerat nga objekti i djathtë, dhe të caktojmë vlerën e targetuar në vlerën e emrit të njëjtë të vetisë në objektin në anën e majtë. Në këtë rast, ne po caktojmë vlerën "💀" në `spookyItems[3]`. Kjo do të thotë se ne po ndryshojmë vargun `spookyItems`, po i shtojmë "💀". Kur printojmë `spookyItems`, `["👻", "🎃", "🕸", "💀"]` printohet. + +
++ +#### Përgjigja: C + +Me metoden `Number.isNaN`, ju mund të kontrolloni nëse vlera që ju jepni është një _vlerë numerike_ dhe e barabartë me `NaN`. `name` nuk është një vlerë numerike, kështu që `Number.isNaN(name)` kthen `false`. `age` është një vlerë numerike, por nuk është e barabartë me `NaN`, kështu që `Number.isNaN(age)` kthen `false`. + +Me metoden `isNaN`, ju mund të kontrolloni nëse vlera që ju jepni nuk është numër. `name` nuk është numër, kështu që `isNaN(name)` kthen true. `age` është numër, kështu që `isNaN(age)` kthen `false`. + +
++ +#### Përgjigja: D + +Variablat e deklaruara me fjalën kyçe `const` nuk janë të referueshme para inicializimit të tyre: kjo quhet _zona e vdekjes së përkohshme_. Në funksionin `getInfo`, variabla `randomValue` është me shtrirje në fushën e funksionit `getInfo`. Në rreshtin ku ne duam të printojmë vlerën e `typeof randomValue`, variabla `randomValue` nuk është inicializuar ende: një `ReferenceError` hidhet! Makina e JS nuk shkoi poshtë në zinxhirin e fushës pasi ne deklaruam variablën `randomValue` në funksionin `getInfo`. + +
++ +#### Përgjigja: C + +Në bllokun `try`, ne jemi duke printuar vlerën e pritur të variablës `myPromise`: `"Woah some cool data"`. Pasi që nuk u hodhën gabime në bllokun `try`, kodi në bllokun `catch` nuk ekzekutohet. Kodi në bllokun `finally` _gjithmonë_ ekzekutohet, `"Oh finally!"` printohet. + +
++ +#### Përgjigja: B + +Me metodën flat, ne mund të krijojmë një varg të ri, të rrafshët. Thellësia e vargut të rrafshët varet nga vlera që ne japim. Në këtë rast, ne dhamë vlerën 1 (e cila nuk ishte e nevojshme, ajo është vlera e paracaktuar), që do të thotë se vetëm vargjet në thellësinë e parë do të bashkohen. ['🥑'] dhe ['✨', '✨', ['🍕', '🍕']] në këtë rast. Bashkimi i këtyre dy vargjeve rezulton në ['🥑', '✨', '✨', ['🍕', '🍕']]. + +
+
+
+#### Përgjigja: D
+
+`counterOne` është një instancë e klasës `Counter`. Klasa Counter përmban një veti `count` në konstruktorin e saj, dhe një metodë `increment`. Së pari, ne thirrëm metodën `increment` dy herë duke thirrur `counterOne.increment()`. Aktualisht, `counterOne.count` është `2`.
+
+
+
+Më pas, ne krijojmë një variabël të re `counterTwo`, dhe e vendosim të barabartë me `counterOne`. Pasi objektet ndërveprojnë me referencë, ne thjesht po krijojmë një referencë të re për të njëjtin vend në memorie ku `counterOne` tregon. Meqenëse po tregon në të njëjtin vend në memorie, çdo ndryshim i bërë në objektin që `counterTwo` ka një referencë, gjithashtu vlen edhe për `counterOne`. Aktualisht, `counterTwo.count` është `2`.
+
+Ne thërrasim `counterTwo.increment()`, i cili vendos `count` në `3`. Pastaj, printojmë numëruesin `counterOne`, i cili printon `3`.
+
+
+
+
+ +#### Përgjigja: C + +Së pari, ne thirrim `funcOne`. Në rreshtin e parë të `funcOne`, ne thirrim funksionin _asinkron_ `setTimeout`, nga i cili callback është dërguar tek API-ja e Web-it. (shih artikullin tim mbi ciklin e ngjarjeve këtu.) + +Pastaj e thirrim premtimin `myPromise`, e cila është një operacion _asinkron_. + +Edhe premtimi dhe koha e pritjes janë operacione asinkrone, funksioni vazhdon të ekzekutohet ndërsa është i zënë në plotësimin e premtimeve dhe trajtimin e callback-ut `setTimeout`. Kjo do të thotë se `Last line 1!` printohet së pari, pasi kjo nuk është një operacion asinkron. + +Meqenëse callstack nuk është bosh ende, funksioni `setTimeout` dhe premtimi në `funcOne` nuk mund të shtohen ende në callstack. + +Në `funcTwo`, variabla `res` merr `Promise` sepse `Promise.resolve(Promise.resolve('Promise'))` është ekuivalente me `Promise.resolve('Promise')` pasi plotësimi i një premtimi thjesht i plotëson vlerat e tij. `await` në këtë rresht ndalon ekzekutimin e funksionit derisa të marrë zgjidhjen e premtimit dhe pastaj vazhdon të ekzekutohet sinkronisht deri në përfundim, kështu që `Promise 2!` dhe pastaj `Last line 2!` janë regjistruar dhe `setTimeout` është dërguar tek API-ja e Web-it. + +Pastaj call stack është bosh. Premtimet janë _mikrodetyra_ (microtasks) prandaj ato zgjidhen së pari kur call stack është bosh, kështu që `Promise 1!` printohet. + +Tani, pasi që `funcTwo` është larguar nga call stack, call stack është bosh. Callback-et që po presin në radhë (`() => console.log("Timeout 1!")` nga `funcOne`, dhe `() => console.log("Timeout 2!")` nga `funcTwo`) shtohen në call stack një nga një. Callback-i i parë printon `Timeout 1!`, dhe largohet nga stack. Më pas, callback-i i dytë printon `Timeout 2!`, dhe largohet nga stack. + +
++ +#### Përgjigja: C + +Me yllin `*`, ne importojmë të gjitha vlerat e eksportuara nga ai fajll, si ato të paracaktuara dhe ato të emëruara. Nëse kemi fajllin e mëposhtëm: + +```javascript +// info.js +export const name = 'Lydia'; +export const age = 21; +export default 'I love JavaScript'; + +// index.js +import * as info from './info'; +console.log(info); +``` + +The following would get logged: + +```javascript +{ + default: "I love JavaScript", + name: "Lydia", + age: 21 +} +``` + +Për shembullin `sum`, do të thotë se vlera e importuar e `sum` do të dukej kështu: + +```javascript +{ default: function sum(x) { return x + x } } +``` + +Mund të e thërrasim këtë funksion, duke thirrur `sum.default` + +
++ +#### Përgjigja: C + +Me një objekt Proxy, ne mund të shtojmë sjellje të personalizuara për një objekt të cilit i kalohet si argumenti i dytë. Në këtë rast, ne i kalojmë objektin `handler` i cili përmban dy veti: `set` dhe `get`. `set` thirret çdo herë kur ne _caktojmë_ vlerat e vetisë, `get` thirret çdo herë kur ne _marrim_ (i qasemi) vlerave të vetisë. + +Argumenti i parë është një objekt i zbrazët `{}`, i cili është vlera e `person`. Tek ky objekt, shtohet sjellja e personalizuar e specifikuar në objektin `handler`. Nëse shtojmë një veti tek objekti `person`, `set` do të thirret. Nëse i qasemi një vetie në objektin `person`, `get` do të thirret. + +Së pari, ne shtuam një veti të re `name` tek objekti proxy (`person.name = "Lydia"`). `set` thirret, dhe printon `"Added a new property!"`. + +Pastaj, ne i qasemi një vlerë të vetisë në objektin proxy, vetia `get` në objektin handler thirret. `"Accessed a property!"` printohet. + +
++ +#### Përgjigja: A + +Me `Object.seal` ne mund të parandalojmë shtimin e vetive të reja, ose fshirjen e vetive ekzistuese. + +Megjithatë, ju ende mund të modifikoni vlerën e vetive ekzistuese. + +
++ +#### Përgjigja: C + +Metoda `Object.freeze` _ngrin_ një objekt. Asnjë veti nuk mund të shtohet, të modifikohet, ose të hiqet. + +Megjithatë, ajo vetëm _ngrin sipërfaqësisht_ objektin, që do të thotë se vetëm vetitë _e drejtpërdrejta_ në objekt janë të ngrira. Nëse vetia është një tjetër objekt, si `address` në këtë rast, vetitë në atë objekt nuk janë të ngrira, dhe mund të modifikohen. + +
++ +#### Përgjigja: A + +Së pari, ne thirrëm `myFunc()` pa kaluar asnjë argument. Pasi që nuk kaluam argumente, `num` dhe `value` morën vlerat e tyre të paracaktuara: num është `2`, dhe `value` është vlera e kthyer nga funksioni `add`. Tek funksioni `add`, ne i japim si argument `num`, i cili ka vlerën `2`. `Add` kthen `4`, e cila është vlera e `value`. + +Më pas, ne thirrëm `myFunc(3)` dhe kaluam vlerën `3` si vlerë për argumentin `num`. Nuk kaluam një argument për `value`. Pasi nuk kaluam një vlerë për argumentin `value`, ai mori vlerën e paracaktuar: vlerën e kthyer nga funksioni `add`. Tek `add`, ne i japim si argument `num`, i cili ka vlerën `3`. `Add` kthen `6`, e cila është vlera e `value`. + +
++ +#### Përgjigja: D + +Në ES2020, mund të shtojmë variabla private në klasa duke përdorur `#`. Nuk mund t'i qasemi këtyre variablave jashtë klasës. Kur provojmë të printojmë `counter.#number`, hidhet një SyntaxError: nuk mund t'i qaseni jashtë klasës `Counter`! + +
++ +#### Përgjigja: B + +Për të iteruar mbi `members` në çdo element në array `teams`, duhet të kaloni `teams[i].members` në funksionin gjenerator `getMembers`. Funksioni gjenerator kthen një objekt gjenerator. Për të iteruar mbi çdo element në këtë objekt gjenerator, duhet të përdorim `yield*`. + +Nëse do të shkruanim `yield`, `return yield`, ose `return`, gjithë funksioni gjenerator do të kthehej herën e parë që do e thirrim metodën `next`. + +
++ +#### Përgjigja: C + +Funksioni `addHobby` merr dy argumente, `hobby` dhe `hobbies` me vlerën e paracaktuar të array `hobbies` në objektin `person`. + +Së pari, ne thirrim funksionin `addHobby`, dhe japim `"running"` si vlerë për `hobby` dhe një array bosh si vlerë për `hobbies`. Pasi japim një varg bosh si vlerë për `hobbies`, `"running"` shtohet në këtë varg bosh. + +Pastaj, ne thirrim funksionin `addHobby`, dhe japim `"dancing"` si vlerë për `hobby`. Nuk kemi dhënë vlerë për `hobbies`, kështu që ajo merr vlerën e paracaktuar, vetinë `hobbies` në objektin `person`. Ne shtojmë hobi `dancing` në array `person.hobbies`. + +Në fund, ne thirrim funksionin `addHobby`, dhe japim `"baking"` si vlerë për `hobby`, dhe array `person.hobbies` si vlerë për `hobbies`. Ne shtojmë hobi `baking` në array `person.hobbies`. + +Pas shtimit të `dancing` dhe `baking`, vlera e `person.hobbies` është `["coding", "dancing", "baking"]` + +
++ +#### Përgjigja: B + +Krijojmë variablën `pet` që është një instancë e klasës `Flamingo`. Kur ne e instantojmë këtë instancë, thirret `constructor` në `Flamingo`. Së pari, `"I'm pink. 🌸"` printohet, pas të cilit thirrim `super()`. `super()` thirr constructorin e klasës prind, `Bird`. Thirret constructori në `Bird`, dhe printon `"I'm a bird. 🦢"`. + +
++ +#### Përgjigja: D + +Fjala kyçe `const` thjesht do të thotë se nuk mund të _ri-deklarojmë_ vlerën e asaj ndryshore, është _vetëm për lexim_. Megjithatë, vlera e elementeve të array nuk është e pandryshueshme. Vetitë në vargun `emojis` mund të modifikohen, për shembull duke shtuar vlera të reja, duke i shpërndarë ato, ose duke caktuar gjatësinë e vargut në 0. + +
++ +#### Përgjigja: C + +Objektet nuk janë të paraprakisht të iterueshme. Një objekt është i iterueshëm nëse protokolli i iteratorëve është prezent. Ne mund ta shtojmë këtë manualisht duke shtuar simbolin e iteratorit `[Symbol.iterator]`, i cili duhet të kthejë një objekt gjenerator, për shembull duke e bërë atë një funksion gjenerator `*[Symbol.iterator]() {}`. Ky funksion gjenerator duhet të prodhojë `Object.values` e objektit `person` nëse dëshirojmë që të kthejë array `["Lydia Hallie", 21]`: `yield* Object.values(this)`. + +
++ +#### Përgjigja: C + +Kushti `if` brenda ciklit `forEach` kontrollon nëse vlera e `num` është e vërtetë apo false. Meqenëse numri i parë në array `nums` është `0`, një vlerë false, blloku i kodit të deklaratës `if` nuk do të ekzekutohet. `count` rritet vetëm për 3 numrat e tjerë në array `nums`, `1`, `2` dhe `3`. Meqenëse `count` rritet për `1` 3 herë, vlera e `count` është `3`. + +
++ +#### Përgjigja: D + +Simboli ? na lejon të i qasemi opsionalisht vetive më të thella brenda objekteve. Ne po provojmë të shfaqim elementin në indeksin 1 brenda në nën-array që është në indeksin 1 të array fruits. Nëse nën-array në indeksin 1 në array fruits nuk ekziston, thjesht do të kthejë undefined. Nëse nën-array në indeksin 1 në vargun fruits ekziston, por ky nën-array nuk ka një artikull në indeksin e tij 1, gjithashtu do të kthejë undefined. + +Së pari, ne po përpiqemi të printojmë artikullin e dytë në nën-array `['🍍']` të `[['🍊', '🍌'], ['🍍']]`. Ky nën-array përmban vetëm një element, që do të thotë se nuk ka element në indeksin `1`, dhe kthen `undefined`. + +Më pas, ne po thërrasim funksionin `getFruits` pa kaluar një vlerë si argument, që do të thotë se `fruits` ka vlerë `undefined` të paracaktuar. Pasi që po lidhim në mënyrë kushtëzuese elementin në indeksin `1` të `fruits`, kthen `undefined` pasi ky element në indeksin `1` nuk ekziston. + +Së fundmi, po përpiqemi të shfaqim artikullin e dytë në nën-array `['🍊', '🍌']` të `['🍍'], ['🍊', '🍌']`. Elementi në indeksin `1` brenda këtij nën-array është `🍌` që printohet. + +
++ +#### Përgjigja: A + +Ne i caktojmë variablës `calc` të jetë e barabartë me një instancë të re të klasës `Calc`. Më pas, ne krijojmë një instancë të re të `Calc`, dhe thërrasim metodën `increase` në këtë instancë. Pasi që vetia 'count' është brenda konstruktorit të klasës `Calc`, vetia 'calc' nuk është e përbashkët në prototipin e `Calc`. Kjo do të thotë se vlera 'calc' nuk është përditësuar për instancën që tregon calc, numërimi është ende `0`. + +
++ +#### Përgjigja: B + +Funksioni `updateUser` përditëson vlerat e vetive `email` dhe `password` në user, nëse vlerat e tyre i janë kaluar funksionit, pas së cilës funksioni kthen objektin `user`. Vlera e kthyer e funksionit `updateUser` është objekti `user`, që do të thotë se vlera e updatedUser është një referencë për të njëjtin objekt `user` që tregon `user`. `updatedUser === user` është e barabartë me `true`. + +
++ +#### Përgjigja: C + +Së pari, ne thirrim metodën `slice` në array e frutave. Metoda slice nuk modifikon array origjinal, por kthen vlerën që e ka 'prerë (slice)' nga array: emoji e bananes. +Më pas, ne thirrim metodën `splice` në array e frutave. Metoda splice modifikon array origjinal, që do të thotë se array i frutave tani përbëhet nga `['🍊', '🍎']`. +Në fund, ne thirrim metodën `unshift` në array e frutave, e cila modifikon array origjinal duke shtuar vlerën e dhënë, në këtë rast ‘🍇’, si elementin e parë në varg. Array i frutave tani përbëhet nga `['🍇', '🍊', '🍎']`. + +
++ +#### Përgjigja: B + +Çelësat e objektit konvertohen në stringje. + +Pasi që vlera e `dog` është një objekt, `animals[dog]` në fakt do të thotë që ne po krijojmë një veti të re të quajtur `"object Object"` të barabartë me objektin e ri. Tani `animals["object Object"]` është i barabartë me `{ emoji: "🐶", name: "Mara"}`. + +`cat` është gjithashtu një objekt, që do të thotë që `animals[cat]` në fakt do të thotë se ne po mbishkruajmë vlerën e `animals["object Object"]` me vetitë e reja të macës. + +Duke printuar `animals[dog]`, ose në fakt `animals["object Object"]` pasi që konvertimi i objektit `dog` në string rezulton në `"object Object"`, kthen `{ emoji: "🐈", name: "Sara" }`. + +
++ +#### Përgjigja: A + +Funksioni `updateEmail` është një funksion shigjetë dhe nuk është i lidhur me objektin `user`. Kjo do të thotë se fjalë kyçe `this` nuk i referohet objektit `user`, por i referohet shtrirjes globale në këtë rast. Vlera e `email` brenda objektit `user` nuk përditësohet. Kur printohet vlera e `user.email`, kthehet vlera origjinale e `my@email.com`. + +
++ +#### Përgjigja: D + +Metoda `Promise.all` ekzekuton premtimet e dhëna si argumente paralelisht. Nëse një premtim dështon, metoda 'Promise.all' _refuzon_ me vlerën e premtimit të refuzuar. Në këtë rast, `promise3` u refuzua me vlerën `"Third"`. Ne po kapim vlerën e refuzuar në metodën `catch` në thirrjen `runPromises` për të kapur çdo gabim brenda funksionit `runPromises`. Vetëm `"Third"` printohet, pasi `promise3` u refuzua me këtë vlerë. + +
++ +#### Përgjigja: C + +Metoda `fromEntries` transformon një array 2d në një objekt. Elementi i parë në çdo nën-array do të jetë çelësi, dhe elementi i dytë në çdo nën-array do të jetë vlera. Në këtë rast, ne jemi duke mapuar mbi array `keys`, i cili kthen një array ku elementi i parë është elementi në array të çelësave në indeksin aktual, dhe elementi i dytë është elementi i vlerave të array në indeksin aktual. + +Kjo krijon një array të nën-arrays që përmbajnë çelësat dhe vlerat e duhura, të cilat rezultojnë në `{ name: "Lydia", age: 22 }` + +
++ +#### Përgjigja: C + +Vlera e paracaktuar e `address` është një objekt i zbrazët `{}`. Kur vendosëm variablën `member` të barabartë me objektin që kthehet nga funksioni `createMember`, ne nuk kaluam një vlerë për adresën, që do të thotë se vlera e adresës është objekti i zbrazët parazgjedhur `{}`. Një objekt i zbrazët është një vlerë e vërtetë, që do të thotë se gjendja e `address ? address : null` kushtëzuese kthehet `true`. Vlera e adresës është objekti i zbrazët `{}`. + +
++ +#### Përgjigja: B + +Kushti brenda deklaratës `if` kontrollon nëse vlera e `!typeof randomValue` është e barabartë me `"string"`. Operatori `!` e shndërron vlerën në një vlerë booleane. Nëse vlera është e vërtetë, vlera e kthyer do të jetë `false`, nëse vlera është e pavërtetë, vlera e kthyer do të jetë `true`. Në këtë rast, vlera e kthyer e `typeof randomValue` është vlera e vërtetë `"number"`, që do të thotë se vlera e `!typeof randomValue` është vlera booleane `false`. + +`!typeof randomValue === "string"` gjithmonë kthen false, pasi në fakt po kontrollojmë `false === "string"`. Pasi që kushtëzimi ktheu `false`, blloku i kodit të deklaratës `else` ekzekutohet, dhe `Yay it's a string!` printohet. + +
+@@ -477,7 +481,7 @@ sum(1, "2"); #### Відповідь: C -JavaScript це **динамічно тіпізірованна мова**: ми не визначаємо тип змінних. Змінні можуть автоматично бути перетворені з одного типу в інший без нашої участі, що називається _неявним приведенням типів_. **Приведення** це перетворення з одного типу в інший. +JavaScript це **динамічно типізована мова**: ми не визначаємо тип змінних. Змінні можуть автоматично бути перетворені з одного типу в інший без нашої участі, що називається _неявним приведенням типів_. **Приведення** це перетворення з одного типу в інший. У цьому прикладі, JavaScript конвертувати число `1` в рядок, щоб операція всередині функції мала сенс і повернула значення. Під час складання числа (`1`) і рядки (`'2'`) число перетворюється до рядка. Ми можемо додавати рядки ось так: `"Hello" + "World"`. Таким чином, "`1"` + `"2"` повертає "`12"`. @@ -661,7 +665,7 @@ const sum = eval("10*10+5"); #### Відповідь: A -`eval` виконує код, переданий у вигляді рядка. Якщо це рядок (як в даному випадку), то обчислюється вираз. Вираз `10 * 10 + 5` поверне число `105`. +`eval` виконує код, переданий у вигляді рядка. Якщо це рядок (як в такому випадку), то обчислюється вираз. Вираз `10 * 10 + 5` поверне число `105`.
+ +#### Відповідь: C + +Звичайні функції не можна зупинити "на півдорозі" після виклику. Однак функція-генератор може зупинитися "на півдорозі", а потім продовжити з того місця, де вона зупинилась. Кожного разу, коли функція-генератор зустрічає ключове слово `yield`, функція видає значення, що вказане після нього. Зауважте, що функція-генератор в цьому випадку не _повертає_ (return) значення, вона _дає_ (yields) значення. + +Спочатку ми ініціалізуємо функцію-генератор з `i` рівним `10`. Ми викликаємо функцію-генератор за допомогою методу `next()`. Коли ми вперше викликаємо функцію генератора, `i` дорівнює `10`. Перше ключове слово `yield`: воно дає значення `i`. Генератор тепер "призупинено", і `10` записується у консоль. + +Потім ми знову викликаємо функцію за допомогою методу `next()`. Виконання коду продовжується там, де зупинилося раніше, все ще з `i` що дорівнює `10`. Тепер функція зустрічає наступне ключове слово `yield` і дає `i * 2`. `i` дорівнює `10`, тож віддається `10 * 2`, що дорівнює `20`. У результаті: `10, 20`. + +
++ +#### Відповідь: B + +Коли ми передаємо кілька промісів методу `Promise.race`, він вирішує/відхиляє _перший_ проміс, яки вирішився/відхилився. Методу `setTimeout` ми передаємо таймер: 500 мс для першого промісу (`firstPromise`) та 100 мс для другого промісу (`secondPromise`). Це означає, що `secondPromise` вирішиться першим зі значенням `'two'`. `res` тепер містить значення `'two'`, яке буде зображено у консолі. + +
+
+
+#### Відповідь: D
+
+Спочатку ми оголошуємо змінну `person` що містить об'єкта, який має властивість `name`.
+
+
+
+Потім ми оголошуємо змінну `members`. Ми встановлюємо перший елемент масиву рівним значенню змінної `person`. Об'єкти взаємодіють за допомогою _посилання_, коли їх встановлюють рівними один одному. Коли ви призначаєте посилання з однієї змінної на іншу, ви робите _копію_ цього посилання. (зверніть увагу, що вони не мають _однакового_ посилання!)
+
+
+
+Далі ми встановлюємо змінну `person` рівною `null`.
+
+
+
+Ми лише змінюємо значення змінної `person`, а не перший елемент у масиві, оскільки цей елемент має інше (скопійоване) посилання на об’єкт.Перший елемент у `members` все ще містить своє посилання на вихідний об’єкт. Коли ми виводимо у консоль масив `members`, перший елемент усе ще містить значення об'єкта, який і показується у консолі.
+
+
-#### 答案: D
+#### 答案:D
在函数内部,我们首先通过 `var` 关键字声明了 `name` 变量。这意味着变量被提升了(内存空间在创建阶段就被设置好了),直到程序运行到定义变量位置之前默认值都是 `undefined`。因为当我们打印 `name` 变量时还没有执行到定义变量的位置,因此变量的值保持为 `undefined`。
@@ -60,7 +60,7 @@ for (let i = 0; i < 3; i++) {
-#### 答案: C
+#### 答案:C
由于 JavaScript 的事件循环,`setTimeout` 回调会在*遍历结束后*才执行。因为在第一个遍历中遍历 `i` 是通过 `var` 关键字声明的,所以这个值是全局作用域下的。在遍历过程中,我们通过一元操作符 `++` 来每次递增 `i` 的值。当 `setTimeout` 回调执行的时候,`i` 的值等于 3。
@@ -94,7 +94,7 @@ shape.perimeter()
-#### 答案: B
+#### 答案:B
注意 `diameter` 的值是一个常规函数,但是 `perimeter` 的值是一个箭头函数。
@@ -121,7 +121,7 @@ shape.perimeter()
-#### 答案: A
+#### 答案:A
一元操作符加号尝试将 bool 转为 number。`true` 转换为 number 的话为 `1`,`false` 为 `0`。
@@ -153,7 +153,7 @@ const mouse = {
-#### 答案: A
+#### 答案:A
在 JavaScript 中,所有对象的 keys 都是字符串(除非对象是 Symbol)。尽管我们可能不会定义它们为字符串,但它们在底层总会被转换为字符串。
@@ -188,7 +188,7 @@ console.log(d.greeting)
-#### 答案: A
+#### 答案:A
在 JavaScript 中,当设置两个对象彼此相等时,它们会通过*引用*进行交互。
@@ -223,7 +223,7 @@ console.log(b === c)
-#### 答案: C
+#### 答案:C
`new Number()` 是一个内建的函数构造器。虽然它看着像是一个 number,但它实际上并不是一个真实的 number:它有一堆额外的功能并且它是一个对象。
@@ -262,7 +262,7 @@ freddie.colorChange('orange')
-#### 答案: D
+#### 答案:D
`colorChange` 是一个静态方法。静态方法被设计为只能被创建它们的构造器使用(也就是 `Chameleon`),并且不能传递给实例。因为 `freddie` 是一个实例,静态方法不能被实例使用,因此抛出了 `TypeError` 错误。
@@ -286,9 +286,9 @@ console.log(greetign)
-#### 答案: A
+#### 答案:A
-代码打印出了一个对象,这是因为我们在全局对象上创建了一个空对象!当我们将 `greeting` 写错成 `greetign` 时,JS 解释器实际在上浏览器中将它视为 `global.greetign = {}` (或者 `window.greetign = {}`)。
+代码打印出了一个对象,这是因为我们在全局对象上创建了一个空对象!当我们将 `greeting` 写错成 `greetign` 时,JS 解释器实际在上浏览器中将它视为 `global.greetign = {}`(或者 `window.greetign = {}`)。
为了避免这个为题,我们可以使用 `"use strict"。这能确保当你声明变量时必须赋值。
@@ -307,7 +307,7 @@ function bark() {
bark.animal = 'dog'
```
-- A: 正常运行!
+- A: 正常运行!
- B: `SyntaxError`. 你不能通过这种方式给函数增加属性。
- C: `undefined`
- D: `ReferenceError`
@@ -315,7 +315,7 @@ bark.animal = 'dog'
-#### 答案: A
+#### 答案:A
这在 JavaScript 中是可以的,因为函数是对象!(除了基本类型之外其他都是对象)
@@ -350,7 +350,7 @@ console.log(member.getFullName());
-#### 答案: A
+#### 答案:A
你不能像常规对象那样,给构造函数添加属性。如果你想一次性给所有实例添加特性,你应该使用原型。因此本例中,使用如下方式:
@@ -390,7 +390,7 @@ console.log(sarah)
-#### 答案: A
+#### 答案:A
对于 `sarah`,我们没有使用 `new` 关键字。当使用 `new` 时,`this` 引用我们创建的空对象。当未使用 `new` 时,`this` 引用的是**全局对象**(global object)。
@@ -411,7 +411,7 @@ console.log(sarah)
-#### 答案: D
+#### 答案:D
在**捕获**(capturing)阶段中,事件从祖先元素向下传播到目标元素。当事件达到**目标**(target)元素后,**冒泡**(bubbling)才开始。
@@ -430,7 +430,7 @@ console.log(sarah)
-#### 答案: B
+#### 答案:B
除了**基本对象**(base object),所有对象都有原型。基本对象可以访问一些方法和属性,比如 `.toString`。这就是为什么你可以使用内置的 JavaScript 方法!所有这些方法在原型上都是可用的。虽然 JavaScript 不能直接在对象上找到这些方法,但 JavaScript 会沿着原型链找到它们,以便于你使用。
@@ -457,7 +457,7 @@ sum(1, '2')
-#### 答案: C
+#### 答案:C
JavaScript 是一种**动态类型语言**:我们不指定某些变量的类型。值可以在你不知道的情况下自动转换成另一种类型,这种类型称为**隐式类型转换**(implicit type coercion)。**Coercion** 是指将一种类型转换为另一种类型。
@@ -485,7 +485,7 @@ console.log(number)
-#### 答案: C
+#### 答案:C
一元**后自增**运算符 `++`:
@@ -526,7 +526,7 @@ getPersonInfo`${person} is ${age} years old`
-#### 答案: B
+#### 答案:B
如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值!
@@ -558,7 +558,7 @@ checkAge({ age: 18 })
-#### 答案: C
+#### 答案:C
在测试相等性时,基本类型通过它们的值(value)进行比较,而对象通过它们的引用(reference)进行比较。JavaScript 检查对象是否具有对内存中相同位置的引用。
@@ -589,7 +589,7 @@ getAge(21)
-#### 答案: C
+#### 答案:C
扩展运算符(`...args`)会返回实参组成的数组。而数组是对象,因此 `typeof args` 返回 `"object"`。
@@ -618,7 +618,7 @@ getAge()
-#### 答案: C
+#### 答案:C
使用 `"use strict"`,你可以确保不会意外地声明全局变量。我们从来没有声明变量 `age`,因为我们使用 `"use strict"`,它将抛出一个引用错误。如果我们不使用 `"use strict"`,它就会工作,因为属性 `age` 会被添加到全局对象中了。
@@ -641,7 +641,7 @@ const sum = eval('10*10+5')
-#### 答案: A
+#### 答案:A
代码以字符串形式传递进来,`eval` 对其求值。如果它是一个表达式,就像本例中那样,它对表达式求值。表达式是 `10 * 10 + 5`。这将返回数字 `105`。
@@ -664,7 +664,7 @@ sessionStorage.setItem('cool_secret', 123)
-#### 答案: B
+#### 答案:B
关闭 **tab 标签页** 后,`sessionStorage` 存储的数据才会删除。
@@ -692,7 +692,7 @@ console.log(num)
-#### 答案: B
+#### 答案:B
使用 `var` 关键字,你可以用相同的名称声明多个变量。然后变量将保存最新的值。
@@ -723,7 +723,7 @@ set.has(1)
-#### 答案: C
+#### 答案:C
所有对象的键(不包括 Symbol)在底层都是字符串,即使你自己没有将其作为字符串输入。这就是为什么 `obj.hasOwnProperty('1')` 也返回 `true`。
@@ -749,7 +749,7 @@ console.log(obj)
-#### 答案: C
+#### 答案:C
如果你有两个名称相同的键,则键会被替换掉。它仍然位于第一个键出现的位置,但是值是最后出现那个键的值。
@@ -767,7 +767,7 @@ console.log(obj)
-#### 答案: A
+#### 答案:A
基本执行上下文是全局执行上下文:它是代码中随处可访问的内容。
@@ -793,7 +793,7 @@ for (let i = 1; i < 5; i++) {
-#### 答案: C
+#### 答案:C
如果某个条件返回 `true`,则 `continue` 语句跳过本次迭代。
@@ -822,9 +822,9 @@ name.giveLydiaPizza()
-#### 答案: A
+#### 答案:A
-`String` 是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象)都可以访问该方法!
+`String` 是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象) 都可以访问该方法!
-#### 答案: B
+#### 答案:B
对象的键被自动转换为字符串。我们试图将一个对象 `b` 设置为对象 `a` 的键,且相应的值为 `123`。
@@ -885,13 +885,13 @@ baz()
-#### 答案: B
+#### 答案:B
我们有一个 `setTimeout` 函数,并首先调用它。然而,它是最后打印日志的。
这是因为在浏览器中,我们不仅有运行时引擎,还有一个叫做 `WebAPI` 的东西。`WebAPI` 提供了 `setTimeout` 函数,也包含其他的,例如 DOM。
-将 _callback_ 推送到 WebAPI 后,`setTimeout` 函数本身(但不是回调!)将从栈中弹出。
+将 _callback_ 推送到 WebAPI 后,`setTimeout` 函数本身 (但不是回调!) 将从栈中弹出。
-#### 答案: C
+#### 答案:C
导致事件的最深嵌套的元素是事件的 target。你可以通过 `event.stopPropagation` 来停止冒泡。
@@ -965,7 +965,7 @@ WebAPI 不能随时向栈内添加内容。相反,它将回调函数推到名
-#### 答案: A
+#### 答案:A
如果我们点击 `p`,我们会看到两个日志:`p` 和 `div`。在事件传播期间,有三个阶段:捕获、目标和冒泡。默认情况下,事件处理程序在冒泡阶段执行(除非将 `useCapture` 设置为 `true`)。它从嵌套最深的元素向外传播。
@@ -995,7 +995,7 @@ sayHi.bind(person, 21)
-#### 答案: D
+#### 答案:D
使用这两种方法,我们都可以传递我们希望 `this` 关键字引用的对象。但是,`.call` 是**立即执行**的。
@@ -1024,11 +1024,11 @@ typeof sayHi()
-#### 答案: B
+#### 答案:B
-`sayHi` 方法返回的是立即执行函数(IIFE)的返回值.此立即执行函数的返回值是 `0`, 类型是 `number`
+`sayHi` 方法返回的是立即执行函数 (IIFE) 的返回值。此立即执行函数的返回值是 `0`,类型是 `number`
-参考:只有7种内置类型:`null`,`undefined`,`boolean`,`number`,`string`,`object`, `symbol` 和 `bigint`。 ``function`` 不是一种类型,函数是对象,它的类型是``object``。
+参考:只有 7 种内置类型:`null`,`undefined`,`boolean`,`number`,`string`,`object`, `symbol` 和 `bigint`。``function`` 不是一种类型,函数是对象,它的类型是``object``。
-#### 答案: A
+#### 答案:A
-只有 8 种 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy) 值:
+只有 8 种 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy) 值:
@@ -1069,7 +1069,7 @@ undefined
- `-0`
- `0n` (BigInt(0))
-`Function` 构造函数, 比如 `new Number` 和 `new Boolean`,是 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。
+`Function` 构造函数,比如 `new Number` 和 `new Boolean`,是 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。
-#### 答案: B
+#### 答案:B
`typeof 1` 返回 `"number"`。
`typeof "number"` 返回 `"string"`。
@@ -1116,9 +1116,9 @@ console.log(numbers)
-#### 答案: C
+#### 答案:C
-当你为数组设置超过数组长度的值的时候, JavaScript 会创建名为 "empty slots" 的东西。它们的值实际上是 `undefined`。你会看到以下场景:
+当你为数组设置超过数组长度的值的时候,JavaScript 会创建名为 "empty slots" 的东西。它们的值实际上是 `undefined`。你会看到以下场景:
`[1, 2, 3, 7 x empty, 11]`
@@ -1153,13 +1153,13 @@ console.log(numbers)
-#### 答案: A
+#### 答案:A
-`catch` 代码块接收参数 `x`。当我们传递参数时,这与之前定义的变量 `x` 不同 。这个 `x` 是属于 `catch` 块级作用域的。
+`catch` 代码块接收参数 `x`。当我们传递参数时,这与之前定义的变量 `x` 不同。这个 `x` 是属于 `catch` 块级作用域的。
然后,我们将块级作用域中的变量赋值为 `1`,同时也设置了变量 `y` 的值。现在,我们打印块级作用域中的变量 `x`,值为 `1`。
-`catch` 块之外的变量 `x` 的值仍为 `undefined`, `y` 的值为 `2`。当我们在 `catch` 块之外执行 `console.log(x)` 时,返回 `undefined`,`y` 返回 `2`。
+`catch` 块之外的变量 `x` 的值仍为 `undefined`,`y` 的值为 `2`。当我们在 `catch` 块之外执行 `console.log(x)` 时,返回 `undefined`,`y` 返回 `2`。
-#### 答案: A
+#### 答案:A
JavaScript 只有基本类型和对象。
@@ -1206,10 +1206,10 @@ JavaScript 只有基本类型和对象。
-#### 答案: C
+#### 答案:C
-`[1, 2]`是初始值。初始值将会作为首次调用时第一个参数 `acc` 的值。在第一次执行时, `acc` 的值是 `[1, 2]`, `cur` 的值是 `[0, 1]`。合并它们,结果为 `[1, 2, 0, 1]`。
-第二次执行, `acc` 的值是 `[1, 2, 0, 1]`, `cur` 的值是 `[2, 3]`。合并它们,最终结果为 `[1, 2, 0, 1, 2, 3]`
+`[1, 2]`是初始值。初始值将会作为首次调用时第一个参数 `acc` 的值。在第一次执行时,`acc` 的值是 `[1, 2]`,`cur` 的值是 `[0, 1]`。合并它们,结果为 `[1, 2, 0, 1]`。
+第二次执行,`acc` 的值是 `[1, 2, 0, 1]`,`cur` 的值是 `[2, 3]`。合并它们,最终结果为 `[1, 2, 0, 1, 2, 3]`
-#### 答案: B
+#### 答案:B
-`null` 是 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy)。 `!null` 的值是 `true`。 `!true` 的值是 `false`。
+`null` 是 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy)。`!null` 的值是 `true`。`!true` 的值是 `false`。
-`""` 是 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy)。 `!""` 的值是 `true`。 `!true` 的值是 `false`。
+`""` 是 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy)。`!""` 的值是 `true`。`!true` 的值是 `false`。
-`1` 是 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。 `!1` 的值是 `false`。 `!false` 的值是 `true`。
+`1` 是 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。`!1` 的值是 `false`。`!false` 的值是 `true`。
-#### 答案: A
+#### 答案:A
`setInterval` 返回一个唯一的 id。此 id 可被用于 `clearInterval` 函数来取消定时。
@@ -1282,7 +1282,7 @@ setInterval(() => console.log('Hi'), 1000)
-#### 答案: A
+#### 答案:A
string 类型是可迭代的。扩展运算符将迭代的每个字符映射成一个元素。
@@ -1291,7 +1291,7 @@ string 类型是可迭代的。扩展运算符将迭代的每个字符映射成
---
-###### 44. 输出是什么?
+###### 44. 输出是什么?
```javascript
function* generator(i) {
@@ -1313,9 +1313,9 @@ console.log(gen.next().value);
-#### 答案: C
+#### 答案:C
-一般的函数在执行之后是不能中途停下的。但是,生成器函数却可以中途“停下”,之后可以再从停下的地方继续。当生成器遇到`yield`关键字的时候,会生成`yield`后面的值。注意,生成器在这种情况下不 _返回_ (_return_ )值,而是 _生成_ (_yield_)值。
+一般的函数在执行之后是不能中途停下的。但是,生成器函数却可以中途“停下”,之后可以再从停下的地方继续。当生成器遇到`yield`关键字的时候,会生成`yield`后面的值。注意,生成器在这种情况下不 _返回_ (_return_ ) 值,而是 _生成_ (_yield_) 值。
首先,我们用`10`作为参数`i`来初始化生成器函数。然后使用`next()`方法一步步执行生成器。第一次执行生成器的时候,`i`的值为`10`,遇到第一个`yield`关键字,它要生成`i`的值。此时,生成器“暂停”,生成了`10`。
@@ -1325,7 +1325,7 @@ console.log(gen.next().value);
-#### 答案: B
+#### 答案:B
-当我们向`Promise.race`方法中传入多个`Promise`时,会进行 _优先_ 解析。在这个例子中,我们用`setTimeout`给`firstPromise`和`secondPromise`分别设定了500ms和100ms的定时器。这意味着`secondPromise`会首先解析出字符串`two`。那么此时`res`参数即为`two`,是为输出结果。
+当我们向`Promise.race`方法中传入多个`Promise`时,会进行 _优先_ 解析。在这个例子中,我们用`setTimeout`给`firstPromise`和`secondPromise`分别设定了 500ms 和 100ms 的定时器。这意味着`secondPromise`会首先解析出字符串`two`。那么此时`res`参数即为`two`,是为输出结果。
-#### 答案: D
+#### 答案:D
首先我们声明了一个拥有`name`属性的对象 `person`。
-#### 答案: B
+#### 答案:B
-在`for-in`循环中,我们可以通过对象的key来进行迭代,也就是这里的`name`和`age`。在底层,对象的key都是字符串(如果他们不是Symbol的话)。在每次循环中,我们将`item`设定为当前遍历到的key.所以一开始,`item`是`name`,之后 `item`输出的则是`age`。
+在`for-in`循环中,我们可以通过对象的 key 来进行迭代,也就是这里的`name`和`age`。在底层,对象的 key 都是字符串(如果他们不是 Symbol 的话)。在每次循环中,我们将`item`设定为当前遍历到的 key.所以一开始,`item`是`name`,之后 `item`输出的则是`age`。
-#### 答案: B
+#### 答案:B
当所有运算符的 _优先级_ 相同时,计算表达式需要确定运算符的结合顺序,即从右到左还是从左往右。在这个例子中,我们只有一类运算符`+`,对于加法来说,结合顺序就是从左到右。
`3 + 4`首先计算,得到数字`7`.
-由于类型的强制转换,`7 + '5'`的结果是`"75"`. JavaScript将`7`转换成了字符串,可以参考问题15.我们可以用`+`号把两个字符串连接起来。 `"7" + "5"` 就得到了`"75"`.
+由于类型的强制转换,`7 + '5'`的结果是`"75"`. JavaScript 将`7`转换成了字符串,可以参考问题 15.我们可以用`+`号把两个字符串连接起来。`"7" + "5"` 就得到了`"75"`.
-#### 答案: C
+#### 答案:C
-只返回了字符串中第一个字母. 设定了 _进制_ 后 (也就是第二个参数,指定需要解析的数字是什么进制: 十进制、十六机制、八进制、二进制等等……),`parseInt` 检查字符串中的字符是否合法. 一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。
+只返回了字符串中第一个字母。设定了 _进制_ 后 (也就是第二个参数,指定需要解析的数字是什么进制:十进制、十六机制、八进制、二进制等等……),`parseInt` 检查字符串中的字符是否合法。一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。
`*`就是不合法的数字字符。所以只解析到`"7"`,并将其解析为十进制的`7`. `num`的值即为`7`.
@@ -1478,7 +1478,7 @@ const num = parseInt("7*6", 10);
---
-###### 50. 输出是什么?
+###### 50. 输出是什么?
```javascript
[1, 2, 3].map(num => {
@@ -1495,9 +1495,9 @@ const num = parseInt("7*6", 10);
-#### 答案: C
+#### 答案:C
-对数组进行映射的时候,`num`就是当前循环到的元素. 在这个例子中,所有的映射都是number类型,所以if中的判断`typeof num === "number"`结果都是`true`.map函数创建了新数组并且将函数的返回值插入数组。
+对数组进行映射的时候,`num`就是当前循环到的元素。在这个例子中,所有的映射都是 number 类型,所以 if 中的判断`typeof num === "number"`结果都是`true`.map 函数创建了新数组并且将函数的返回值插入数组。
但是,没有任何值返回。当函数没有返回任何值时,即默认返回`undefined`.对数组中的每一个元素来说,函数块都得到了这个返回值,所以结果中每一个元素都是`undefined`.
@@ -1506,7 +1506,7 @@ const num = parseInt("7*6", 10);
---
-###### 51. 输出的是什么?
+###### 51. 输出的是什么?
```javascript
function getInfo(member, year) {
@@ -1530,20 +1530,20 @@ console.log(person, birthYear);
-#### 答案: A
+#### 答案:A
-普通参数都是 _值_ 传递的,而对象则不同,是 _引用_ 传递。所以说,`birthYear`是值传递,因为他是个字符串而不是对象。当我们对参数进行值传递时,会创建一份该值的 _复制_ 。(可以参考问题46)
+普通参数都是 _值_ 传递的,而对象则不同,是 _引用_ 传递。所以说,`birthYear`是值传递,因为他是个字符串而不是对象。当我们对参数进行值传递时,会创建一份该值的 _复制_。(可以参考问题 46)
变量`birthYear`有一个对`"1997"`的引用,而传入的参数也有一个对`"1997"`的引用,但二者的引用并不相同。当我们通过给 `year`赋值`"1998"`来更新`year`的值的时候我们只是更新了`year`(的引用)。此时`birthYear`仍然是`"1997"`.
-而`person`是个对象。参数`member`引用与之 _相同的_ 对象。当我们修改`member`所引用对象的属性时,`person`的相应属性也被修改了,因为他们引用了相同的对象. `person`的 `name`属性也变成了 `"Lydia"`.
+而`person`是个对象。参数`member`引用与之 _相同的_ 对象。当我们修改`member`所引用对象的属性时,`person`的相应属性也被修改了,因为他们引用了相同的对象。`person`的 `name`属性也变成了 `"Lydia"`.
-#### 答案: D
+#### 答案:D
-通过`throw`语句,我么可以创建自定义错误。 而通过它,我们可以抛出异常。异常可以是一个字符串, 一个 数字, 一个 布尔类型 或者是一个 对象。在本例中,我们的异常是字符串`'Hello world'`.
+通过`throw`语句,我么可以创建自定义错误。而通过它,我们可以抛出异常。异常可以是一个字符串,一个 数字,一个 布尔类型 或者是一个 对象。在本例中,我们的异常是字符串`'Hello world'`.
通过 `catch`语句,我们可以设定当`try`语句块中抛出异常后应该做什么处理。在本例中抛出的异常是字符串`'Hello world'`. `e`就是这个字符串,因此被输出。最终结果就是`'Oh an error: Hello world'`.
@@ -1581,7 +1581,7 @@ sayHi();
---
-###### 53. 输出是什么?
+###### 53. 输出是什么?
```javascript
function Car() {
@@ -1601,7 +1601,7 @@ console.log(myCar.make);
-#### 答案: B
+#### 答案:B
返回属性的时候,属性的值等于 _返回的_ 值,而不是构造函数中设定的值。我们返回了字符串 `"Maserati"`,所以 `myCar.make`等于`"Maserati"`.
@@ -1610,7 +1610,7 @@ console.log(myCar.make);
---
-###### 54. 输出是什么?
+###### 54. 输出是什么?
```javascript
(() => {
@@ -1629,27 +1629,27 @@ console.log(typeof y);
-#### 答案: A
+#### 答案:A
-`let x = y = 10;` 是下面这个表达式的缩写:
+`let x = y = 10;` 是下面这个表达式的缩写:
```javascript
y = 10;
let x = y;
```
-我们设定`y`等于`10`时,我们实际上增加了一个属性`y`给全局对象(浏览器里的`window`, Nodejs里的`global`)。在浏览器中, `window.y`等于`10`.
+我们设定`y`等于`10`时,我们实际上增加了一个属性`y`给全局对象 (浏览器里的`window`, Nodejs 里的`global`)。在浏览器中,`window.y`等于`10`.
-然后我们声明了变量`x`等于`y`,也是`10`.但变量是使用 `let`声明的,它只作用于 _块级作用域_, 仅在声明它的块中有效;就是案例中的立即调用表达式(IIFE)。使用`typeof`操作符时, 操作值 `x`没有被定义:因为我们在`x`声明块的外部,无法调用它。这就意味着`x`未定义。未分配或是未声明的变量类型为`"undefined"`. `console.log(typeof x)`返回`"undefined"`.
+然后我们声明了变量`x`等于`y`,也是`10`.但变量是使用 `let`声明的,它只作用于 _块级作用域_,仅在声明它的块中有效;就是案例中的立即调用表达式 (IIFE)。使用`typeof`操作符时,操作值 `x`没有被定义:因为我们在`x`声明块的外部,无法调用它。这就意味着`x`未定义。未分配或是未声明的变量类型为`"undefined"`. `console.log(typeof x)`返回`"undefined"`.
-而我们创建了全局变量`y`,并且设定`y`等于`10`.这个值在我们的代码各处都访问的到。 `y`已经被定义了,而且有一个`"number"`类型的值。 `console.log(typeof y)`返回`"number"`.
+而我们创建了全局变量`y`,并且设定`y`等于`10`.这个值在我们的代码各处都访问的到。`y`已经被定义了,而且有一个`"number"`类型的值。`console.log(typeof y)`返回`"number"`.
-#### 答案: A
+#### 答案:A
-我们可以用`delete`关键字删除对象的属性,对原型也是适用的。删除了原型的属性后,该属性在原型链上就不可用了。在本例中,函数`bark`在执行了`delete Dog.prototype.bark`后不可用, 然而后面的代码还在调用它。
+我们可以用`delete`关键字删除对象的属性,对原型也是适用的。删除了原型的属性后,该属性在原型链上就不可用了。在本例中,函数`bark`在执行了`delete Dog.prototype.bark`后不可用,然而后面的代码还在调用它。
当我们尝试调用一个不存在的函数时`TypeError`异常会被抛出。在本例中就是 `TypeError: pet.bark is not a function`,因为`pet.bark`是`undefined`.
@@ -1690,7 +1690,7 @@ pet.bark();
---
-###### 56. 输出是什么?
+###### 56. 输出是什么?
```javascript
const set = new Set([1, 1, 2, 3, 4]);
@@ -1706,7 +1706,7 @@ console.log(set);
-#### 答案: D
+#### 答案:D
`Set`对象是独一无二的值的集合:也就是说同一个值在其中仅出现一次。
@@ -1717,7 +1717,7 @@ console.log(set);
---
-###### 57. 输出是什么?
+###### 57. 输出是什么?
```javascript
// counter.js
@@ -1742,18 +1742,18 @@ console.log(myCounter);
-#### 答案: C
+#### 答案:C
-引入的模块是 _只读_ 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。
+引入的模块是 _只读_ 的:你不能修改引入的模块。只有导出他们的模块才能修改其值。
-当我们给`myCounter`增加一个值的时候会抛出一个异常: `myCounter`是只读的,不能被修改。
+当我们给`myCounter`增加一个值的时候会抛出一个异常:`myCounter`是只读的,不能被修改。
-#### 答案: A
+#### 答案:A
-`delete`操作符返回一个布尔值: `true`指删除成功,否则返回`false`. 但是通过 `var`, `const` 或 `let` 关键字声明的变量无法用 `delete` 操作符来删除。
+`delete`操作符返回一个布尔值:`true`指删除成功,否则返回`false`. 但是通过 `var`, `const` 或 `let` 关键字声明的变量无法用 `delete` 操作符来删除。
-`name`变量由`const`关键字声明,所以删除不成功:返回 `false`. 而我们设定`age`等于`21`时,我们实际上添加了一个名为`age`的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以`delete age`返回`true`.
+`name`变量由`const`关键字声明,所以删除不成功:返回 `false`. 而我们设定`age`等于`21`时,我们实际上添加了一个名为`age`的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以`delete age`返回`true`.
-#### 答案: C
+#### 答案:C
我们可以通过解构赋值来解析来自对象的数组或属性的值,比如说:
@@ -1809,7 +1809,7 @@ console.log(y);
-#### 答案: B
+#### 答案:B
扩展运算符`...`为对象的组合提供了可能。你可以复制对象中的键值对,然后把它们加到另一个对象里去。在本例中,我们复制了`user`对象键值对,然后把它们加入到`admin`对象中。`admin`对象就拥有了这些键值对,所以结果为`{ admin: true, name: "Lydia", age: 21 }`.
@@ -1850,7 +1850,7 @@ console.log(admin);
---
-###### 61. 输出是什么?
+###### 61. 输出是什么?
```javascript
const person = { name: "Lydia" };
@@ -1869,9 +1869,9 @@ console.log(Object.keys(person));
-#### 答案: B
+#### 答案:B
-通过`defineProperty`方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用`defineProperty`方法给对象添加了一个属性之后,属性默认为 _不可枚举(not enumerable)_. `Object.keys`方法仅返回对象中 _可枚举(enumerable)_ 的属性,因此只剩下了`"name"`.
+通过`defineProperty`方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用`defineProperty`方法给对象添加了一个属性之后,属性默认为 _不可枚举 (not enumerable)_. `Object.keys`方法仅返回对象中 _可枚举 (enumerable)_ 的属性,因此只剩下了`"name"`.
用`defineProperty`方法添加的属性默认不可变。你可以通过`writable`, `configurable` 和 `enumerable`属性来改变这一行为。这样,`defineProperty`方法可以让您更好地控制要添加到对象的属性。
@@ -1880,7 +1880,7 @@ console.log(Object.keys(person));
---
-###### 62. 输出是什么?
+###### 62. 输出是什么?
```javascript
const settings = {
@@ -1901,21 +1901,21 @@ console.log(data);
-#### 答案: A
+#### 答案:A
-`JSON.stringify`的第二个参数是 _替代者(replacer)_. 替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。
+`JSON.stringify`的第二个参数是 _替代者 (replacer)_. 替代者 (replacer) 可以是个函数或数组,用以控制哪些值如何被转换为字符串。
-如果替代者(replacer)是个 _数组_ ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为`"level"` 和 `"health"` 的属性被包括进来, `"username"`则被排除在外。 `data` 就等于 `"{"level":19, "health":90}"`.
+如果替代者 (replacer) 是个 _数组_,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为`"level"` 和 `"health"` 的属性被包括进来,`"username"`则被排除在外。`data` 就等于 `"{"level":19, "health":90}"`.
-而如果替代者(replacer)是个 _函数_,这个函数将被对象的每个属性都调用一遍。
-函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为`undefined`,则该属性会被排除在外。
+而如果替代者 (replacer) 是个 _函数_,这个函数将被对象的每个属性都调用一遍。
+函数返回的值会成为这个属性的值,最终体现在转化后的 JSON 字符串中(译者注:Chrome 下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出 JSON 字符串),而如果返回值为`undefined`,则该属性会被排除在外。
-#### 答案: A
+#### 答案:A
-一元操作符 `++` _先返回_ 操作值, _再累加_ 操作值。`num1`的值是`10`, 因为`increaseNumber`函数首先返回`num`的值,也就是`10`,随后再进行 `num`的累加。
+一元操作符 `++` _先返回_ 操作值,_再累加_ 操作值。`num1`的值是`10`,因为`increaseNumber`函数首先返回`num`的值,也就是`10`,随后再进行 `num`的累加。
-`num2`是`10`因为我们将 `num1`传入`increasePassedNumber`. `number`等于`10`(`num1`的值。同样道理,`++` _先返回_ 操作值, _再累加_ 操作值。) `number`是`10`,所以`num2`也是`10`.
+`num2`是`10`因为我们将 `num1`传入`increasePassedNumber`. `number`等于`10`(`num1`的值。同样道理,`++` _先返回_ 操作值,_再累加_ 操作值。)`number`是`10`,所以`num2`也是`10`.
-#### 答案: C
+#### 答案:C
-在ES6中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为 `"undefined"` ,那么参数的值将是默认值。上述例子中,我们将 `value` 对象进行了解构并传到一个新对象中,因此 `x` 的默认值为 `{number:10}` 。
+在 ES6 中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为 `"undefined"`,那么参数的值将是默认值。上述例子中,我们将 `value` 对象进行了解构并传到一个新对象中,因此 `x` 的默认值为 `{number:10}`。
-默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用 `multiply` 函数且不传递值,那么每一次 `x` 的默认值都为 `{number:10}` ,因此打印出该数字的乘积值为`20`。
+默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用 `multiply` 函数且不传递值,那么每一次 `x` 的默认值都为 `{number:10}`,因此打印出该数字的乘积值为`20`。
-第三次调用 `multiply` 时,我们传递了一个参数,即对象`value`。 `*=`运算符实际上是`x.number = x.number * 2`的简写,我们修改了`x.number`的值,并打印出值`20`。
+第三次调用 `multiply` 时,我们传递了一个参数,即对象`value`。`*=`运算符实际上是`x.number = x.number * 2`的简写,我们修改了`x.number`的值,并打印出值`20`。
-第四次,我们再次传递`value`对象。 `x.number`之前被修改为`20`,所以`x.number * = 2`打印为`40`。
+第四次,我们再次传递`value`对象。`x.number`之前被修改为`20`,所以`x.number * = 2`打印为`40`。
-#### 答案: D
+#### 答案:D
-`reducer` 函数接收4个参数:
+`reducer` 函数接收 4 个参数:
1. Accumulator (acc) (累计器)
2. Current Value (cur) (当前值)
@@ -2012,21 +2012,21 @@ multiply(value);
`reducer` 函数的返回值将会分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。
-`reducer` 函数还有一个可选参数`initialValue`, 该参数将作为第一次调用回调函数时的第一个参数的值。如果没有提供`initialValue`,则将使用数组中的第一个元素。
+`reducer` 函数还有一个可选参数`initialValue`,该参数将作为第一次调用回调函数时的第一个参数的值。如果没有提供`initialValue`,则将使用数组中的第一个元素。
-在上述例子,`reduce`方法接收的第一个参数(Accumulator)是`x`, 第二个参数(Current Value)是`y`。
+在上述例子,`reduce`方法接收的第一个参数 (Accumulator) 是`x`,第二个参数 (Current Value) 是`y`。
在第一次调用时,累加器`x`为`1`,当前值`“y”`为`2`,打印出累加器和当前值:`1`和`2`。
-例子中我们的回调函数没有返回任何值,只是打印累加器的值和当前值。如果函数没有返回值,则默认返回`undefined`。 在下一次调用时,累加器为`undefined`,当前值为“3”, 因此`undefined`和`3`被打印出。
+例子中我们的回调函数没有返回任何值,只是打印累加器的值和当前值。如果函数没有返回值,则默认返回`undefined`。在下一次调用时,累加器为`undefined`,当前值为“3”,因此`undefined`和`3`被打印出。
-在第四次调用时,回调函数依然没有返回值。 累加器再次为 `undefined` ,当前值为“4”。 `undefined`和`4`被打印出。
+在第四次调用时,回调函数依然没有返回值。累加器再次为 `undefined`,当前值为“4”。`undefined`和`4`被打印出。
-#### 答案: B
+#### 答案:B
-在子类中,在调用`super`之前不能访问到`this`关键字。 如果这样做,它将抛出一个`ReferenceError`:1和4将引发一个引用错误。
+在子类中,在调用`super`之前不能访问到`this`关键字。如果这样做,它将抛出一个`ReferenceError`:1 和 4 将引发一个引用错误。
-使用`super`关键字,需要用给定的参数来调用父类的构造函数。 父类的构造函数接收`name`参数,因此我们需要将`name`传递给`super`。
+使用`super`关键字,需要用给定的参数来调用父类的构造函数。父类的构造函数接收`name`参数,因此我们需要将`name`传递给`super`。
-`Labrador`类接收两个参数,`name`参数是由于它继承了`Dog`,`size`作为`Labrador`类的额外属性,它们都需要传递给`Labrador`的构造函数,因此使用构造函数2正确完成。
+`Labrador`类接收两个参数,`name`参数是由于它继承了`Dog`,`size`作为`Labrador`类的额外属性,它们都需要传递给`Labrador`的构造函数,因此使用构造函数 2 正确完成。
-#### 答案: B
+#### 答案:B
`import`命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。
-这是CommonJS中`require()`和`import`之间的区别。使用`require()`,您可以在运行代码时根据需要加载依赖项。 如果我们使用`require`而不是`import`,`running index.js`,`running sum.js`,`3`会被依次打印。
+这是 CommonJS 中`require()`和`import`之间的区别。使用`require()`,您可以在运行代码时根据需要加载依赖项。如果我们使用`require`而不是`import`,`running index.js`,`running sum.js`,`3`会被依次打印。
-#### 答案: A
+#### 答案:A
-每个`Symbol`都是完全唯一的。传递给`Symbol`的参数只是给`Symbol`的一个描述。 `Symbol`的值不依赖于传递的参数。 当我们测试相等时,我们创建了两个全新的符号:第一个`Symbol('foo')`,第二个`Symbol('foo')`, 这两个值是唯一的,彼此不相等,因此返回`false`。
+每个`Symbol`都是完全唯一的。传递给`Symbol`的参数只是给`Symbol`的一个描述。`Symbol`的值不依赖于传递的参数。当我们测试相等时,我们创建了两个全新的符号:第一个`Symbol('foo')`,第二个`Symbol('foo')`,这两个值是唯一的,彼此不相等,因此返回`false`。
-#### 答案: C
+#### 答案:C
-使用`padStart`方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。字符串`Lydia Hallie`的长度为`12`, 因此`name.padStart(13)`在字符串的开头只会插入1(`13 - 12 = 1`)个空格。
+使用`padStart`方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。字符串`Lydia Hallie`的长度为`12`,因此`name.padStart(13)`在字符串的开头只会插入 1(`13 - 12 = 1`)个空格。
如果传递给`padStart`方法的参数小于字符串的长度,则不会添加填充。
@@ -2163,7 +2163,7 @@ console.log(name.padStart(2))
---
-###### 70. 输出什么?
+###### 70. 输出什么?
```javascript
console.log("🥑" + "💻");
@@ -2177,9 +2177,9 @@ console.log("🥑" + "💻");
-#### 答案: A
+#### 答案:A
-使用`+`运算符,您可以连接字符串。 上述情况,我们将字符串`“🥑”`与字符串`”💻“`连接起来,产生`”🥑💻“`。
+使用`+`运算符,您可以连接字符串。上述情况,我们将字符串`“🥑”`与字符串`”💻“`连接起来,产生`”🥑💻“`。
-#### 答案: C
+#### 答案:C
-`generator`函数在遇到`yield`关键字时会“暂停”其执行。 首先,我们需要让函数产生字符串`Do you love JavaScript?`,这可以通过调用`game.next().value`来完成。上述函数的第一行就有一个`yield`关键字,那么运行立即停止了,`yield`表达式本身没有返回值,或者说总是返回`undefined`, 这意味着此时变量 `答案` 为`undefined`
+`generator`函数在遇到`yield`关键字时会“暂停”其执行。首先,我们需要让函数产生字符串`Do you love JavaScript?`,这可以通过调用`game.next().value`来完成。上述函数的第一行就有一个`yield`关键字,那么运行立即停止了,`yield`表达式本身没有返回值,或者说总是返回`undefined`,这意味着此时变量 `答案` 为`undefined`
`next`方法可以带一个参数,该参数会被当作上一个 `yield` 表达式的返回值。当我们调用`game.next("Yes").value`时,先前的 `yield` 的返回值将被替换为传递给`next()`函数的参数`"Yes"`。此时变量 `答案` 被赋值为 `"Yes"`,`if`语句返回`false`,所以`JavaScript loves you back ❤️`被打印。
@@ -2221,7 +2221,7 @@ console.log(/* 2 */); // JavaScript loves you back ❤️
---
-###### 72. 输出什么?
+###### 72. 输出什么?
```javascript
console.log(String.raw`Hello\nworld`);
@@ -2235,7 +2235,7 @@ console.log(String.raw`Hello\nworld`);
-#### 答案: C
+#### 答案:C
`String.raw`函数是用来获取一个模板字符串的原始字符串的,它返回一个字符串,其中忽略了转义符(`\n`,`\v`,`\t`等)。但反斜杠可能造成问题,因为你可能会遇到下面这种类似情况:
@@ -2261,7 +2261,7 @@ String.raw`C:\Documents\Projects\table.html`
---
-###### 73. 输出什么?
+###### 73. 输出什么?
```javascript
async function getData() {
@@ -2280,9 +2280,9 @@ console.log(data);
-#### 答案: C
+#### 答案:C
-异步函数始终返回一个promise。`await`仍然需要等待promise的解决:当我们调用`getData()`并将其赋值给`data`,此时`data`为`getData`方法返回的一个挂起的promise,该promise并没有解决。
+异步函数始终返回一个 promise。`await`仍然需要等待 promise 的解决:当我们调用`getData()`并将其赋值给`data`,此时`data`为`getData`方法返回的一个挂起的 promise,该 promise 并没有解决。
如果我们想要访问已解决的值`"I made it!"`,可以在`data`上使用`.then()`方法:
@@ -2295,7 +2295,7 @@ console.log(data);
---
-###### 74. 输出什么?
+###### 74. 输出什么?
```javascript
function addToList(item, list) {
@@ -2314,18 +2314,18 @@ console.log(result);
-#### 答案: B
+#### 答案:B
-`push()`方法返回新数组的长度。一开始,数组包含一个元素(字符串`"banana"`),长度为1。 在数组中添加字符串`"apple"`后,长度变为2,并将从`addToList`函数返回。
+`push()`方法返回新数组的长度。一开始,数组包含一个元素(字符串`"banana"`),长度为 1。在数组中添加字符串`"apple"`后,长度变为 2,并将从`addToList`函数返回。
-`push`方法修改原始数组,如果你想从函数返回数组而不是数组长度,那么应该在push `item`之后返回`list`。
+`push`方法修改原始数组,如果你想从函数返回数组而不是数组长度,那么应该在 push `item`之后返回`list`。
-#### 答案: B
+#### 答案:B
`Object.freeze`使得无法添加、删除或修改对象的属性(除非属性的值是另一个对象)。
当我们创建变量`shape`并将其设置为等于冻结对象`box`时,`shape`指向的也是冻结对象。你可以使用`Object.isFrozen`检查一个对象是否被冻结,上述情况,`Object.isFrozen(shape)`将返回`true`。
-由于`shape`被冻结,并且`x`的值不是对象,所以我们不能修改属性`x`。 `x`仍然等于`10`,`{x:10,y:20}`被打印。
+由于`shape`被冻结,并且`x`的值不是对象,所以我们不能修改属性`x`。`x`仍然等于`10`,`{x:10,y:20}`被打印。
-注意,上述例子我们对属性`x`进行修改,可能会导致抛出TypeError异常(最常见但不仅限于严格模式下时)。
+注意,上述例子我们对属性`x`进行修改,可能会导致抛出 TypeError 异常(最常见但不仅限于严格模式下时)。
-#### 答案: D
+#### 答案:D
当我们从右侧的对象解构属性`name`时,我们将其值`Lydia`分配给名为`myName`的变量。
-使用`{name:myName}`,我们是在告诉JavaScript我们要创建一个名为`myName`的新变量,并且其值是右侧对象的`name`属性的值。
+使用`{name:myName}`,我们是在告诉 JavaScript 我们要创建一个名为`myName`的新变量,并且其值是右侧对象的`name`属性的值。
当我们尝试打印`name`,一个未定义的变量时,就会引发`ReferenceError`。
@@ -2389,7 +2389,7 @@ console.log(name);
---
-###### 77. 以下是个纯函数么?
+###### 77. 以下是个纯函数么?
```javascript
function sum(a, b) {
@@ -2403,9 +2403,9 @@ function sum(a, b) {
-#### 答案: A
+#### 答案:A
-纯函数在相同的输入值时,需产生相同的输出,其输出的结果,与输入值以外的其他隐藏信息或状态无关,也和由I/O设备产生的外部输出无关。
+纯函数在相同的输入值时,需产生相同的输出,其输出的结果,与输入值以外的其他隐藏信息或状态无关,也和由 I/O 设备产生的外部输出无关。
纯函数不会产生副作用。
纯函数与副作用的定义可参考:
@@ -2416,7 +2416,7 @@ https://zh.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E8%AE%A1%E7%AE%97%E6
---
-###### 78. 输出什么?
+###### 78. 输出什么?
```javascript
const add = () => {
@@ -2446,26 +2446,26 @@ console.log(addFunction(5 * 2));
-#### 答案: C
+#### 答案:C
-`add`函数是一个记忆函数。 通过记忆化,我们可以缓存函数的结果,以加快其执行速度。上述情况,我们创建一个`cache`对象,用于存储先前返回过的值。
+`add`函数是一个记忆函数。通过记忆化,我们可以缓存函数的结果,以加快其执行速度。上述情况,我们创建一个`cache`对象,用于存储先前返回过的值。
如果我们使用相同的参数多次调用`addFunction`函数,它首先检查缓存中是否已有该值,如果有,则返回缓存值,这将节省执行时间。如果没有,那么它将计算该值,并存储在缓存中。
我们用相同的值三次调用了`addFunction`函数:
-在第一次调用,`num`等于`10`时函数的值尚未缓存,if语句`num in cache`返回`false`,else块的代码被执行:`Calculated! 20`,并且其结果被添加到缓存对象,`cache`现在看起来像`{10:20}`。
+在第一次调用,`num`等于`10`时函数的值尚未缓存,if 语句`num in cache`返回`false`,else 块的代码被执行:`Calculated! 20`,并且其结果被添加到缓存对象,`cache`现在看起来像`{10:20}`。
-第二次,`cache`对象包含`10`的返回值。 if语句 `num in cache` 返回`true`,`From cache! 20`被打印。
+第二次,`cache`对象包含`10`的返回值。if 语句 `num in cache` 返回`true`,`From cache! 20`被打印。
-第三次,我们将`5 * 2`(值为10)传递给函数。 `cache`对象包含`10`的返回值。 if语句 `num in cache` 返回`true`,`From cache! 20`被打印。
+第三次,我们将`5 * 2`(值为 10) 传递给函数。`cache`对象包含`10`的返回值。if 语句 `num in cache` 返回`true`,`From cache! 20`被打印。
-#### 答案: A
+#### 答案:A
-通过`for-in`循环,我们可以遍历一个对象**自有的**、**继承的**、**可枚举的**、**非Symbol的**属性。 在数组中,可枚举属性是数组元素的“键”, 即它们的索引。 类似于下面这个对象:
+通过`for-in`循环,我们可以遍历一个对象**自有的**、**继承的**、**可枚举的**、**非 Symbol 的**属性。在数组中,可枚举属性是数组元素的“键”,即它们的索引。类似于下面这个对象:
`{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}`
其中键则是可枚举属性,因此 `0`,`1`,`2`,`3`被记录。
-通过`for-of`循环,我们可以迭代**可迭代对象**(包括 `Array`,`Map`,`Set`,`String`,`arguments`等)。当我们迭代数组时,在每次迭代中,不同属性的值将被分配给变量`item`, 因此`“☕”`,`“💻”`,`“🍷”`,`“🍫”`被打印。
+通过`for-of`循环,我们可以迭代**可迭代对象**(包括 `Array`,`Map`,`Set`,`String`,`arguments`等)。当我们迭代数组时,在每次迭代中,不同属性的值将被分配给变量`item`,因此`“☕”`,`“💻”`,`“🍷”`,`“🍫”`被打印。
-#### 答案: C
+#### 答案:C
-数组元素可以包含任何值。 数字,字符串,布尔值,对象,数组,`null`,`undeifned`, 以及其他表达式,如日期,函数和计算。
+数组元素可以包含任何值。数字,字符串,布尔值,对象,数组,`null`,`undefined`,以及其他表达式,如日期,函数和计算。
-元素将等于返回的值。 `1 + 2`返回`3`,`1 * 2`返回'2`,'1 / 2`返回`0.5`。
+元素将等于返回的值。`1 + 2`返回`3`,`1 * 2`返回'2`,'1 / 2`返回`0.5`。
-#### 答案: B
+#### 答案:B
-默认情况下,如果不给函数传参,参数的值将为`undefined`。 上述情况,我们没有给参数`name`传值。 `name`等于`undefined`,并被打印。
+默认情况下,如果不给函数传参,参数的值将为`undefined`。上述情况,我们没有给参数`name`传值。`name`等于`undefined`,并被打印。
-在ES6中,我们可以使用默认参数覆盖此默认的`undefined`值。 例如:
+在 ES6 中,我们可以使用默认参数覆盖此默认的`undefined`值。例如:
-`function sayHi(name =“Lydia”){...}`
+`function sayHi (name =“Lydia”){...}`
在这种情况下,如果我们没有传递值或者如果我们传递`undefined`,`name`总是等于字符串`Lydia`
@@ -2561,7 +2561,7 @@ console.log(sayHi())
---
-###### 82. 输出什么?
+###### 82. 输出什么?
```javascript
var status = "😎"
@@ -2589,17 +2589,17 @@ setTimeout(() => {
-#### 答案: B
+#### 答案:B
-`this`关键字的指向取决于使用它的位置。 在**函数**中,比如`getStatus`,`this`指向的是调用它的对象,上述例子中`data`对象调用了`getStatus`,因此`this`指向的就是`data`对象。 当我们打印`this.status`时,`data`对象的`status`属性被打印,即`"🥑"`。
+`this`关键字的指向取决于使用它的位置。在**函数**中,比如`getStatus`,`this`指向的是调用它的对象,上述例子中`data`对象调用了`getStatus`,因此`this`指向的就是`data`对象。当我们打印`this.status`时,`data`对象的`status`属性被打印,即`"🥑"`。
-使用`call`方法,可以更改`this`指向的对象。`data.getStatus.call(this)`是将`this`的指向由`data`对象更改为全局对象。在全局对象上,有一个名为`status`的变量,其值为`”😎“`。 因此打印`this.status`时,会打印`“😎”`。
+使用`call`方法,可以更改`this`指向的对象。`data.getStatus.call(this)`是将`this`的指向由`data`对象更改为全局对象。在全局对象上,有一个名为`status`的变量,其值为`”😎“`。因此打印`this.status`时,会打印`“😎”`。
-#### 答案: A
+#### 答案:A
-我们将变量`city`设置为等于`person`对象上名为`city`的属性的值。 这个对象上没有名为`city`的属性,因此变量`city`的值为`undefined`。
+我们将变量`city`设置为等于`person`对象上名为`city`的属性的值。这个对象上没有名为`city`的属性,因此变量`city`的值为`undefined`。
请注意,我们没有引用`person`对象本身,只是将变量`city`设置为等于`person`对象上`city`属性的当前值。
-然后,我们将`city`设置为等于字符串`“Amsterdam”`。 这不会更改person对象:没有对该对象的引用。
+然后,我们将`city`设置为等于字符串`“Amsterdam”`。这不会更改 person 对象:没有对该对象的引用。
因此打印`person`对象时,会返回未修改的对象。
@@ -2636,7 +2636,7 @@ console.log(person)
---
-###### 84. 输出什么?
+###### 84. 输出什么?
```javascript
function checkAge(age) {
@@ -2660,16 +2660,16 @@ console.log(checkAge(21))
-#### 答案: C
+#### 答案:C
-`const`和`let`声明的变量是具有**块级作用域**的,块是大括号(`{}`)之间的任何东西, 即上述情况`if / else`语句的花括号。 由于块级作用域,我们无法在声明的块之外引用变量,因此抛出`ReferenceError`。
+`const`和`let`声明的变量是具有**块级作用域**的,块是大括号(`{}`)之间的任何东西,即上述情况`if / else`语句的花括号。由于块级作用域,我们无法在声明的块之外引用变量,因此抛出`ReferenceError`。
-#### 答案: C
+#### 答案:C
-第二个`.then`中`res`的值等于前一个`.then`中的回调函数返回的值。 你可以像这样继续链接`.then`,将值传递给下一个处理程序。
+第二个`.then`中`res`的值等于前一个`.then`中的回调函数返回的值。你可以像这样继续链接`.then`,将值传递给下一个处理程序。
-#### 答案: A
+#### 答案:A
-使用逻辑非运算符`!`,将返回一个布尔值,使用`!! name`,我们可以确定`name`的值是真的还是假的。 如果`name`是真实的,那么`!name`返回`false`。 `!false`返回`true`。
+使用逻辑非运算符`!`,将返回一个布尔值,使用`!! name`,我们可以确定`name`的值是真的还是假的。如果`name`是真实的,那么`!name`返回`false`。`!false`返回`true`。
通过将`hasName`设置为`name`,可以将`hasName`设置为等于传递给`getName`函数的值,而不是布尔值`true`。
@@ -2723,7 +2723,7 @@ function getName(name) {
-#### 答案: B
+#### 答案:B
-可以使用方括号表示法获取字符串中特定索引的字符,字符串中的第一个字符具有索引0,依此类推。 在这种情况下,我们想要得到索引为0的元素,字符`'I'`被记录。
+可以使用方括号表示法获取字符串中特定索引的字符,字符串中的第一个字符具有索引 0,依此类推。在这种情况下,我们想要得到索引为 0 的元素,字符`'I'`被记录。
-请注意,IE7及更低版本不支持此方法。 在这种情况下,应该使用`.charAt()`
+请注意,IE7 及更低版本不支持此方法。在这种情况下,应该使用`.charAt()`
-#### 答案: B
+#### 答案:B
-您可以将默认参数的值设置为函数的另一个参数,只要另一个参数定义在其之前即可。 我们将值`10`传递给`sum`函数。 如果`sum`函数只接收1个参数,则意味着没有传递`num2`的值,这种情况下,`num1`的值等于传递的值`10`。 `num2`的默认值是`num1`的值,即`10`。 ```num1 + num2```返回`20`。
+您可以将默认参数的值设置为函数的另一个参数,只要另一个参数定义在其之前即可。我们将值`10`传递给`sum`函数。如果`sum`函数只接收 1 个参数,则意味着没有传递`num2`的值,这种情况下,`num1`的值等于传递的值`10`。`num2`的默认值是`num1`的值,即`10`。```num1 + num2```返回`20`。
如果您尝试将默认参数的值设置为后面定义的参数,则可能导致参数的值尚未初始化,从而引发错误。比如:
```js
@@ -2785,7 +2785,7 @@ test(3, 4) // 3 4
---
-###### 89. 输出什么?
+###### 89. 输出什么?
```javascript
// module.js
@@ -2806,18 +2806,18 @@ console.log(data)
-#### 答案: A
+#### 答案:A
-使用`import * as name`语法,我们将`module.js`文件中所有`export`导入到`index.js`文件中,并且创建了一个名为`data`的新对象。 在`module.js`文件中,有两个导出:默认导出和命名导出。 默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为`name`的变量,其值为字符串`“Lydia”`。
+使用`import * as name`语法,我们将`module.js`文件中所有`export`导入到`index.js`文件中,并且创建了一个名为`data`的新对象。在`module.js`文件中,有两个导出:默认导出和命名导出。默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为`name`的变量,其值为字符串`“Lydia”`。
-`data`对象具有默认导出的`default`属性,其他属性具有指定exports的名称及其对应的值。
+`data`对象具有默认导出的`default`属性,其他属性具有指定 exports 的名称及其对应的值。
-#### 答案: C
+#### 答案:C
类是构造函数的语法糖,如果用构造函数的方式来重写`Person`类则将是:
@@ -2855,7 +2855,7 @@ function Person() {
---
-###### 91. 输出什么?
+###### 91. 输出什么?
```javascript
let newList = [1, 2, 3].push(4)
@@ -2871,18 +2871,18 @@ console.log(newList.push(5))
-#### 答案: D
+#### 答案:D
-`.push`方法返回数组的长度,而不是数组本身! 通过将`newList`设置为`[1,2,3].push(4)`,实际上`newList`等于数组的新长度:`4`。
+`.push`方法返回数组的长度,而不是数组本身!通过将`newList`设置为`[1,2,3].push(4)`,实际上`newList`等于数组的新长度:`4`。
-然后,尝试在`newList`上使用`.push`方法。 由于`newList`是数值`4`,抛出TypeError。
+然后,尝试在`newList`上使用`.push`方法。由于`newList`是数值`4`,抛出 TypeError。
-#### 答案: D
+#### 答案:D
-常规函数,例如`giveLydiaPizza`函数,有一个`prototype`属性,它是一个带有`constructor`属性的对象(原型对象)。 然而,箭头函数,例如`giveLydiaChocolate`函数,没有这个`prototype`属性。 尝试使用`giveLydiaChocolate.prototype`访问`prototype`属性时会返回`undefined`。
+常规函数,例如`giveLydiaPizza`函数,有一个`prototype`属性,它是一个带有`constructor`属性的对象(原型对象)。然而,箭头函数,例如`giveLydiaChocolate`函数,没有这个`prototype`属性。尝试使用`giveLydiaChocolate.prototype`访问`prototype`属性时会返回`undefined`。
-#### 答案: A
+#### 答案:A
`Object.entries()`方法返回一个给定对象自身可枚举属性的键值对数组,上述情况返回一个二维数组,数组每个元素是一个包含键和值的数组:
-`[['name','Lydia'],['age',21]]`
+`[['name','Lydia'],['age', 21]]`
-使用`for-of`循环,我们可以迭代数组中的每个元素,上述情况是子数组。 我们可以使用`const [x,y]`在`for-of`循环中解构子数组。 `x`等于子数组中的第一个元素,`y`等于子数组中的第二个元素。
+使用`for-of`循环,我们可以迭代数组中的每个元素,上述情况是子数组。我们可以使用`const [x,y]`在`for-of`循环中解构子数组。`x`等于子数组中的第一个元素,`y`等于子数组中的第二个元素。
第一个子阵列是`[“name”,“Lydia”]`,其中`x`等于`name`,而`y`等于`Lydia`。
第二个子阵列是`[“age”,21]`,其中`x`等于`age`,而`y`等于`21`。
@@ -2948,7 +2948,7 @@ for (const [x, y] of Object.entries(person)) {
---
-###### 94. 输出什么?
+###### 94. 输出什么?
```javascript
function getItems(fruitList, ...args, favoriteFruit) {
@@ -2966,7 +2966,7 @@ getItems(["banana", "apple"], "pear", "orange")
-#### 答案: D
+#### 答案:D
`... args`是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,**并且只能作为最后一个参数**。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。
@@ -2984,7 +2984,7 @@ getItems(["banana", "apple"], "pear", "orange")
---
-###### 95. 输出什么?
+###### 95. 输出什么?
```javascript
function nums(a, b) {
@@ -3009,26 +3009,26 @@ console.log(nums(1, 2))
-#### 答案: B
+#### 答案:B
-在JavaScript中,我们不必显式地编写分号(`;`),但是JavaScript引擎仍然在语句之后自动添加分号。这称为**自动分号插入**。例如,一个语句可以是变量,或者像`throw`、`return`、`break`这样的关键字。
+在 JavaScript 中,我们不必显式地编写分号 (`;`),但是 JavaScript 引擎仍然在语句之后自动添加分号。这称为**自动分号插入**。例如,一个语句可以是变量,或者像`throw`、`return`、`break`这样的关键字。
-在这里,我们在新的一行上写了一个`return`语句和另一个值`a + b `。然而,由于它是一个新行,引擎并不知道它实际上是我们想要返回的值。相反,它会在`return`后面自动添加分号。你可以这样看:
+在这里,我们在新的一行上写了一个`return`语句和另一个值`a + b `。然而,由于它是一个新行,引擎并不知道它实际上是我们想要返回的值。相反,它会在`return`后面自动添加分号。你可以这样看:
```javascript
return;
a + b
```
-这意味着永远不会到达`a + b`,因为函数在`return`关键字之后停止运行。如果没有返回值,就像这里,函数返回`undefined`。注意,在`if/else`语句之后没有自动插入!
+这意味着永远不会到达`a + b`,因为函数在`return`关键字之后停止运行。如果没有返回值,就像这里,函数返回`undefined`。注意,在`if/else`语句之后没有自动插入!
-#### 答案: B
+#### 答案:B
-我们可以将类设置为等于其他类/函数构造函数。 在这种情况下,我们将`Person`设置为`AnotherPerson`。 这个构造函数的名字是`Sarah`,所以新的`Person`实例`member`上的name属性是`Sarah`。
+我们可以将类设置为等于其他类/函数构造函数。在这种情况下,我们将`Person`设置为`AnotherPerson`。这个构造函数的名字是`Sarah`,所以新的`Person`实例`member`上的 name 属性是`Sarah`。
-#### 答案: D
+#### 答案:D
-`Symbol`类型是不可枚举的。`Object.keys`方法返回对象上的所有可枚举的键属性。`Symbol`类型是不可见的,并返回一个空数组。 记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。
+`Symbol`类型是不可枚举的。`Object.keys`方法返回对象上的所有可枚举的键属性。`Symbol`类型是不可见的,并返回一个空数组。记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。
-这是`Symbol`的众多特性之一:除了表示完全唯一的值(防止对象意外名称冲突,例如当使用2个想要向同一对象添加属性的库时),您还可以`隐藏`这种方式对象的属性(尽管不完全。你仍然可以使用`Object.getOwnPropertySymbols()`方法访问 `Symbol`。
+这是`Symbol`的众多特性之一:除了表示完全唯一的值(防止对象意外名称冲突,例如当使用 2 个想要向同一对象添加属性的库时),您还可以`隐藏`这种方式对象的属性(尽管不完全。你仍然可以使用`Object.getOwnPropertySymbols()`方法访问 `Symbol`。
-#### 答案: A
+#### 答案:A
-`getList`函数接收一个数组作为其参数。 在`getList`函数的括号之间,我们立即解构这个数组。 您可以将其视为:
+`getList`函数接收一个数组作为其参数。在`getList`函数的括号之间,我们立即解构这个数组。您可以将其视为:
`[x, ...y] = [1, 2, 3, 4]`
-使用剩余的参数`... y`,我们将所有剩余参数放在一个数组中。 在这种情况下,其余的参数是`2`,`3`和`4`。 `y`的值是一个数组,包含所有其余参数。 在这种情况下,`x`的值等于`1`,所以当我们打印`[x,y]`时,会打印`[1,[2,3,4]]`。
+使用剩余的参数`... y`,我们将所有剩余参数放在一个数组中。在这种情况下,其余的参数是`2`,`3`和`4`。 `y`的值是一个数组,包含所有其余参数。在这种情况下,`x`的值等于`1`,所以当我们打印`[x,y]`时,会打印`[1,[2,3,4]]`。
- `getUser`函数接收一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须将它写在圆括号之间,否则两个花括号之间的所有内容都将被解释为一个块语句!在这种情况下,花括号之间的代码不是有效的 JavaScript 代码,因此会抛出SyntaxError。
+ `getUser`函数接收一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须将它写在圆括号之间,否则两个花括号之间的所有内容都将被解释为一个块语句!在这种情况下,花括号之间的代码不是有效的 JavaScript 代码,因此会抛出 SyntaxError。
以下函数将返回一个对象:
@@ -3138,7 +3138,7 @@ console.log(getUser(user))
---
-###### 99. 输出什么?
+###### 99. 输出什么?
```javascript
const name = "Lydia"
@@ -3154,22 +3154,22 @@ console.log(name())
-#### 答案: C
+#### 答案:C
变量`name`保存字符串的值,该字符串不是函数,因此无法调用。
-当值不是预期类型时,会抛出`TypeErrors`。 JavaScript期望`name`是一个函数,因为我们试图调用它。 但它是一个字符串,因此抛出`TypeError`:`name is not a function`
+当值不是预期类型时,会抛出`TypeErrors`。JavaScript 期望`name`是一个函数,因为我们试图调用它。但它是一个字符串,因此抛出`TypeError`:`name is not a function`
-当你编写了一些非有效的JavaScript时,会抛出语法错误,例如当你把`return`这个词写成`retrun`时。
-当JavaScript无法找到您尝试访问的值的引用时,抛出`ReferenceErrors`。
+当你编写了一些非有效的 JavaScript 时,会抛出语法错误,例如当你把`return`这个词写成`retrun`时。
+当 JavaScript 无法找到您尝试访问的值的引用时,抛出`ReferenceErrors`。
-#### 答案: B
+#### 答案:B
-`[]`是一个真值。 使用`&&`运算符,如果左侧值是真值,则返回右侧值。 在这种情况下,左侧值`[]`是一个真值,所以返回`Im`。
+`[]`是一个真值。使用`&&`运算符,如果左侧值是真值,则返回右侧值。在这种情况下,左侧值`[]`是一个真值,所以返回`Im`。
-`""`是一个假值。 如果左侧值是假的,则不返回任何内容。 `n't`不会被退回。
+`""`是一个假值。如果左侧值是假的,则不返回任何内容。`n't`不会被退回。
-#### 答案: C
+#### 答案:C
-使用`||`运算符,我们可以返回第一个真值。 如果所有值都是假值,则返回最后一个值。
+使用`||`运算符,我们可以返回第一个真值。如果所有值都是假值,则返回最后一个值。
-`(false || {} || null)`:空对象`{}`是一个真值。 这是第一个(也是唯一的)真值,它将被返回。`one`等于`{}`。
+`(false || {} || null)`:空对象`{}`是一个真值。这是第一个(也是唯一的)真值,它将被返回。`one`等于`{}`。
-`(null || false ||“”)`:所有值都是假值。 这意味着返回传递的值`""`。 `two`等于`""`。
+`(null || false ||“”)`:所有值都是假值。这意味着返回传递的值`""`。`two`等于`""`。
-`([] || 0 ||“”)`:空数组`[]`是一个真值。 这是第一个返回的真值。 `three`等于`[]`。
+`([] || 0 ||“”)`:空数组`[]`是一个真值。这是第一个返回的真值。`three`等于`[]`。
-#### 答案: D
+#### 答案:D
-有了promise,我们通常会说:当我想要调用某个方法,但是由于它可能需要一段时间,因此暂时将它放在一边。只有当某个值被resolved/rejected,并且执行栈为空时才使用这个值。
+有了 promise,我们通常会说:当我想要调用某个方法,但是由于它可能需要一段时间,因此暂时将它放在一边。只有当某个值被 resolved/rejected,并且执行栈为空时才使用这个值。
-我们可以在`async`函数中通过`.then`和`await`关键字获得该值。 尽管我们可以通过`.then`和`await`获得promise的价值,但是它们的工作方式有所不同。
+我们可以在`async`函数中通过`.then`和`await`关键字获得该值。尽管我们可以通过`.then`和`await`获得 promise 的价值,但是它们的工作方式有所不同。
-在 `firstFunction`中,当运行到`myPromise`方法时我们将其放在一边,即promise进入微任务队列,其他后面的代码(`console.log('second')`)照常运行,因此`second`被打印出,`firstFunction`方法到此执行完毕,执行栈中宏任务队列被清空,此时开始执行微任务队列中的任务,`I have resolved`被打印出。
+在 `firstFunction`中,当运行到`myPromise`方法时我们将其放在一边,即 promise 进入微任务队列,其他后面的代码(`console.log('second')`)照常运行,因此`second`被打印出,`firstFunction`方法到此执行完毕,执行栈中宏任务队列被清空,此时开始执行微任务队列中的任务,`I have resolved`被打印出。
在`secondFunction`方法中,我们通过`await`关键字,暂停了后面代码的执行,直到异步函数的值被解析才开始后面代码的执行。这意味着,它会等着直到 `myPromise` 以值`I have resolved`被解决之后,下一行`second`才开始执行。
@@ -3275,7 +3275,7 @@ secondFunction()
---
-###### 103. 输出什么?
+###### 103. 输出什么?
```javascript
const set = new Set()
@@ -3297,22 +3297,22 @@ for (let item of set) {
-#### 答案: C
+#### 答案:C
-“+”运算符不仅用于添加数值,还可以使用它来连接字符串。 每当JavaScript引擎发现一个或多个值不是数字时,就会将数字强制为字符串。
+“+”运算符不仅用于添加数值,还可以使用它来连接字符串。每当 JavaScript 引擎发现一个或多个值不是数字时,就会将数字强制为字符串。
-第一个是数字1。 1 + 2返回数字3。
+第一个是数字 1。1 + 2 返回数字 3。
-但是,第二个是字符串“Lydia”。 “Lydia”是一个字符串,2是一个数字:2被强制转换为字符串。 “Lydia”和“2”被连接起来,产生字符串“Lydia2”。
+但是,第二个是字符串“Lydia”。 “Lydia”是一个字符串,2 是一个数字:2 被强制转换为字符串。 “Lydia”和“2”被连接起来,产生字符串“Lydia2”。
-`{name:“ Lydia”}`是一个对象。 数字和对象都不是字符串,因此将二者都字符串化。 每当我们对常规对象进行字符串化时,它就会变成`[Object object]`。 与“2”串联的“ [Object object]”成为“[Object object]2”。
+`{name:“Lydia”}`是一个对象。数字和对象都不是字符串,因此将二者都字符串化。每当我们对常规对象进行字符串化时,它就会变成`[Object object]`。与“2”串联的“ [Object object]”成为“[Object object]2”。
-#### 答案: C
+#### 答案:C
-我们可以将我们想要的任何类型的值传递`Promise.resolve`,无论是否`promise`。 该方法本身返回带有已解析值的`Promise` (`
-#### 答案: B
+#### 答案:B
-对象通过引用传递。 当我们检查对象的严格相等性(===)时,我们正在比较它们的引用。
+对象通过引用传递。当我们检查对象的严格相等性(===)时,我们正在比较它们的引用。
我们将“person2”的默认值设置为“person”对象,并将“person”对象作为“person1”的值传递。
这意味着两个值都引用内存中的同一位置,因此它们是相等的。
-运行“ else”语句中的代码块,并记录`They are the same!` 。
+运行“else”语句中的代码块,并记录`They are the same!`。
-#### 答案: D
+#### 答案:D
-在JavaScript中,我们有两种访问对象属性的方法:括号表示法或点表示法。 在此示例中,我们使用点表示法(`colorConfig.colors`)代替括号表示法(`colorConfig [“ colors”]`)。
+在 JavaScript 中,我们有两种访问对象属性的方法:括号表示法或点表示法。在此示例中,我们使用点表示法(`colorConfig.colors`)代替括号表示法(`colorConfig [“colors”]`)。
-使用点表示法,JavaScript会尝试使用该确切名称在对象上查找属性。 在此示例中,JavaScript尝试在colorconfig对象上找到名为colors的属性。 没有名为“colors”的属性,因此返回“undefined”。
-然后,我们尝试使用`[1]`访问第一个元素的值。 我们无法对未定义的值执行此操作,因此会抛出`Cannot read property '1' of undefined`。
+使用点表示法,JavaScript 会尝试使用该确切名称在对象上查找属性。在此示例中,JavaScript 尝试在 colorConfig 对象上找到名为 colors 的属性。没有名为“colors”的属性,因此返回“undefined”。
+然后,我们尝试使用`[1]`访问第一个元素的值。我们无法对未定义的值执行此操作,因此会抛出`Cannot read property '1' of undefined`。
-JavaScript解释(或取消装箱)语句。 当我们使用方括号表示法时,它会看到第一个左方括号`[`并一直进行下去,直到找到右方括号`]`。 只有这样,它才会评估该语句。 如果我们使用了colorConfig [colors [1]],它将返回colorConfig对象上red属性的值。
+JavaScript 解释(或取消装箱)语句。当我们使用方括号表示法时,它会看到第一个左方括号`[`并一直进行下去,直到找到右方括号`]`。只有这样,它才会评估该语句。如果我们使用了 colorConfig [colors [1]],它将返回 colorConfig 对象上 red 属性的值。
-#### 答案: A
+#### 答案:A
-在内部,表情符号是unicode。 heat表情符号的unicode是`“ U + 2764 U + FE0F”`。 对于相同的表情符号,它们总是相同的,因此我们将两个相等的字符串相互比较,这将返回true。
+在内部,表情符号是 unicode。heat 表情符号的 unicode 是`“U + 2764 U + FE0F”`。对于相同的表情符号,它们总是相同的,因此我们将两个相等的字符串相互比较,这将返回 true。
-#### 答案: D
+#### 答案:D
-使用`splice`方法,我们通过删除,替换或添加元素来修改原始数组。 在这种情况下,我们从索引1中删除了2个元素(我们删除了`'🥑'`和`'😍'`),同时添加了✨emoji表情。
+使用`splice`方法,我们通过删除,替换或添加元素来修改原始数组。在这种情况下,我们从索引 1 中删除了 2 个元素(我们删除了`'🥑'`和`'😍'`),同时添加了✨emoji 表情。
`map`,`filter`和`slice`返回一个新数组,`find`返回一个元素,而`reduce`返回一个减小的值。
@@ -3469,7 +3469,7 @@ emojis.splice(1, 2, '✨')
---
-###### 109. 输出什么?
+###### 109. 输出什么?
```javascript
const food = ['🍕', '🍫', '🥑', '🍔']
@@ -3488,18 +3488,18 @@ console.log(food)
-#### 答案: A
+#### 答案:A
-我们将`info`对象上的`favoriteFood`属性的值设置为披萨表情符号“🍕”的字符串。字符串是原始数据类型。在JavaScript中,原始数据类型通过值起作用
+我们将`info`对象上的`favoriteFood`属性的值设置为披萨表情符号“🍕”的字符串。字符串是原始数据类型。在 JavaScript 中,原始数据类型通过值起作用
-在这种情况下,我们将`info`对象上的`favoriteFood`属性的值设置为等于`food`数组中的第一个元素的值,字符串为披萨表情符号(`'🍕'` )。字符串是原始数据类型,并且通过值进行交互,我们更改`info`对象上`favoriteFood`属性的值。 food数组没有改变,因为favoriteFood的值只是该数组中第一个元素的值的复制,并且与该元素上的元素没有相同的内存引用食物`[0]`。当我们记录食物时,它仍然是原始数组`['🍕','🍫','🥑','🍔']`。
+在这种情况下,我们将`info`对象上的`favoriteFood`属性的值设置为等于`food`数组中的第一个元素的值,字符串为披萨表情符号(`'🍕'`)。字符串是原始数据类型,并且通过值进行交互,我们更改`info`对象上`favoriteFood`属性的值。food 数组没有改变,因为 favoriteFood 的值只是该数组中第一个元素的值的复制,并且与该元素上的元素没有相同的内存引用食物`[0]`。当我们记录食物时,它仍然是原始数组`['🍕','🍫','🥑','🍔']`。
-#### 答案: A
+#### 答案:A
-使用`JSON.parse()`方法,我们可以将JSON字符串解析为JavaScript值。
+使用`JSON.parse()`方法,我们可以将 JSON 字符串解析为 JavaScript 值。
```javascript
-// 将数字字符串化为有效的JSON,然后将JSON字符串解析为JavaScript值:
+// 将数字字符串化为有效的 JSON,然后将 JSON 字符串解析为 JavaScript 值:
const jsonNumber = JSON.stringify(4) // '4'
JSON.parse(jsonNumber) // 4
-// 将数组值字符串化为有效的JSON,然后将JSON字符串解析为JavaScript值:
+// 将数组值字符串化为有效的 JSON,然后将 JSON 字符串解析为 JavaScript 值:
const jsonArray = JSON.stringify([1, 2, 3]) // '[1, 2, 3]'
JSON.parse(jsonArray) // [1, 2, 3]
-// 将对象字符串化为有效的JSON,然后将JSON字符串解析为JavaScript值:
+// 将对象字符串化为有效的 JSON,然后将 JSON 字符串解析为 JavaScript 值:
const jsonArray = JSON.stringify({ name: "Lydia" }) // '{"name":"Lydia"}'
JSON.parse(jsonArray) // { name: 'Lydia' }
```
@@ -3536,7 +3536,7 @@ JSON.parse(jsonArray) // { name: 'Lydia' }
---
-###### 111. 输出什么?
+###### 111. 输出什么?
```javascript
let name = 'Lydia'
@@ -3557,13 +3557,13 @@ getName()
-#### 答案: D
+#### 答案:D
-每个函数都有其自己的执行上下文。 `getName`函数首先在其自身的上下文(范围)内查找,以查看其是否包含我们尝试访问的变量`name`。 上述情况,`getName`函数包含其自己的`name`变量:我们用`let`关键字和`Sarah`的值声明变量`name`。
+每个函数都有其自己的执行上下文。`getName`函数首先在其自身的上下文(范围)内查找,以查看其是否包含我们尝试访问的变量`name`。上述情况,`getName`函数包含其自己的`name`变量:我们用`let`关键字和`Sarah`的值声明变量`name`。
-带有`let`关键字(和`const`)的变量被提升,但是与`var`不同,它不会被***初始化***。 在我们声明(初始化)它们之前,无法访问它们。 这称为“暂时性死区”。 当我们尝试在声明变量之前访问变量时,JavaScript会抛出`ReferenceError: Cannot access 'name' before initialization`。
+带有`let`关键字(和`const`)的变量被提升,但是与`var`不同,它不会被*** 初始化***。在我们声明(初始化)它们之前,无法访问它们。这称为“暂时性死区”。当我们尝试在声明变量之前访问变量时,JavaScript 会抛出`ReferenceError: Cannot access 'name' before initialization`。
-如果我们不在`getName`函数中声明`name`变量,则javascript引擎会查看原型链。会找到其外部作用域有一个名为`name`的变量,其值为`Lydia`。 在这种情况下,它将打印`Lydia`:
+如果我们不在`getName`函数中声明`name`变量,则 javascript 引擎会查看原型链。会找到其外部作用域有一个名为`name`的变量,其值为`Lydia`。在这种情况下,它将打印`Lydia`:
```javascript
let name = 'Lydia'
@@ -3606,18 +3606,18 @@ console.log(two.next().value)
-#### 答案: C
+#### 答案:C
-通过 `yield` 关键字, 我们在 `Generator` 函数里执行`yield`表达式. 通过 `yield*` 关键字, 我们可以在一个`Generator` 函数里面执行(`yield`表达式)另一个 `Generator` 函数, 或可遍历的对象 (如数组).
+通过 `yield` 关键字,我们在 `Generator` 函数里执行`yield`表达式。通过 `yield*` 关键字,我们可以在一个`Generator` 函数里面执行(`yield`表达式)另一个 `Generator` 函数,或可遍历的对象 (如数组).
-在函数 `generatorOne` 中, 我们通过 `yield` 关键字 yield 了一个完整的数组 `['a', 'b', 'c']`。函数`one`通过`next`方法返回的对象的`value` 属性的值 (`one.next().value`) 等价于数组 `['a', 'b', 'c']`.
+在函数 `generatorOne` 中,我们通过 `yield` 关键字 yield 了一个完整的数组 `['a', 'b', 'c']`。函数`one`通过`next`方法返回的对象的`value` 属性的值 (`one.next().value`) 等价于数组 `['a', 'b', 'c']`.
```javascript
console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined
```
-在函数 `generatorTwo` 中, 我们使用 `yield*` 关键字。就相当于函数`two`第一个`yield`的值, 等价于在迭代器中第一个 `yield` 的值。数组`['a', 'b', 'c']`就是这个迭代器. 第一个 `yield` 的值就是 `a`, 所以我们第一次调用 `two.next().value`时, 就返回`a`。
+在函数 `generatorTwo` 中,我们使用 `yield*` 关键字。就相当于函数`two`第一个`yield`的值,等价于在迭代器中第一个 `yield` 的值。数组`['a', 'b', 'c']`就是这个迭代器。第一个 `yield` 的值就是 `a`,所以我们第一次调用 `two.next().value`时,就返回`a`。
```javascript
console.log(two.next().value) // 'a'
@@ -3645,16 +3645,16 @@ console.log(`${(x => x)('I love')} to program`)
-#### 答案: A
+#### 答案:A
-带有模板字面量的表达式首先被执行。相当于字符串会包含表达式,这个立即执行函数 `(x => x)('I love')` 返回的值. 我们向箭头函数 `x => x` 传递 `'I love'` 作为参数。`x` 等价于返回的 `'I love'`。这就是结果 `I love to program`。
+带有模板字面量的表达式首先被执行。相当于字符串会包含表达式,这个立即执行函数 `(x => x)('I love')` 返回的值。我们向箭头函数 `x => x` 传递 `'I love'` 作为参数。`x` 等价于返回的 `'I love'`。这就是结果 `I love to program`。
-#### 答案: C
+#### 答案:C
-一般情况下当我们将对象赋值为 `null`, 那些对象会被进行 _垃圾回收(garbage collected)_ 因为已经没有对这些对象的引用了。然而,`setInterval`的参数是一个箭头函数(所以上下文绑定到对象 `config` 了),回调函数仍然保留着对 `config`的引用。只要存在引用,对象就不会被垃圾回收。因为没有被垃圾回收,`setInterval` 的回调每1000ms (1s)会被调用一次。
+一般情况下当我们将对象赋值为 `null`,那些对象会被进行 _垃圾回收(garbage collected)_ 因为已经没有对这些对象的引用了。然而,`setInterval`的参数是一个箭头函数(所以上下文绑定到对象 `config` 了),回调函数仍然保留着对 `config`的引用。只要存在引用,对象就不会被垃圾回收。因为没有被垃圾回收,`setInterval` 的回调每 1000ms (1s) 会被调用一次。
-#### 答案: B
+#### 答案:B
-当通过 `set` 方法添加一个键值对,一个传递给 `set`方法的参数将会是键名,第二个参数将会是值。在这个case里,键名为 _函数_ `() => 'greeting'`,值为`'Hello world'`。 `myMap` 现在就是 `{ () => 'greeting' => 'Hello world!' }`。
+当通过 `set` 方法添加一个键值对,一个传递给 `set`方法的参数将会是键名,第二个参数将会是值。在这个 case 里,键名为 _函数_ `() => 'greeting'`,值为`'Hello world'`。 `myMap` 现在就是 `{ () => 'greeting' => 'Hello world!' }`。
1 是错的,因为键名不是 `'greeting'` 而是 `() => 'greeting'`。
3 是错的,因为我们给`get` 方法传递了一个新的函数。对象受 _引用_ 影响。函数也是对象,因此两个函数严格上并不等价,尽管他们相同:他们有两个不同的内存引用地址。
@@ -3747,13 +3747,13 @@ console.log(person)
-#### 答案: C
+#### 答案:C
函数 `changeAge` 和函数 `changeAgeAndName` 有着不同的参数,定义一个 _新_ 生成的对象 `{ ...person }`。这个对象有着所有 `person` 对象 中 k/v 值的副本。
-首项, 我们调用 `changeAge` 函数并传递 `person` 对象作为它的参数。这个函数对 `age` 属性进行加一操作。`person` 现在是 `{ name: "Lydia", age: 22 }`。
+首项,我们调用 `changeAge` 函数并传递 `person` 对象作为它的参数。这个函数对 `age` 属性进行加一操作。`person` 现在是 `{ name: "Lydia", age: 22 }`。
-然后,我们调用函数 `changeAgeAndName` ,然而我们没有传递参数。取而代之,`x` 的值等价 _new_ 生成的对象: `{ ...person }`。因为它是一个新生成的对象,它并不会对对象 `person` 造成任何副作用。`person` 仍然等价于 `{ name: "Lydia", age: 22 }`。
+然后,我们调用函数 `changeAgeAndName`,然而我们没有传递参数。取而代之,`x` 的值等价 _new_ 生成的对象:`{ ...person }`。因为它是一个新生成的对象,它并不会对对象 `person` 造成任何副作用。`person` 仍然等价于 `{ name: "Lydia", age: 22 }`。
-#### 答案: C
+#### 答案:C
-通过展开操作符 `...`,我们可以 _暂开_ 单个可迭代的元素。函数 `sumValues` function 接收三个参数: `x`, `y` 和 `z`。`...[1, 2, 3]` 的执行结果为 `1, 2, 3`,将会传递给函数 `sumValues`。
+通过展开操作符 `...`,我们可以 _暂开_ 单个可迭代的元素。函数 `sumValues` function 接收三个参数:`x`, `y` 和 `z`。`...[1, 2, 3]` 的执行结果为 `1, 2, 3`,将会传递给函数 `sumValues`。
-#### 答案: B
+#### 答案:B
-通过 `+=` 操作符,我们对值 `num` 进行加 `1` 操作。 `num` 有初始值 `1`,因此 `1 + 1` 的执行结果为 `2`。数组 `list` 的第二项为 🥰,`console.log(list[2])` 输出 🥰.
+通过 `+=` 操作符,我们对值 `num` 进行加 `1` 操作。`num` 有初始值 `1`,因此 `1 + 1` 的执行结果为 `2`。数组 `list` 的第二项为 🥰,`console.log(list[2])` 输出 🥰.
-#### 答案: B
+#### 答案:B
通过 ES10 或 TS3.7+[可选链操作符 `?.`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/%E5%8F%AF%E9%80%89%E9%93%BE),我们不再需要显式检测更深层的嵌套值是否有效。如果我们尝试获取 `undefined` 或 `null` 的值 (_nullish_),表达将会短路并返回 `undefined`.
-`person.pet?.name`: `person` 有一个名为 `pet` 的属性: `person.pet` 不是 nullish。它有个名为 `name` 的属性,并返回字符串 `Mara`。
-`person.pet?.family?.name`: `person` 有一个名为 `pet` 的属性: `person.pet` 不是 nullish. `pet` _并没有_ 一个名为 `family` 的属性, `person.pet.family` 是 nullish。表达式返回 `undefined`。
-`person.getFullName?.()`: `person` 有一个名为 `getFullName` 的属性: `person.getFullName()` 不是 nullish 并可以被调用,返回字符串 `Lydia Hallie`。
+`person.pet?.name`:`person` 有一个名为 `pet` 的属性:`person.pet` 不是 nullish。它有个名为 `name` 的属性,并返回字符串 `Mara`。
+`person.pet?.family?.name`:`person` 有一个名为 `pet` 的属性:`person.pet` 不是 nullish. `pet` _并没有_ 一个名为 `family` 的属性,`person.pet.family` 是 nullish。表达式返回 `undefined`。
+`person.getFullName?.()`:`person` 有一个名为 `getFullName` 的属性:`person.getFullName()` 不是 nullish 并可以被调用,返回字符串 `Lydia Hallie`。
`member.getLastName?.()`: 变量`member` 不存在,因此会抛出错误`ReferenceError`。
-#### 答案: B
+#### 答案:B
-我们传递了一个状态 `groceries.indexOf("banana")` 给if条件语句。`groceries.indexOf("banana")` 返回 `0`, 一个 falsy 的值。因为if条件语句的状态为 falsy,`else` 块区内的代码执行,并且 `We don't have to buy bananas!` 被输出.
+我们传递了一个状态 `groceries.indexOf("banana")` 给 if 条件语句。`groceries.indexOf("banana")` 返回 `0`,一个 falsy 的值。因为 if 条件语句的状态为 falsy,`else` 块区内的代码执行,并且 `We don't have to buy bananas!` 被输出。
-#### 答案: D
+#### 答案:D
-方法 `language` 是一个 `setter`。Setters 并不保存一个实际值,它们的使命在于 _修改_ 属性。当调用方法 `setter`, 返回 `undefined`。
+方法 `language` 是一个 `setter`。Setters 并不保存一个实际值,它们的使命在于 _修改_ 属性。当调用方法 `setter`,返回 `undefined`。
-#### 答案: C
+#### 答案:C
-`typeof name` 返回 `"string"`。字符串 `"string"` 是一个 truthy 的值,因此 `!typeof name` 返回一个布尔值 `false`。 `false === "object"` 和 `false === "string"` 都返回 `false`。
+`typeof name` 返回 `"string"`。字符串 `"string"` 是一个 truthy 的值,因此 `!typeof name` 返回一个布尔值 `false`。`false === "object"` 和 `false === "string"` 都返回 `false`。
(如果我们想检测一个值的类型,我们应该用 `!==` 而不是 `!typeof`)
@@ -3941,7 +3941,7 @@ console.log(!typeof name === "string");
---
-###### 123. 输出什么?
+###### 123. 输出什么?
```javascript
const add = x => y => z => {
@@ -3960,7 +3960,7 @@ add(4)(5)(6);
-#### 答案: A
+#### 答案:A
函数 `add` 是一个返回 返回箭头函数的箭头函数 的箭头函数(still with me?)。第一个函数接收一个值为 `4` 的参数 `x`。我们调用第二个函数,它接收一个值为 `5` 的参数 `y`。然后我们调用第三个函数,它接收一个值为 `6` 的参数 `z`。当我们尝试在最后一个箭头函数中获取 `x`, `y` 和 `z` 的值,JS 引擎根据作用域链去找 `x` 和 `y` 的值。得到 `4` `5` `6`.
@@ -3994,9 +3994,9 @@ async function* range(start, end) {
-#### 答案: C
+#### 答案:C
-我们给 函数range 传递: `Promise{1}`, `Promise{2}`, `Promise{3}`,Generator 函数 `range` 返回一个全是 async object promise 数组。我们将 async object 赋值给变量 `gen`,之后我们使用`for await ... of` 进行循环遍历。我们将返回的 Promise 实例赋值给 `item`: 第一个返回 `Promise{1}`, 第二个返回 `Promise{2}`,之后是 `Promise{3}`。因为我们正 _awaiting_ `item` 的值,resolved 状态的 promsie,promise数组的resolved _值_ 以此为: `1`,`2`,`3`.
+我们给 函数 range 传递:`Promise{1}`, `Promise{2}`, `Promise{3}`,Generator 函数 `range` 返回一个全是 async object promise 数组。我们将 async object 赋值给变量 `gen`,之后我们使用`for await ... of` 进行循环遍历。我们将返回的 Promise 实例赋值给 `item`:第一个返回 `Promise{1}`,第二个返回 `Promise{2}`,之后是 `Promise{3}`。因为我们正 _awaiting_ `item` 的值,resolved 状态的 promise,promise 数组的 resolved _值_ 以此为:`1`,`2`,`3`.
-#### 答案: D
+#### 答案:D
-`myFunc` 期望接收一个包含 `x`, `y` 和 `z` 属性的对象作为它的参数。因为我们仅仅传递三个单独的数字值 (1, 2, 3) 而不是一个含有 `x`, `y` 和 `z` 属性的对象 ({x: 1, y: 2, z: 3}), `x`, `y` 和 `z` 有着各自的默认值 `undefined`.
+`myFunc` 期望接收一个包含 `x`, `y` 和 `z` 属性的对象作为它的参数。因为我们仅仅传递三个单独的数字值 (1, 2, 3) 而不是一个含有 `x`, `y` 和 `z` 属性的对象 ({x: 1, y: 2, z: 3}),`x`, `y` 和 `z` 有着各自的默认值 `undefined`.
-#### 答案: B
+#### 答案:B
-通过方法 `Intl.NumberFormat`,我们可以格式化任意区域的数字值。我们对数字值 `130` 进行 `mile-per-hour` 作为 `unit` 的 `en-US` 区域 格式化,结果为 `130 mph`。对数字值 `300` 进行 `USD` 作为 `currentcy` 的 `en-US` 区域格式化,结果为 `$300.00`.
+通过方法 `Intl.NumberFormat`,我们可以格式化任意区域的数字值。我们对数字值 `130` 进行 `mile-per-hour` 作为 `unit` 的 `en-US` 区域 格式化,结果为 `130 mph`。对数字值 `300` 进行 `USD` 作为 `currency` 的 `en-US` 区域格式化,结果为 `$300.00`.
-#### 答案: B
+#### 答案:B
通过解构对象们,我们可以从右手边的对象中拆出值,并且将拆出的值分配给左手边对象同名的属性。在这种情况下,我们将值 "💀" 分配给 `spookyItems[3]`。相当于我们正在篡改数组 `spookyItems`,我们给它添加了值 "💀"。当输出 `spookyItems` 时,结果为 `["👻", "🎃", "🕸", "💀"]`。
@@ -4114,11 +4114,11 @@ console.log(isNaN(age));
-#### 答案: C
+#### 答案:C
通过方法 `Number.isNaN`,你可以检测你传递的值是否为 _数字值_ 并且是否等价于 `NaN`。`name` 不是一个数字值,因此 `Number.isNaN(name)` 返回 `false`。`age` 是一个数字值,但它不等价于 `NaN`,因此 `Number.isNaN(age)` 返回 `false`.
-通过方法 `isNaN`, 你可以检测你传递的值是否一个 number。`name` 不是一个 `number`,因此 `isNaN(name)` 返回 `true`. `age` 是一个 `number` 因此 `isNaN(age)` 返回 `false`.
+通过方法 `isNaN`,你可以检测你传递的值是否一个 number。`name` 不是一个 `number`,因此 `isNaN(name)` 返回 `true`. `age` 是一个 `number` 因此 `isNaN(age)` 返回 `false`.
-#### 答案: D
+#### 答案:D
-通过 `const` 关键字声明的变量在被初始化之前不可被引用:这被称之为 _暂时性死区_。在函数 `getInfo` 中, 变量 `randomValue` 声明在`getInfo` 的作用域的此法环境中。在想要对 `typeof randomValue` 进行log之前,变量 `randomValue` 仍未被初始化: 错误`ReferenceError` 被抛出! JS引擎并不会根据作用域链网上寻找该变量,因为我们已经在 `getInfo` 函数中声明了 `randomValue` 变量。
+通过 `const` 关键字声明的变量在被初始化之前不可被引用:这被称之为 _暂时性死区_。在函数 `getInfo` 中,变量 `randomValue` 声明在`getInfo` 的作用域的此法环境中。在想要对 `typeof randomValue` 进行 log 之前,变量 `randomValue` 仍未被初始化:错误`ReferenceError` 被抛出!JS 引擎并不会根据作用域链网上寻找该变量,因为我们已经在 `getInfo` 函数中声明了 `randomValue` 变量。
-#### 答案: C
+#### 答案:C
-在 `try` 块区,我们打印 `myPromise` 变量的 awaited 值: `"Woah some cool data"`。因为`try` 块区没有错误抛出,`catch` 块区的代码并不执行。`finally` 块区的代码 _总是_ 执行,`"Oh finally!"` 被输出。
+在 `try` 块区,我们打印 `myPromise` 变量的 awaited 值:`"Woah some cool data"`。因为`try` 块区没有错误抛出,`catch` 块区的代码并不执行。`finally` 块区的代码 _总是_ 执行,`"Oh finally!"` 被输出。
-#### 答案: B
+#### 答案:B
-通过方法 `flat`, 我们可以创建一个新的, 已被扁平化的数组。被扁平化的深度取决于我们传递的值。在这个case里,我们传递了值 `1` (并不必要,这是默认值),相当于只有第一层的数组才会被连接。即这个 case 里的 `['🥑']` and `['✨', '✨', ['🍕', '🍕']]`。连接这两个数组得到结果 `['🥑', '✨', '✨', ['🍕', '🍕']]`.
+通过方法 `flat`,我们可以创建一个新的,已被扁平化的数组。被扁平化的深度取决于我们传递的值。在这个 case 里,我们传递了值 `1` (并不必要,这是默认值),相当于只有第一层的数组才会被连接。即这个 case 里的 `['🥑']` and `['✨', '✨', ['🍕', '🍕']]`。连接这两个数组得到结果 `['🥑', '✨', '✨', ['🍕', '🍕']]`.
-#### 答案: D
+#### 答案:D
-`counterOne` 是类 `Counter` 的一个实例。类 Counter 包含一个`count` 属性在它的构造函数里, 和一个 `increment` 方法。首先,我们通过 `counterOne.increment()` 调用方法 `increment` 两次。现在, `counterOne.count` 为 `2`.
+`counterOne` 是类 `Counter` 的一个实例。类 Counter 包含一个`count` 属性在它的构造函数里,和一个 `increment` 方法。首先,我们通过 `counterOne.increment()` 调用方法 `increment` 两次。现在,`counterOne.count` 为 `2`.
-#### 答案: D
+#### 答案:D
-首先,我们调用 `funcOne`。在函数 `funcOne` 的第一行,我们调用`myPromise` promise _异步操作_。当JS引擎在忙于执行 promise,它继续执行函数 `funcOne`。下一行 _异步操作_ `setTimeout`,其回调函数被 Web API 调用。 (详情请参考我关于event loop的文章.)
+首先,我们调用 `funcOne`。在函数 `funcOne` 的第一行,我们调用`myPromise` promise _异步操作_。当 JS 引擎在忙于执行 promise,它继续执行函数 `funcOne`。下一行 _异步操作_ `setTimeout`,其回调函数被 Web API 调用。 (详情请参考我关于 event loop 的文章.)
-promise 和 timeout 都是异步操作,函数继续执行当JS引擎忙于执行promise 和 处理 `setTimeout` 的回调。相当于 `Last line!` 首先被输出, 因为它不是异步操作。执行完 `funcOne` 的最后一行,promise 状态转变为 resolved,`Promise!` 被打印。然而,因为我们调用了 `funcTwo()`, 调用栈不为空,`setTimeout` 的回调仍不能入栈。
+promise 和 timeout 都是异步操作,函数继续执行当 JS 引擎忙于执行 promise 和 处理 `setTimeout` 的回调。相当于 `Last line!` 首先被输出,因为它不是异步操作。执行完 `funcOne` 的最后一行,promise 状态转变为 resolved,`Promise!` 被打印。然而,因为我们调用了 `funcTwo()`,调用栈不为空,`setTimeout` 的回调仍不能入栈。
-我们现在处于 `funcTwo`,先 _awaiting_ myPromise。通过 `await` 关键字, 我们暂停了函数的执行直到 promise 状态变为 resolved (或 rejected)。然后,我们输出 `res` 的 awaited 值(因为 promise 本身返回一个 promise)。 接着输出 `Promise!`。
+我们现在处于 `funcTwo`,先 _awaiting_ myPromise。通过 `await` 关键字,我们暂停了函数的执行直到 promise 状态变为 resolved (或 rejected)。然后,我们输出 `res` 的 awaited 值(因为 promise 本身返回一个 promise)。接着输出 `Promise!`。
下一行就是 _异步操作_ `setTimeout`,其回调函数被 Web API 调用。
@@ -4328,7 +4328,7 @@ import * as sum from "./sum";
-#### 答案: C
+#### 答案:C
使用符号 `*`,我们引入文件中的所有值,包括默认和具名。如果我们有以下文件:
@@ -4388,13 +4388,13 @@ person.name;
-#### 答案: C
+#### 答案:C
使用 Proxy 对象,我们可以给一个对象添加自定义行为。在这个 case,我们传递一个包含以下属性的对象 `handler` : `set` and `get`。每当我们 _设置_ 属性值时 `set` 被调用,每当我们 _获取_ 时 `get` 被调用。
-第一个参数是一个空对象 `{}`,作为 `person` 的值。对于这个对象,自定义行为被定义在对象 `handler`。如果我们向对象 `person` 添加属性,`set` 将被调用。如果我们获取 `person` 的属性, `get` 将被调用。
+第一个参数是一个空对象 `{}`,作为 `person` 的值。对于这个对象,自定义行为被定义在对象 `handler`。如果我们向对象 `person` 添加属性,`set` 将被调用。如果我们获取 `person` 的属性,`get` 将被调用。
-首先,我们向 proxy 对象(`person.name = "Lydia"`)添加一个属性 `name`。`set` 被调用并输出 `"Added a new property!"`。
+首先,我们向 proxy 对象 (`person.name = "Lydia"`) 添加一个属性 `name`。`set` 被调用并输出 `"Added a new property!"`。
然后,我们获取 proxy 对象的一个属性,对象 handler 的属性 `get` 被调用。输出 `"Accessed a property!"`。
@@ -4419,7 +4419,7 @@ Object.seal(person);
-#### 答案: A
+#### 答案:A
使用 `Object.seal` 我们可以防止新属性 _被添加_,或者存在属性 _被移除_.
@@ -4451,7 +4451,7 @@ Object.freeze(person);
-#### 答案: C
+#### 答案:C
使用方法 `Object.freeze` 对一个对象进行 _冻结_。不能对属性进行添加,修改,删除。
@@ -4483,11 +4483,11 @@ myFunc(3);
-#### 答案: A
+#### 答案:A
-首先我们不传递任何参数调用 `myFunc()`。因为我们没有传递参数,`num` 和 `value` 获取它们各自的默认值:num 为 `2`, 而 `value` 为函数 `add` 的返回值。对于函数 `add`,我们传递值为2的 `num` 作为参数。函数 `add` 返回 `4` 作为 `value` 的值。
+首先我们不传递任何参数调用 `myFunc()`。因为我们没有传递参数,`num` 和 `value` 获取它们各自的默认值:num 为 `2`,而 `value` 为函数 `add` 的返回值。对于函数 `add`,我们传递值为 2 的 `num` 作为参数。函数 `add` 返回 `4` 作为 `value` 的值。
-然后,我们调用 `myFunc(3)` 并传递值 `3` 参数 `num` 的值。我们没有给 `value` 传递值。因为我们没有给参数 `value` 传递值,它获取默认值:函数 `add` 的返回值。对于函数 `add`,我们传递值为3的 `num`给它。函数 `add` 返回 `6` 作为 `value` 的值。
+然后,我们调用 `myFunc(3)` 并传递值 `3` 参数 `num` 的值。我们没有给 `value` 传递值。因为我们没有给参数 `value` 传递值,它获取默认值:函数 `add` 的返回值。对于函数 `add`,我们传递值为 3 的 `num`给它。函数 `add` 返回 `6` 作为 `value` 的值。
-#### 答案: D
+#### 答案:D
-在 ES2020 中,通过 `#` 我们可以给 class 添加私有变量。在 class 的外部我们无法获取该值。当我们尝试输出 `counter.#number`,语法错误被抛出:我们无法在 class `Counter` 外部获取它!
+在 ES2020 中,通过 `#` 我们可以给 class 添加私有变量。在 class 的外部我们无法获取该值。当我们尝试输出 `counter.#number`,语法错误被抛出:我们无法在 class `Counter` 外部获取它!
-#### 答案: B
+#### 答案:B
为了遍历 `teams` 数组中对象的属性 `members` 中的每一项,我们需要将 `teams[i].members` 传递给 Generator 函数 `getMembers`。Generator 函数返回一个 generator 对象。为了遍历这个 generator 对象中的每一项,我们需要使用 `yield*`.
-如果我们没有写 `yield`,`return yield` 或者 `return`,整个 Generator 函数不会第一时间 return 当我们调用 `next` 方法.
+如果我们没有写 `yield`,`return yield` 或者 `return`,整个 Generator 函数不会第一时间 return 当我们调用 `next` 方法。
-#### 答案: C
+#### 答案:C
函数 `addHobby` 接受两个参数,`hobby` 和有着对象 `person` 中数组 `hobbies` 默认值的 `hobbies`。
@@ -4612,7 +4612,7 @@ console.log(person.hobbies);
然后,我们调用函数 `addHobby`,并给 `hobby` 传递 `"dancing"`。我们不向 `hobbies` 传递值,因此它获取其默认值 —— 对象 `person` 的 属性 `hobbies`。我们向数组 `person.hobbies` push `dancing`。
-最后,我们调用函数 `addHobby`,并向 `hobby` 传递 值 `"bdaking"`,并且向 `hobbies` 传递 `person.hobbies`。我们向数组 `person.hobbies` push `dancing`。
+最后,我们调用函数 `addHobby`,并向 `hobby` 传递 值 `"baking"`,并且向 `hobbies` 传递 `person.hobbies`。我们向数组 `person.hobbies` push `dancing`。
pushing `dancing` 和 `baking` 之后,`person.hobbies` 的值为 `["coding", "dancing", "baking"]`
@@ -4648,9 +4648,9 @@ const pet = new Flamingo();
-#### 答案: B
+#### 答案:B
-我们创建了类 `Flamingo` 的实例 `pet`。当我们实例化这个实例,`Flamingo` 中的 `constructor` 被调用。首相,输出 `"I'm pink. 🌸"`, 之后我们调用`super()`。`super()` 调用父类的构造函数,`Bird`。`Bird` 的构造函数被调用,并输出 `"I'm a bird. 🦢"`。
+我们创建了类 `Flamingo` 的实例 `pet`。当我们实例化这个实例,`Flamingo` 中的 `constructor` 被调用。首相,输出 `"I'm pink. 🌸"`,之后我们调用`super()`。`super()` 调用父类的构造函数,`Bird`。`Bird` 的构造函数被调用,并输出 `"I'm a bird. 🦢"`。
-#### 答案: D
+#### 答案:D
-`const` 关键字意味着我们不能 _重定义_ 变量中的值,它 _仅可读_。而然,值本身不可修改。数组 `emojis` 中的值可被修改,如 push 新的值, 拼接,又或者将数组的长度设置为0。
+`const` 关键字意味着我们不能 _重定义_ 变量中的值,它 _仅可读_。然而,值本身不可修改。数组 `emojis` 中的值可被修改,如 push 新的值,拼接,又或者将数组的长度设置为 0。
-#### 答案: C
+#### 答案:C
-对象默认并不是可迭代的。如果迭代规则被定义,则一个对象是可迭代的(An iterable is an iterable if the iterator protocol is present)。我们可以通过添加迭代器symbol `[Symbol.iterator]` 来定义迭代规则,其返回一个 generator 对象,比如说构建一个 generator 函数 `*[Symbol.iterator]() {}`。如果我们想要返回数组 `["Lydia Hallie", 21]`: `yield* Object.values(this)`,这个 generator 函数一定要 yield 对象 `person` 的`Object.values`。
+对象默认并不是可迭代的。如果迭代规则被定义,则一个对象是可迭代的(An iterable is an iterable if the iterator protocol is present)。我们可以通过添加迭代器 symbol `[Symbol.iterator]` 来定义迭代规则,其返回一个 generator 对象,比如说构建一个 generator 函数 `*[Symbol.iterator]() {}`。如果我们想要返回数组 `["Lydia Hallie", 21]`: `yield* Object.values(this)`,这个 generator 函数一定要 yield 对象 `person` 的`Object.values`。
-#### 答案: C
+#### 答案:C
-在 `forEach` 循环内部的 `if` 会判断 `num` 的值是truthy或者是falsy。因为 `nums` 数组的第一个数字是 `0`,一个falsy值, `if` 语句代码块不会被执行。`count` 仅仅在 `nums` 数组的其他3个数字 `1`,`2`,`3` 时加1。因为 `count` 执行了3次加 `1` 运算,所以 `count` 的值为 `3`。
+在 `forEach` 循环内部的 `if` 会判断 `num` 的值是 truthy 或者是 falsy。因为 `nums` 数组的第一个数字是 `0`,一个 falsy 值,`if` 语句代码块不会被执行。`count` 仅仅在 `nums` 数组的其他 3 个数字 `1`,`2`,`3` 时加 1。因为 `count` 执行了 3 次加 `1` 运算,所以 `count` 的值为 `3`。
-#### 答案: D
+#### 答案:D
-`?` 允许我们去选择性地访问对象内部更深层的嵌套属性。 我们尝试打印 `fruits` 数组索引值为 `1` 的子数组内部的索引值为 `1` 的元素。 如果在 `fruits` 数组索引值 为 `1` 的位置不存在元素,会直接返回 `undefined`。 如果 `fruits` 数组在索引值为 `1` 的位置存在元素,但是子数组在索引值为 `1` 的位置不存在元素,也会返回 `undefined`。
+`?` 允许我们去选择性地访问对象内部更深层的嵌套属性。我们尝试打印 `fruits` 数组索引值为 `1` 的子数组内部的索引值为 `1` 的元素。如果在 `fruits` 数组索引值 为 `1` 的位置不存在元素,会直接返回 `undefined`。如果 `fruits` 数组在索引值为 `1` 的位置存在元素,但是子数组在索引值为 `1` 的位置不存在元素,也会返回 `undefined`。
-首先,我们尝试打印 `[['🍊', '🍌'], ['🍍']]` 的子数组 `['🍍']` 的第2个元素。这个子数组只包含一个元素,也就意味着在索引值为 `1` 的位置不存在元素,所以返回的是 `undefined` 。
+首先,我们尝试打印 `[['🍊', '🍌'], ['🍍']]` 的子数组 `['🍍']` 的第 2 个元素。这个子数组只包含一个元素,也就意味着在索引值为 `1` 的位置不存在元素,所以返回的是 `undefined`。
-其次,我们在没有传入任何参数调用了 `getFruits` 函数,也就意味着形参 `fruits` 的默认值为`undefined`。因为我们选择性地链接了 `fruits` 在索引值为 `1` 的元素,因为在索引值为 `1` 的位置不存在元素,因此返回的是 `undefined` 。
+其次,我们在没有传入任何参数调用了 `getFruits` 函数,也就意味着形参 `fruits` 的默认值为`undefined`。因为我们选择性地链接了 `fruits` 在索引值为 `1` 的元素,因为在索引值为 `1` 的位置不存在元素,因此返回的是 `undefined`。
-最后,我们尝试打印 `['🍍'], ['🍊', '🍌']` 的子数组 `['🍊', '🍌']` 的第2个元素。子数组索引值为 `1`的位置为 `🍌` ,因此它被打印出了。
+最后,我们尝试打印 `['🍍'], ['🍊', '🍌']` 的子数组 `['🍊', '🍌']` 的第 2 个元素。子数组索引值为 `1`的位置为 `🍌`,因此它被打印出了。
-#### 答案: A
+#### 答案:A
-我们设置 `calc` 变量为 `Calc` 类的一个新实例。 然后,我们初始化一个 `Calc` 的新实例,而且调用了这个实例的 `increase` 方法。因为count属性是在 `Calc` class的constructor内部的,所以count属性不会在 `Calc` 的原型链上共享出去。这就意味着calc实例的count值不会被更新,count仍然是 `0`。
+我们设置 `calc` 变量为 `Calc` 类的一个新实例。然后,我们初始化一个 `Calc` 的新实例,而且调用了这个实例的 `increase` 方法。因为 count 属性是在 `Calc` class 的 constructor 内部的,所以 count 属性不会在 `Calc` 的原型链上共享出去。这就意味着 calc 实例的 count 值不会被更新,count 仍然是 `0`。
-#### 答案: B
+#### 答案:B
- `updateUser` 函数更新user的 `email` 和 `password` 属性的值, 如果它们的值传入函数, 函数返回的就是 `user` 对象。 `updateUser` 函数的返回值是 `user` 对象,意味着updatedUser的值与 `user` 指向的是同一个 `user` 对象。`updatedUser === user` 为 `true`.
+ `updateUser` 函数更新 user 的 `email` 和 `password` 属性的值,如果它们的值传入函数,函数返回的就是 `user` 对象。`updateUser` 函数的返回值是 `user` 对象,意味着 updatedUser 的值与 `user` 指向的是同一个 `user` 对象。`updatedUser === user` 为 `true`.
-#### 答案: C
+#### 答案:C
-首先,我们在fruit数组上调用 `slice` 方法。 slice方法不会修改原始数组,但是会返回从数组切片下来的值:香蕉emoji。
-其次,我们在fruit数组上调用 `splice` 方法。 splice方法会修改原始数组,也就意味着fruit数组此时为 `['🍊', '🍎']`。
-最后,我们在fruit数组上调用 `unshift` 方法,通过添加一个值的方式改变了原始数组,添加的是'🍇',它成为了数组的第一个元素。现在fruit数组的组成为 `['🍇', '🍊', '🍎']`。
+首先,我们在 fruit 数组上调用 `slice` 方法。slice 方法不会修改原始数组,但是会返回从数组切片下来的值:香蕉 emoji。
+其次,我们在 fruit 数组上调用 `splice` 方法。splice 方法会修改原始数组,也就意味着 fruit 数组此时为 `['🍊', '🍎']`。
+最后,我们在 fruit 数组上调用 `unshift` 方法,通过添加一个值的方式改变了原始数组,添加的是'🍇',它成为了数组的第一个元素。现在 fruit 数组的组成为 `['🍇', '🍊', '🍎']`。
-#### 答案: B
+#### 答案:B
对象的键会被转换为字符串。
-因为 `dog` 的值是一个对象, `animals[dog]` 实际上意味着我们创建了一个叫做 `"object Object"` 的属性来代表新的对象。 `animals["object Object"]` 现在等于 `{ emoji: "🐶", name: "Mara"}`。
+因为 `dog` 的值是一个对象,`animals[dog]` 实际上意味着我们创建了一个叫做 `"object Object"` 的属性来代表新的对象。`animals["object Object"]` 现在等于 `{ emoji: "🐶", name: "Mara"}`。
-`cat` 也是一个对象,`animals[cat]` 实际上意味着我们在用新的cat的属性覆盖 `animals[``"``object Object``"``]` 的值。
+`cat` 也是一个对象,`animals[cat]` 实际上意味着我们在用新的 cat 的属性覆盖 `animals[``"``object Object``"``]` 的值。
-打印 `animals[dog]`,实际上是`animals["object Object"]`,这是因为转化`dog`对象为一个字符串结果 `"object Object"` ,所以返回 `{ emoji: "🐈", name: "Sara" }`。
+打印 `animals[dog]`,实际上是`animals["object Object"]`,这是因为转化`dog`对象为一个字符串结果 `"object Object"`,所以返回 `{ emoji: "🐈", name: "Sara" }`。
-#### 答案: A
+#### 答案:A
-`updateEmail` 函数是一个箭头函数,它没有和 `user` 对象绑定。这就意味着 `this` 关键字不会引用到 `user` 对象,但是会引用到全局对象。 `user` 对象内部的 `email` 的值不会更新。当打印 `user.email` 的时候, 原始值 `my@email.com` 被返回。
+`updateEmail` 函数是一个箭头函数,它没有和 `user` 对象绑定。这就意味着 `this` 关键字不会引用到 `user` 对象,但是会引用到全局对象。`user` 对象内部的 `email` 的值不会更新。当打印 `user.email` 的时候,原始值 `my@email.com` 被返回。
-#### 答案: D
+#### 答案:D
- `Promise.all` 方法可以并行式运行promise。如果其中一个promise失败了,`Promise.all` 方法会带上被reject的promise的值_rejects_。在这个例子中, `promise3` 带着 `"Third"` 值reject。我们在调用 `runPromises` 时在 `runPromises` 函数内部的 `catch` 方法去捕获任意error从而捕获到被reject的值。因为 `promise3` 带着 `"Third"` 被reject,所以只有 `"Third"` 打印。
+ `Promise.all` 方法可以并行式运行 promise。如果其中一个 promise 失败了,`Promise.all` 方法会带上被 reject 的 promise 的值_rejects_。在这个例子中,`promise3` 带着 `"Third"` 值 reject。我们在调用 `runPromises` 时在 `runPromises` 函数内部的 `catch` 方法去捕获任意 error 从而捕获到被 reject 的值。因为 `promise3` 带着 `"Third"` 被 reject,所以只有 `"Third"` 打印。
-#### 答案: C
+#### 答案:C
- `fromEntries` 方法可以将二维数组转换为对象。在每个子数组的第一个元素是key,在每个子数组的第二个元素是value。在这个例子中,我们映射了 `keys` 数组,它返回了一个数组,数组的第一个元素为keys数组当前索引的值,第二个元素为values数组当前索引的值。
+ `fromEntries` 方法可以将二维数组转换为对象。在每个子数组的第一个元素是 key,在每个子数组的第二个元素是 value。在这个例子中,我们映射了 `keys` 数组,它返回了一个数组,数组的第一个元素为 keys 数组当前索引的值,第二个元素为 values 数组当前索引的值。
-这样就创建了一个包含正确keys和values的子数组的数组,因此结果为`{ name: "Lydia", age: 22 }`。
+这样就创建了一个包含正确 keys 和 values 的子数组的数组,因此结果为`{ name: "Lydia", age: 22 }`。
-#### 答案: C
+#### 答案:C
- `address` 的默认值是一个空对象 `{}`。当我们设置 `member` 变量为 `createMember` 函数返回的对象,我们没有为address参数传值,意味着address的值为默认的空对象 `{}`。一个空对象是一个truthy值,意味着 `address ? address : null` 条件会返回 `true`。address的值为空对象 `{}`。
+ `address` 的默认值是一个空对象 `{}`。当我们设置 `member` 变量为 `createMember` 函数返回的对象,我们没有为 address 参数传值,意味着 address 的值为默认的空对象 `{}`。一个空对象是一个 truthy 值,意味着 `address ? address : null` 条件会返回 `true`。address 的值为空对象 `{}`。
-#### 答案: B
+#### 答案:B
- `if` 语句的条件判断 `!typeof randomValue` 的值是否等于 `"string"`。 `!` 操作符将这个值转化为一个布尔值。如果值是truthy的话,返回值会是 `false`,如果值是falsy,返回值会是 `true`。在这里, `typeof randomValue` 的返回值是一个truthy值 `"number"`,意味着 `!typeof randomValue` 的值是一个布尔值 `false`。
+ `if` 语句的条件判断 `!typeof randomValue` 的值是否等于 `"string"`。`!` 操作符将这个值转化为一个布尔值。如果值是 truthy 的话,返回值会是 `false`,如果值是 falsy,返回值会是 `true`。在这里,`typeof randomValue` 的返回值是一个 truthy 值 `"number"`,意味着 `!typeof randomValue` 的值是一个布尔值 `false`。
- `!typeof randomValue === "string"` 总是返回false,因为我们实际上是在执行 `false === "string"`。因为条件返回的是 `false`,所以 `else` 语句中的代码块会被运行,因此打印 `Yay it's a string!` 。
+ `!typeof randomValue === "string"` 总是返回 false,因为我们实际上是在执行 `false === "string"`。因为条件返回的是 `false`,所以 `else` 语句中的代码块会被运行,因此打印 `Yay it's a string!`。
-#### 答案: A
+#### 答案:A
基本执行上下文是全局执行上下文:它是代码中随处可访问的内容。
基底的執行環境是全域的:代表它在程式碼中,可被隨處使用。
@@ -802,7 +802,7 @@ for (let i = 1; i < 5; i++) {
-#### 答案: C
+#### 答案:C
當 `if` 條件成立時會回傳 `true`,執行 `continue` 語句,代表忽略本次迭代(`console.log(i)`)。
@@ -820,7 +820,7 @@ String.prototype.giveLydiaPizza = () => {
const name = 'Lydia';
-name.giveLydiaPizza();
+console.log(name.giveLydiaPizza())
```
- A: `"Just give Lydia pizza already!"`
@@ -831,7 +831,7 @@ name.giveLydiaPizza();
-#### 答案: A
+#### 答案:A
`String` 是內建的建構函式,我們可以向它新增属性。我只是在它的原型中加上一個方法。基本型別字串被自動轉換成字串物件,由字串原型函式生成。因此,所有 string(string 物件)都可以使用 `giveLydiaPizza` 方法!
@@ -861,7 +861,7 @@ console.log(a[b]);
-#### 答案: B
+#### 答案:B
物件的 key 自動轉為字串型別。我們正嘗試將物件 `b` 的 key 設為物件 `a` 的 key,其值爲 `123`。
@@ -894,7 +894,7 @@ baz();
-#### 答案: B
+#### 答案:B
我們有一個 `setTimeout` 函式,首先呼叫它。然而,它的執行順序是最後執行的。
@@ -942,21 +942,21 @@ WebAPI 不能隨時向堆疊内新增内容。相反,它會將回呼函式彈
- A: 第一層的 `div`
- B: 第二層的 `div`
- C: `button` 本身
-- D: 一個包含此巢狀元件的陣列.
+- D: 一個包含此巢狀元件的陣列。
-#### 答案: C
+#### 答案:C
-產生事件(event)的元件即為此事件的 target,您可以透過 `event.stopPropagation` 來停止事件的冒泡(bubbling)
+產生事件 (event) 的元件即為此事件的 target,您可以透過 `event.stopPropagation` 來停止事件的冒泡 (bubbling)
-#### 答案: A
+#### 答案:A
-輸出內容是 `p` 及 `div`。在事件傳播(event propagation) 期間,分為三個階段:捕獲(capturing),目標(target) 和冒泡(bubbling)。
-預設情況下,事件處理(event handlers) 在冒泡階段執行(除非您將useCapture設置為true)。 它從巢狀元素的最深層向外層。
+輸出內容是 `p` 及 `div`。在事件傳播 (event propagation) 期間,分為三個階段:捕獲 (capturing),目標 (target) 和冒泡 (bubbling)。
+預設情況下,事件處理 (event handlers) 在冒泡階段執行(除非您將 useCapture 設置為 true)。它從巢狀元素的最深層向外層。
-#### 答案: D
+#### 答案:D
通過 `.call` 及 `.bind`,我們可以將想要 `this` 關鍵字引用的物件傳遞給它。
-然而,`.call` 會 _立即執行_! `.bind.` 則是會回傳一份函式(function)的 _複製_ 且不會立即執行。
+然而,`.call` 會 _立即執行_! `.bind.` 則是會回傳一份函式 (function) 的 _複製_ 且不會立即執行。
-#### 答案: B
+#### 答案:B
-`sayHi` 函數會回傳立即執行函式表示式(IIFE)的回傳值。 該函數回傳類型為 `"number"` 的 `0`。
-FYI: JS只有7種原生類型(type) : `null`, `undefined`, `boolean`, `number`, `string`, `object`, `symbol`, 和 `bigint`. `"function"` 不是一種類型而是物件。
+`sayHi` 函數會回傳立即執行函式表示式 (IIFE)的回傳值。該函數回傳類型為 `"number"` 的 `0`。
+FYI: JS 只有 7 種原生類型 (type) : `null`, `undefined`, `boolean`, `number`, `string`, `object`, `symbol`, 和 `bigint`. `"function"` 不是一種類型而是物件。
-#### 答案: A
+#### 答案:A
只有八個值是 falsy
@@ -1075,7 +1075,7 @@ undefined;
- `-0`
- `0n` (BigInt(0))
-函式建構式(Function constructors) 如 `new Number` 和 `new Boolean` 都為 truthy。
+函式建構式 (Function constructors) 如 `new Number` 和 `new Boolean` 都為 truthy。
-#### 答案: B
+#### 答案:B
`typeof 1` 回傳 `"number"`
`typeof "number"` 回傳 `"string"`
@@ -1122,11 +1122,11 @@ console.log(numbers);
-#### 答案: C
+#### 答案:C
-當您設置的元素其位置大過陣列長度時,JavaScript 會建立一個叫做 "empty slots" 的物件, 它們的值實際上為 `undefined`。
+當您設置的元素其位置大過陣列長度時,JavaScript 會建立一個叫做 "empty slots" 的物件,它們的值實際上為 `undefined`。
-但您會看到類似的輸出內容 : `[1, 2, 3, 7 x empty, 11]`。實際執行環境會使其輸出內容略微不同 (瀏覽器, node... 等)
+但您會看到類似的輸出內容 : `[1, 2, 3, 7 x empty, 11]`。實際執行環境會使其輸出內容略微不同 (瀏覽器,node... 等)
-#### 答案: A
+#### 答案:A
-程式中的 `catch` 區塊捕獲了一個例外情況且賦殖予 argument `x`。這個 `x` 是在區塊內產生的,其有效範圍只在區塊內(block-scoped),它跟 `console.log` 中所傳入的 `x` 並不是同一個。
+程式中的 `catch` 區塊捕獲了一個例外情況且賦殖予 argument `x`。這個 `x` 是在區塊內產生的,其有效範圍只在區塊內 (block-scoped),它跟 `console.log` 中所傳入的 `x` 並不是同一個。
-接著我們將此區塊變數 `x` 設置為等於 `1`,並設置變數 `y` 的值, 現在我們 console.log 區塊變數 `x`,無意外地它輸出 `1`。
+接著我們將此區塊變數 `x` 設置為等於 `1`,並設置變數 `y` 的值,現在我們 console.log 區塊變數 `x`,無意外地它輸出 `1`。
-而在 `catch` 區塊之外的 `x` 仍然是 `undefined` 且 `y` 是 `2`。 因此當我們想在 `catch` 區塊之外使用 `console.log(x)` 時,它回傳 `undefined`,而 `y` 回傳 `2`。
+而在 `catch` 區塊之外的 `x` 仍然是 `undefined` 且 `y` 是 `2`。因此當我們想在 `catch` 區塊之外使用 `console.log(x)` 時,它回傳 `undefined`,而 `y` 回傳 `2`。
-#### 答案: A
+#### 答案:A
JavaScript 只有 primitive types 和 objects.
而 Primitive types 包含 `boolean`, `null`, `undefined`, `bigint`, `number`, `string`, 和 `symbol`.
-Primitive 不同於 object 的是它沒有任何的屬性(properties) 和方法(methods); 沒有方法的情況下為何 `'foo'.toUpperCase()` (string) 是輸出 `'FOO'` 而不是 `TypeError` ?
-這是因為當您嘗試訪問 primitive types (例如字串) 的屬性或方法時,JavaScript會使用其中一個 wrapper classes 包裝該 primitive type。
+Primitive 不同於 object 的是它沒有任何的屬性 (properties) 和方法 (methods); 沒有方法的情況下為何 `'foo'.toUpperCase()` (string) 是輸出 `'FOO'` 而不是 `TypeError` ?
+這是因為當您嘗試訪問 primitive types (例如字串) 的屬性或方法時,JavaScript 會使用其中一個 wrapper classes 包裝該 primitive type。
-例如使用了 `String` 包裝 primitive type `string`, 接著在 expression 被 evaluates 後拋棄該包裝。 所有 primitives 除了 `null` 和 `undefined` 外都是遵循此行為。
+例如使用了 `String` 包裝 primitive type `string`,接著在 expression 被 evaluates 後拋棄該包裝。所有 primitives 除了 `null` 和 `undefined` 外都是遵循此行為。
-#### 答案: C
+#### 答案:C
-`[1, 2]` 為初始值,同時也是第一個 `acc`。 在第一輪中, `acc` 是 `[1,2]` 且 `cur` 是 `[0, 1]`,兩陣列連接後的結果是 `[1, 2, 0, 1]`。
+`[1, 2]` 為初始值,同時也是第一個 `acc`。在第一輪中,`acc` 是 `[1,2]` 且 `cur` 是 `[0, 1]`,兩陣列連接後的結果是 `[1, 2, 0, 1]`。
接著 `[1, 2, 0, 1]` 是 `acc` 且 `[2, 3]` 是 `cur`,兩陣列連接後的結果是 `[1, 2, 0, 1, 2, 3]`。
@@ -1243,7 +1243,7 @@ Primitive 不同於 object 的是它沒有任何的屬性(properties) 和方法(
-#### 答案: B
+#### 答案:B
`null` 是 falsy. `!null` 回傳 `true`. `!true` 回傳 `false`.
@@ -1270,7 +1270,7 @@ setInterval(() => console.log('Hi'), 1000);
-#### 答案: A
+#### 答案:A
會回傳一個唯一的 id,並可用於 `clearInterval()` 以清除該 interval。
@@ -1293,9 +1293,9 @@ setInterval(() => console.log('Hi'), 1000);
-#### 答案: A
+#### 答案:A
-字串(string) 類別是可以被迭代的(iterable), 展開運算子(spread operator) 將可迭代的字元(character) 映射(map) 置一個元素(element) 上。
+字串 (string) 類別是可以被迭代的 (iterable),展開運算子 (spread operator) 將可迭代的字元 (character) 映射 (map) 置一個元素 (element) 上。
-#### 答案: C
+#### 答案:C
-一般函式不能在被呼叫後中途停止。但是, generator 可以在中途 "停止" 且之後可以從停止的位置繼續執行。
-每當一個 generator 函式遇到一個 `yield` 關鍵字時,該函式就會產生其後指定的值。 請注意,在這種情況下,generator 函式不是 _return_ 值,而是 _yields_ 值。
+一般函式不能在被呼叫後中途停止。但是,generator 可以在中途 "停止" 且之後可以從停止的位置繼續執行。
+每當一個 generator 函式遇到一個 `yield` 關鍵字時,該函式就會產生其後指定的值。請注意,在這種情況下,generator 函式不是 _return_ 值,而是 _yields_ 值。
-首先,我們使用等於 "10" 的 "i" 初始化 generator 函式。 我們使用 "next()" 方法呼叫 generator 函式。 第一次呼叫 generator 函式時, "i" 等於 "10"。
-它遇到第一個 `yield` 關鍵字:它產生 `i` 的值。 現在,generator 已 "暫停", 並且記錄了 "10"。
+首先,我們使用等於 "10" 的 "i" 初始化 generator 函式。我們使用 "next()" 方法呼叫 generator 函式。第一次呼叫 generator 函式時, "i" 等於 "10"。
+它遇到第一個 `yield` 關鍵字:它產生 `i` 的值。現在,generator 已 "暫停",並且記錄了 "10"。
-然後,我們使用 `next()` 方法再次呼叫該函式。 它將從先前停止的地方繼續,仍然是 "i" 等於 "10"。 現在,它遇到下一個 `yield` 關鍵字,並產生 `i * 2` 。
-"i" 等於 "10",因此回傳 "10 * 2",即 "20"。 故結果為10、20。
+然後,我們使用 `next()` 方法再次呼叫該函式。它將從先前停止的地方繼續,仍然是 "i" 等於 "10"。現在,它遇到下一個 `yield` 關鍵字,並產生 `i * 2`。
+"i" 等於 "10",因此回傳 "10 * 2",即 "20"。故結果為 10、20。
-#### 答案: B
+#### 答案:B
當我們向 Promise.race 方法傳遞多個 promise 時,它將 resolves / rejects _最先的_ promise。
-在 setTimeout 方法中,我們傳遞了一個計時器:第一個 promise(firstPromise)為500毫秒,第二個 promise(secondPromise)為100毫秒。 這意味著 "secondPromise" 將先用 "two" 的值進行resolves。 現在, `res` 擁有 'two' 的值且該值被 console.log。
+在 setTimeout 方法中,我們傳遞了一個計時器:第一個 promise(firstPromise)為 500 毫秒,第二個 promise(secondPromise)為 100 毫秒。這意味著 "secondPromise" 將先用 "two" 的值進行 resolves。現在,`res` 擁有 'two' 的值且該值被 console.log。
-#### 答案: D
+#### 答案:D
首先,我們宣告一個物件變數 `person` 包含 `name` 屬性以及值 `Lydia`。
@@ -1434,10 +1434,10 @@ for (const item in person) {
-#### 答案: B
+#### 答案:B
-通過 `for-in` 循環,我們可以遍歷物件的鍵,在這個題目中的鍵是 `name` 和 `age`。 在內部,物件鍵是字串(strings)(如果它們不是 Symbol)。
-在每次循環中,我們將 `item` 的值設置為等於其迭代的當前鍵。 第一輪循環中,`item` 等於 `name`,並輸出內容。 接著, `item` 等於 `age`,並輸出內容。
+通過 `for-in` 循環,我們可以遍歷物件的鍵,在這個題目中的鍵是 `name` 和 `age`。在內部,物件鍵是字串 (strings)(如果它們不是 Symbol)。
+在每次循環中,我們將 `item` 的值設置為等於其迭代的當前鍵。第一輪循環中,`item` 等於 `name`,並輸出內容。接著,`item` 等於 `age`,並輸出內容。
-#### 答案: B
+#### 答案:B
運算子關聯性是編譯器計算表達式的順序,從左到右或從右到左。僅適用於所有運算子具有 _相同_ 優先級時,才會發生這種情況。
-在這裡我們只有一種類型的運算子:+。 而其關聯性是從左到右。
+在這裡我們只有一種類型的運算子:+。而其關聯性是從左到右。
-首先計算 `3 + 4`。 結果為數字7。
+首先計算 `3 + 4`。結果為數字 7。
-由於強制(coercion) ,`7 +'5'` 會導致結果為 `75`。JavaScript將數字 `7` 轉換型態成字串,請參閱問題15。我們可以使用 `+` 運算子將兩個字串連接起來。 `7` + `5` 產生 `75`。
+由於強制 (coercion) ,`7 +'5'` 會導致結果為 `75`。JavaScript 將數字 `7` 轉換型態成字串,請參閱問題 15。我們可以使用 `+` 運算子將兩個字串連接起來。`7` + `5` 產生 `75`。
-#### 答案: C
+#### 答案:C
-僅會回傳字串中的第一個數字。 基於 _radix_ (第二個參數,用於指定我們要將其解析為哪種類型的數字:以10為基數,十六進制,八進制,二進制等),`parseInt` 檢查字串中的字元是否有效。
+僅會回傳字串中的第一個數字。基於 _radix_ (第二個參數,用於指定我們要將其解析為哪種類型的數字:以 10 為基數,十六進制,八進制,二進制等),`parseInt` 檢查字串中的字元是否有效。
一旦遇到基數中無效數字的字元,它將停止解析並忽略以下字元。
`*` 不是合法的 `number`,所以程式僅將字串形態的 `"7"` 轉換至 decimal 形態的 `7`,故 `num` 現在的值為 `7`。
@@ -1515,9 +1515,9 @@ const num = parseInt('7*6', 10);
-#### 答案: C
+#### 答案:C
-當對陣列做映射(map) 時,`num` 的值等同於它當前正在循環的元素。在這種情況中元素均為 numbers,所以條件式 `typeof num === "number"` 會回傳 `true` 的值。
+當對陣列做映射 (map) 時,`num` 的值等同於它當前正在循環的元素。在這種情況中元素均為 numbers,所以條件式 `typeof num === "number"` 會回傳 `true` 的值。
map 函式會建立一個新陣列,並插入該函式回傳的值。
但是我們不回傳任何值。當我們不從函式回傳值時,函式將回傳 `undefined`。由於陣列中的每個元素都會呼叫該函式,因此對於每個元素,我們都回傳 `undefined`。
@@ -1551,15 +1551,15 @@ console.log(person, birthYear);
-#### 答案: A
+#### 答案:A
-參數是透過 _value_ 傳遞,除非它們是一個物件(object),物件則由透過 _reference_ 傳遞。 `birthYear` 是透過值傳遞的,因為它是字串不是物件。 當我們按值傳遞參數時,將建立該值的 _copy_ (請參閱問題46)。
+參數是透過 _value_ 傳遞,除非它們是一個物件 (object),物件則由透過 _reference_ 傳遞。`birthYear` 是透過值傳遞的,因為它是字串不是物件。當我們按值傳遞參數時,將建立該值的 _copy_ (請參閱問題 46)。
變數 `birthYear` 具有對值 `1997` 的 reference。參數 `year` 也有對值 `1997` 的 reference,但與變數 `birthYear` 所 reference 的不同。
-因此當我們通過將 `year` 設置為等於 `1998` 來更新 `year` 的值時,我們僅更新了 `year` 的值。 `birthYear` 仍然等於 `"1997"`。
+因此當我們通過將 `year` 設置為等於 `1998` 來更新 `year` 的值時,我們僅更新了 `year` 的值。`birthYear` 仍然等於 `"1997"`。
-`person` 的值是一個物件。 參數 `member` 具有(複製的)reference 指向 _相同_ 物件。
-因此當我們修改物件 `member` 的屬性時, `person` 的值也會被修改,因為它們都 reference 了相同的物件。 `person` 的 `name` 屬性現在等於值 `"Lydia"`。
+`person` 的值是一個物件。參數 `member` 具有(複製的)reference 指向 _相同_ 物件。
+因此當我們修改物件 `member` 的屬性時,`person` 的值也會被修改,因為它們都 reference 了相同的物件。`person` 的 `name` 屬性現在等於值 `"Lydia"`。
-#### 答案: D
+#### 答案:D
-使用 `throw` 語句,我們可以建立自定義的錯誤。 使用此語句,您可以觸發例外(exception)。例外可以是 `string b>`,`number b>`,`boolean b>` 或 `object b>`。
+使用 `throw` 語句,我們可以建立自定義的錯誤。使用此語句,您可以觸發例外 (exception)。例外可以是 `string b>`,`number b>`,`boolean b>` 或 `object b>`。
在這種情況下,我們的例外是字串 `Hello world`。
-通過 `catch` 語句,我們可以指定如果在 `try` 的程式區塊中拋出例外時該怎麼辦。 例如拋出例外:字串 `'Hello world'`。
-現在, `e` 等於我們記錄的字串。 因此輸出結果將會是 `'Oh an error: Hello world'`。
+通過 `catch` 語句,我們可以指定如果在 `try` 的程式區塊中拋出例外時該怎麼辦。例如拋出例外:字串 `'Hello world'`。
+現在,`e` 等於我們記錄的字串。因此輸出結果將會是 `'Oh an error: Hello world'`。
-#### 答案: B
+#### 答案:B
-當您回傳屬性(property) 時,該屬性的值等於 _returned_ 的值,而不是在函式建構式(constructor function)中設置的值。 我們回傳字串 `Maserati`,因此 `mycar.make` 等於 `Maserati`。
+當您回傳屬性 (property) 時,該屬性的值等於 _returned_ 的值,而不是在函式建構式 (constructor function) 中設置的值。我們回傳字串 `Maserati`,因此 `myCar.make` 等於 `Maserati`。
-#### 答案: A
+#### 答案:A
`let x = y = 10;` 實際上是 shorthand for:
@@ -1663,13 +1663,13 @@ y = 10;
let x = y;
```
-當我們將 `y `設置為等於 `10` 時,我們實際上將屬性 `y` 加入到 global object 中(瀏覽器中的 `window`,Node中的 `global`)。 現在,瀏覽器中 `window.y` 現在等於 `10`。
+當我們將 `y `設置為等於 `10` 時,我們實際上將屬性 `y` 加入到 global object 中(瀏覽器中的 `window`,Node 中的 `global`)。現在,瀏覽器中 `window.y` 現在等於 `10`。
-接著我們宣告一個變數 `x`,並將其值賦予為 `y`,即 `10`。 用` let` 關鍵字宣告的變數是 _block scoped_ ,它們僅在宣告它們的區塊中定義; 另外此案例的函示是,立即函示表達式(IIFE)。
-當我們使用 `typeof` 運算子時, `x` 並未被定義:我們試圖在宣告它的區塊外訪問 `x`。這將獲得 `x` 並未被定義的結果。 未分配值或未宣告的值的類型為 `"undefined"`。 `console.log(typeof x)` 回傳 `"undefined"`。
+接著我們宣告一個變數 `x`,並將其值賦予為 `y`,即 `10`。用` let` 關鍵字宣告的變數是 _block scoped_,它們僅在宣告它們的區塊中定義;另外此案例的函示是,立即函示表達式(IIFE)。
+當我們使用 `typeof` 運算子時,`x` 並未被定義:我們試圖在宣告它的區塊外訪問 `x`。這將獲得 `x` 並未被定義的結果。未分配值或未宣告的值的類型為 `"undefined"`。`console.log(typeof x)` 回傳 `"undefined"`。
-但是,當將 `y` 設置為 `10` 時,我們建立了global variable `y`。 在我們程式中的任何位置均可訪問此值。
-`y` 被定義,並且為類型 `number` 的值。 因此 `console.log(typeof y` 回傳 `"number"`。
+但是,當將 `y` 設置為 `10` 時,我們建立了 global variable `y`。在我們程式中的任何位置均可訪問此值。
+`y` 被定義,並且為類型 `number` 的值。因此 `console.log(typeof y` 回傳 `"number"`。
-#### 答案: A
+#### 答案:A
-透過 `delete` 關鍵字,我們可以從物件中刪除它的屬性。同樣適用在原型(prototype)。通過刪除原型上的屬性,該屬性在原型鏈中將不可再被使用。
-在這個案例中, `bark` 函式在 `delete Dog.prototype.bark` 之後的原型上不再可用,但是我們仍然嘗試訪問它。
+透過 `delete` 關鍵字,我們可以從物件中刪除它的屬性。同樣適用在原型 (prototype)。通過刪除原型上的屬性,該屬性在原型鏈中將不可再被使用。
+在這個案例中,`bark` 函式在 `delete Dog.prototype.bark` 之後的原型上不再可用,但是我們仍然嘗試訪問它。
-因此當我們嘗試呼叫不是函式的東西時,程式將拋出 `TypeError`。 在這個案例中,將為 `TypeError: pet.bark is not a function` ,因為 `pet.bark` 是 `undefined`。
+因此當我們嘗試呼叫不是函式的東西時,程式將拋出 `TypeError`。在這個案例中,將為 `TypeError: pet.bark is not a function`,因為 `pet.bark` 是 `undefined`。
-#### 答案: D
+#### 答案:D
-`Set` 物件是 _唯一_ 值的集合: 任何存在於 `Set` 的值均為唯一的,不會存在相同的值(重複的值將會由後出現的覆蓋已出現的)。
+`Set` 物件是 _唯一_ 值的集合:任何存在於 `Set` 的值均為唯一的,不會存在相同的值 (重複的值將會由後出現的覆蓋已出現的)。
陣列 `[1, 1, 2, 3, 4]` 中有重複的值 `1`,因此結果會是 `{1, 2, 3, 4}`。
@@ -1770,11 +1770,11 @@ console.log(myCounter);
-#### 答案: C
+#### 答案:C
-被引用(imported) 的模組(module) 是 _唯讀_ 的: 您無法修改被引用模組中項目,只有輸出(export) 該項目的模組可以更改它的值。
+被引用 (imported) 的模組 (module) 是 _唯讀_ 的:您無法修改被引用模組中項目,只有輸出 (export) 該項目的模組可以更改它的值。
-因此當我們嘗試增加 `myCounter` 的值時,他將拋出錯誤: `myCounter` is read-only and cannot be modified。
+因此當我們嘗試增加 `myCounter` 的值時,他將拋出錯誤:`myCounter` is read-only and cannot be modified。
-#### 答案: A
+#### 答案:A
-`delete` 運算子會回傳一個布林值: 成功刪除物件的情況下會回傳 `true`,反之則為 `false`。 但是經由 `var`,`const` 或是 `let` 關鍵字所宣告的變數是無法使用 `delete` 運算子刪除的。
+`delete` 運算子會回傳一個布林值:成功刪除物件的情況下會回傳 `true`,反之則為 `false`。但是經由 `var`,`const` 或是 `let` 關鍵字所宣告的變數是無法使用 `delete` 運算子刪除的。
-此處, `name` 無法成功刪除且會回傳 `fasle`,因為它是經由 `const` 所宣告。當我們宣告 `age` 的值為 `21` 時,實際上我們做的是將一個名為 `age` 的屬性為添加到了全球物件中,您可以透過 `delete` 來刪除物件中的屬性,因此您也能刪除全球物件中的屬性,故將回傳 `true`。
+此處,`name` 無法成功刪除且會回傳 `false`,因為它是經由 `const` 所宣告。當我們宣告 `age` 的值為 `21` 時,實際上我們做的是將一個名為 `age` 的屬性為添加到了全球物件中,您可以透過 `delete` 來刪除物件中的屬性,因此您也能刪除全球物件中的屬性,故將回傳 `true`。
-#### 答案: C
+#### 答案:C
-我們可以通過解構(destructuring) 從陣列或物件的屬性中獲得值。例如:
+我們可以通過解構 (destructuring) 從陣列或物件的屬性中獲得值。例如:
```javascript
[a, b] = [1, 2];
@@ -1837,7 +1837,7 @@ console.log(y);
-#### 答案: B
+#### 答案:B
-使用 spread 運算子可以合併物件(`...`)。它使您可以建立一個物件的鍵/值的複製,並將其添加到另一物件中。
+使用 spread 運算子可以合併物件 (`...`)。它使您可以建立一個物件的鍵/值的複製,並將其添加到另一物件中。
在這裡我們建立了 `user` 物件的複製並將其添加至 `admin` 物件。因此將輸出 `{ admin: true, name: "Lydia", age: 21 }`。
-#### 答案: B
+#### 答案:B
-透過 `defineProperty`,我們可以對物件增加新的屬性或是修改已經存在的屬性。當我們使用 `defineProperty` 增加物件的屬性時,它們被預設為 _不可 enumerable_ 。
+透過 `defineProperty`,我們可以對物件增加新的屬性或是修改已經存在的屬性。當我們使用 `defineProperty` 增加物件的屬性時,它們被預設為 _不可 enumerable_。
`Object.keys` 方法僅回傳物件中所有 _可 enumerable_ 的屬性名稱,這個案例中只有 `"name"`。
預設下,使用 `defineProperty `方法增加的屬性是不可變的。但您可以覆蓋這個行為透過 `writable`,`configurable` 及 `enumerable` 屬性。
@@ -1932,14 +1932,14 @@ console.log(data);
-#### 答案: A
+#### 答案:A
-`JSON.stringify` 的第二個參數是 _替換者 (replacer)_ ,替換者可以是函式,也可以是陣列,並允許您控制值要如何獲怎麼串化(stringified)。
+`JSON.stringify` 的第二個參數是 _替換者 (replacer)_,替換者可以是函式,也可以是陣列,並允許您控制值要如何獲怎麼串化 (stringified)。
-如果替換者是 _陣列_ ,僅將陣列中包含的屬性名稱加到 JSON 字串中。
+如果替換者是 _陣列_,僅將陣列中包含的屬性名稱加到 JSON 字串中。
此案例中,僅有 `"level"` and `"health"` 被包含,`"username"` 沒有被包含在內,因此 `data` 的值將為 `"{"level":19, "health":90}"`。
-如果替換者是 _函式_ ,在要字串化的每個物件屬性上將會呼叫此函式。從此函式回傳的值將是加到 JSON 字串中的屬性的值。如果值為 `undefined`,則此屬性從 JSON 字串中排除。
+如果替換者是 _函式_,在要字串化的每個物件屬性上將會呼叫此函式。從此函式回傳的值將是加到 JSON 字串中的屬性的值。如果值為 `undefined`,則此屬性從 JSON 字串中排除。
-#### 答案: A
+#### 答案:A
-單元運算子 `++` 首先 _回傳_ 操作數的值,然後 _遞增_ 操作數的值。 `num1` 的值是 `10`,因為 `increaseNumber` 函式首先回傳 `num` 的值,即 `10`,之後才遞增 `num` 的值。
+單元運算子 `++` 首先 _回傳_ 操作數的值,然後 _遞增_ 操作數的值。`num1` 的值是 `10`,因為 `increaseNumber` 函式首先回傳 `num` 的值,即 `10`,之後才遞增 `num` 的值。
-`num2` 是 `10`, 因為我們將 `num1` 傳遞給了 `increasePassedNumber`。 `number` 等於 `10`( `num1` 的值。同樣,單元運算子 `++` 首先 _回傳_ 操作數的值,然後 _遞增_ 操作數的值。
+`num2` 是 `10`,因為我們將 `num1` 傳遞給了 `increasePassedNumber`。`number` 等於 `10`(`num1` 的值。同樣,單元運算子 `++` 首先 _回傳_ 操作數的值,然後 _遞增_ 操作數的值。
`number` 的值是 `10`,因此 `num2` 等於 `10`。
-#### 答案: C
+#### 答案:C
-在ES6中,我們可以使用預設值初始化參數。如果沒有其他值傳遞給該函式或是傳入的參數是 `undefined`,則該參數的值為預設值。此案例中,我們將 `value` 物件的屬性擴展到一個新物件中,因此 `x` 具有預設值 `{number:10}`。
+在 ES6 中,我們可以使用預設值初始化參數。如果沒有其他值傳遞給該函式或是傳入的參數是 `undefined`,則該參數的值為預設值。此案例中,我們將 `value` 物件的屬性擴展到一個新物件中,因此 `x` 具有預設值 `{number:10}`。
預設值是在 _呼叫_ 時被 evaluated。每次呼叫該函式時,都會建立一個 _新_ 物件。我們在沒有傳遞值的情況下呼叫了 `multiply` 函式兩次:`x` 的預設值是 `{{number:10}`。因此,我們輸出該數字的相乘值,即 `20`。
-第三次呼叫時,我們確實傳遞了一個參數:名為 `value` 的物件。 `*=` 運算子實際上是 `x.number = x.number * 2` 的簡寫:因此我們修改了 `x.number` 的值,並記錄相乘後的值 `20`。
+第三次呼叫時,我們確實傳遞了一個參數:名為 `value` 的物件。`*=` 運算子實際上是 `x.number = x.number * 2` 的簡寫:因此我們修改了 `x.number` 的值,並記錄相乘後的值 `20`。
-第四次,我們再次傳遞名為 `value` 的物件。 `x.number` 先前已修改為 `20`,因此 `x.number * = 2` 為 `40`。
+第四次,我們再次傳遞名為 `value` 的物件。`x.number` 先前已修改為 `20`,因此 `x.number * = 2` 為 `40`。
-#### 答案: D
+#### 答案:D
-`reduce` 方法接收的第一個參數是 _累加器(accumulator)_ ,在這種情況下是 `x`。 第二個參數是 _current value_ `y`。 使用 `reduce` 方法,我們對陣列中的每個元素執行一個 callback 函式,並在最終回一個值。
+`reduce` 方法接收的第一個參數是 _累加器 (accumulator)_,在這種情況下是 `x`。第二個參數是 _current value_ `y`。使用 `reduce` 方法,我們對陣列中的每個元素執行一個 callback 函式,並在最終回一個值。
在此示例中,我們不回傳任何值,僅記錄了累加器的值和當前值。
-累加器的值等於 callback 函式先前回傳的值。 如果沒有 `initialValue` 參數傳遞給 `reduce` 方法,則累加器的初始值將會等於第一個元素。
+累加器的值等於 callback 函式先前回傳的值。如果沒有 `initialValue` 參數傳遞給 `reduce` 方法,則累加器的初始值將會等於第一個元素。
-在第一個呼叫中,累加器(`x`)為`1`,當前值(`y`)為`2`。 我們不從 callback 函式回傳,而是輸出累加器和當前值:`1` 和 `2`。
+在第一個呼叫中,累加器(`x`)為`1`,當前值(`y`)為`2`。我們不從 callback 函式回傳,而是輸出累加器和當前值:`1` 和 `2`。
-如果您不從 callback 函式回傳值,則它將回傳 `undefined`。 在下一次呼叫時,累加器為 `undefined`,當前值為 `3`。 於是 `undefined` 和 `3` 被輸出。
+如果您不從 callback 函式回傳值,則它將回傳 `undefined`。在下一次呼叫時,累加器為 `undefined`,當前值為 `3`。於是 `undefined` 和 `3` 被輸出。
-在第四次呼叫中,我們再次不從 callback 函式回傳。 累加器再次為 `undefined`,當前值為 `4`。於是 `undefined` 和 `4` 被輸出。
+在第四次呼叫中,我們再次不從 callback 函式回傳。累加器再次為 `undefined`,當前值為 `4`。於是 `undefined` 和 `4` 被輸出。
-#### 答案: B
+#### 答案:B
-在子類別中,在呼叫 `super` 前不能存取 `this` 關鍵字,如果你這麼做,它將拋出一個 `ReferenceError`,建構式1與4會引發這個錯誤。
+在子類別中,在呼叫 `super` 前不能存取 `this` 關鍵字,如果你這麼做,它將拋出一個 `ReferenceError`,建構式 1 與 4 會引發這個錯誤。
使用 `super` 關鍵字時,我們要提供參數給父類別呼叫其建構式。父類別需要接受一個 `name` 參數,所以我們需要把 `name` 傳給 `super`。
-`Labrador` 類別接收兩個參數, `name` 參數是由於它繼承了 `Dog` , `size` 作為`Labrador` 類的額外屬性,它們都需要傳遞給 `Labrador` 的建構式,因此使用建構式2是正確答案。
+`Labrador` 類別接收兩個參數,`name` 參數是由於它繼承了 `Dog`,`size` 作為`Labrador` 類的額外屬性,它們都需要傳遞給 `Labrador` 的建構式,因此使用建構式 2 是正確答案。
-#### 答案: B
+#### 答案:B
`import` 命令是 _編譯階段_ 執行的。這代表被引入的模組會優先執行,而引入模組的檔案會 _之後執行_。
-這是 `CommonJS` 中 `require()` 和 `import` 之間的區別!使用 `require()`,您可以在執行程式時根據需要戴入依賴的項目。如果我們使用 `require` 而不是 `import` 來執行此題, 結果將會依 `running index.js`,`running sum.js`,`3` 的順序輸出。
+這是 `CommonJS` 中 `require()` 和 `import` 之間的區別!使用 `require()`,您可以在執行程式時根據需要戴入依賴的項目。如果我們使用 `require` 而不是 `import` 來執行此題,結果將會依 `running index.js`,`running sum.js`,`3` 的順序輸出。
-#### 答案: A
+#### 答案:A
-每個 Symbol 都是完全唯一的。傳遞給 Symbol 的參數只是給 Symbol 的一個描述。 Symbol 的值不依賴於傳遞的參數。當我們建立兩個全新的 Symbol 去比較時:第一個`Symbol('foo')`,第二個`Symbol('foo')`, 因這兩個值是唯一的,彼此不相等,因此 `Symbol('foo') === Symbol('foo')` 會得到 `false`。
+每個 Symbol 都是完全唯一的。傳遞給 Symbol 的參數只是給 Symbol 的一個描述。Symbol 的值不依賴於傳遞的參數。當我們建立兩個全新的 Symbol 去比較時:第一個`Symbol('foo')`,第二個`Symbol('foo')`, 因這兩個值是唯一的,彼此不相等,因此 `Symbol('foo') === Symbol('foo')` 會得到 `false`。
-#### 答案: C
+#### 答案:C
-使用 `padStart` 函數,我們可以在字串的前面加上填充字串。傳遞給此函數的參數是字串的總長度(包含填充字串)。字串 Lydia Hallie 的長度為 `12` , 因此 `name.padStart(13)` 在字串的開頭只會插入1個空格,因為 12 + 1 等於 13。
+使用 `padStart` 函數,我們可以在字串的前面加上填充字串。傳遞給此函數的參數是字串的總長度(包含填充字串)。字串 Lydia Hallie 的長度為 `12` , 因此 `name.padStart(13)` 在字串的開頭只會插入 1 個空格,因為 12 + 1 等於 13。
如果傳給 `padStart` 函數的參數小於字串的長度,則不會加上填充字串。
@@ -2197,13 +2197,13 @@ console.log('🥑' + '💻');
- A: `"🥑💻"`
- B: `257548`
-- C: 一個包含碼位(code point)的字串
+- C: 一個包含碼位 (code point) 的字串
- D: 錯誤
-#### 答案: A
+#### 答案:A
使用 `+` 運算元,你可以連接字串。在此例,我們將字串“🥑”與字串”💻“連接起來,產生”🥑💻“。
@@ -2216,7 +2216,7 @@ console.log('🥑' + '💻');
```javascript
function* startGame() {
- const answer = yield '你喜歡 JavaScript 嗎?';
+ const answer = yield '你喜歡 JavaScript 嗎?';
if (answer !== 'Yes') {
return "哦,我想我們該走了";
}
@@ -2224,7 +2224,7 @@ function* startGame() {
}
const game = startGame();
-console.log(/* 1 */); // 你喜歡 JavaScript 嗎?
+console.log(/* 1 */); // 你喜歡 JavaScript 嗎?
console.log(/* 2 */); // JavaScript 也愛你 ❤️
```
@@ -2236,13 +2236,13 @@ console.log(/* 2 */); // JavaScript 也愛你 ❤️
-#### 答案: C
+#### 答案:C
-`generator` 函數在遇到 yield 關鍵字時會 “暫停” 執行。首先,我們需要讓函數產生字串 "你喜歡 JavaScript 嗎?",這可以透過呼叫 `game.next().value` 來完成。
+`generator` 函數在遇到 yield 關鍵字時會“暫停”執行。首先,我們需要讓函數產生字串 "你喜歡 JavaScript 嗎?",這可以透過呼叫 `game.next().value` 來完成。
-`startGame()` 函數會一行一行執行直到遇到 `yield` 關鍵字,在函數裡第一個就有一個 `yield` 關鍵字:所以執行到第一行就停止了! _此時answer變數還尚未定義_
+`startGame()` 函數會一行一行執行直到遇到 `yield` 關鍵字,在函數裡第一個就有一個 `yield` 關鍵字:所以執行到第一行就停止了!_此時 answer 變數還尚未定義_
-當我們呼叫 `game.next("Yes").value`,前一個 `yield` 被傳遞給 `next()` 的參數值所取代。此例我們使用 `Yes`。變數 `answer` 的值現在等於 `Yes`。 if 語句的條件回傳 `false`,並且會回傳 `JavaScript 也愛你 ❤️` 。
+當我們呼叫 `game.next("Yes").value`,前一個 `yield` 被傳遞給 `next()` 的參數值所取代。此例我們使用 `Yes`。變數 `answer` 的值現在等於 `Yes`。if 語句的條件回傳 `false`,並且會回傳 `JavaScript 也愛你 ❤️`。
-#### 答案: C
+#### 答案:C
-`String.raw`會回傳一個字串,其中轉義符(`/n`, `/v`, `/t`等)被忽略! 反斜線可能是一個問題,因為你可能會有這樣的結果。
+`String.raw`會回傳一個字串,其中轉義符 (`/n`, `/v`, `/t`等) 被忽略!反斜線可能是一個問題,因為你可能會有這樣的結果。
`const path = "C:\Documents\Projects\table.html"`。
@@ -2303,9 +2303,9 @@ console.log(data);
-#### 答案: C
+#### 答案:C
-一個異步函數總是回傳一個 promise 。 `await` 仍然要等待 promise 的 resolve:當我們呼叫 `getData()` 等於 `data` 時,會得到一個等待的 promise。
+一個異步函數總是回傳一個 promise。 `await` 仍然要等待 promise 的 resolve:當我們呼叫 `getData()` 等於 `data` 時,會得到一個等待的 promise。
如果我們想獲取 resolve 後的值`"I made it"`,我們可以在`data`上使用`.then()`函數:
@@ -2337,11 +2337,11 @@ console.log(result);
-#### 答案: B
+#### 答案:B
`.push()`函數回傳的是陣列的長度!原本陣列包含一個元素(字串`"香蕉"`),長度為`1`。後來將字串 `"apple"` 加到陣列中後,陣列包含兩個元素。所以會從`addToList`函數中得到,長度為 `"2"`。
-`push`函數修改了原來的陣列。如果你想從函數中回傳 _陣列_ 而不是 _陳列的長度_ ,你應該在加完`item`到陣列後,回傳`list`。
+`push`函數修改了原來的陣列。如果你想從函數中回傳 _陣列_ 而不是 _陳列的長度_,你應該在加完`item`到陣列後,回傳`list`。
-#### 答案: B
+#### 答案:B
-`Object.freeze` 使我們無法增加、刪除或修改Object的屬性(除非該屬性的值是另一個Object)。
+`Object.freeze` 使我們無法增加、刪除或修改 Object 的屬性(除非該屬性的值是另一個 Object)。
-當我們建立變數`shape`並等同被凍結的Object`box`時,`shape`也是指一個被凍結的Object。你可以透過使用`Object.isFrozen`檢查一個Object是否被凍結。在這種情況下,`Object.isFrozen(shape)`回傳true,因為變數`shape`也指向一個凍結Object。
+當我們建立變數`shape`並等同被凍結的 Object`box`時,`shape`也是指一個被凍結的 Object。你可以透過使用`Object.isFrozen`檢查一個 Object 是否被凍結。在這種情況下,`Object.isFrozen(shape)`回傳 true,因為變數`shape`也指向一個凍結 Object。
-由於`shape`是被凍結的,而且`x`的值不是一個Object,所以我們不能修改`x`的屬性。 `x`仍然等於`10`,於是`{ x: 10, y: 20 }`被記錄下來。
+由於`shape`是被凍結的,而且`x`的值不是一個 Object,所以我們不能修改`x`的屬性。`x`仍然等於`10`,於是`{ x: 10, y: 20 }`被記錄下來。
-#### 答案: D
+#### 答案:D
當我們從右側的物件解構屬性`name`時,我們將其值`Lydia`分配給名為`myName`的變數。
-使用`{name:myName}`,我們是在告訴JavaScript我們要建立一個名為`myName`的新變數,並且其值是右側物件的`name`屬性的值。
+使用`{name:myName}`,我們是在告訴 JavaScript 我們要建立一個名為`myName`的新變數,並且其值是右側物件的`name`屬性的值。
當我們嘗試輸出`name`,一個未定義的變數時,就會引發`ReferenceError`。
@@ -2411,7 +2411,7 @@ console.log(name);
---
-###### 77. 以下是純函數嗎?
+###### 77. 以下是純函數嗎?
```javascript
function sum(a, b) {
@@ -2425,7 +2425,7 @@ function sum(a, b) {
-#### 答案: B
+#### 答案:B
純函數一種若輸入參數相同,則永遠會得到相同輸出的函數。
@@ -2474,7 +2474,7 @@ console.log(addFunction(5 * 2));
-#### 答案: C
+#### 答案:C
`add`函數是一個記憶函數。通過記憶化,我們可以暫存函數的結果,以加快其執行速度。上述情況,我們建立一個`cache`物件,用於存儲先前存過的值。
@@ -2482,11 +2482,11 @@ console.log(addFunction(5 * 2));
我們用相同的值三次呼叫了`addFunction`函數:
-在第一次呼叫,`num`等於`10`時函數的值尚未暫存,if語句`num in cache`回傳`false`,else塊的代碼被執行:`Calculated! 20`,並且其結果被添加到暫存物件,`cache`現在看起來像`{10:20}`。
+在第一次呼叫,`num`等於`10`時函數的值尚未暫存,if 語句`num in cache`回傳`false`,else 塊的代碼被執行:`Calculated! 20`,並且其結果被添加到暫存物件,`cache`現在看起來像`{10:20}`。
-第二次,`cache`物件包含`10`的回傳值。 if語句 `num in cache` 回傳`true`,印出`From cache! 20`。
+第二次,`cache`物件包含`10`的回傳值。if 語句 `num in cache` 回傳`true`,印出`From cache! 20`。
-第三次,我們將`5 * 2`(值為10)傳遞給函數。 `cache`物件包含`10`的回傳值。 if語句 `num in cache` 回傳`true`,印出`From cache! 20`。
+第三次,我們將`5 * 2`(值為 10) 傳遞給函數。`cache`物件包含`10`的回傳值。if 語句 `num in cache` 回傳`true`,印出`From cache! 20`。
-#### 答案: A
+#### 答案:A
-透過`for-in`迴圈,我們可以遍歷一個物件**自有的**、**繼承的**、**可列舉的**、**非Symbol的**屬性。在陣列中,可列舉屬性是陣列元素的“鍵”, 即它們的索引。類似於下面這個物件:
+透過`for-in`迴圈,我們可以遍歷一個物件**自有的**、**繼承的**、**可列舉的**、**非 Symbol 的**屬性。在陣列中,可列舉屬性是陣列元素的“鍵”,即它們的索引。類似於下面這個物件:
`{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}`
@@ -2544,11 +2544,11 @@ console.log(list)
-#### 答案: C
+#### 答案:C
-陣列元素可以包含任何值。數字,字符,布林,物件,陣列,`null`,`undeifned`, 以及其他表達式,如日期,函數和計算式。
+陣列元素可以包含任何值。數字,字符,布林,物件,陣列,`null`,`undefined`, 以及其他表達式,如日期,函數和計算式。
-元素將等於回傳的值。 `1 + 2`回傳`3`,`1 * 2`回傳'2`,'1 / 2`回傳`0.5`。
+元素將等於回傳的值。`1 + 2`回傳`3`,`1 * 2`回傳'2`,'1 / 2`回傳`0.5`。
-#### 答案: B
+#### 答案:B
-預設情況下,如果不傳參數給函數,函數內參數的值將為`undefined`。上述情況,我們沒有給參數`name`傳值。 `name`等於`undefined`,並被印出。
+預設情況下,如果不傳參數給函數,函數內參數的值將為`undefined`。上述情況,我們沒有給參數`name`傳值。`name`等於`undefined`,並被印出。
-在ES6中,我們可以使用預設參數覆蓋此預設的`undefined`值。例如:
+在 ES6 中,我們可以使用預設參數覆蓋此預設的`undefined`值。例如:
-`function sayHi(name =“Lydia”){...}`
+`function sayHi (name =“Lydia”){...}`
在這種情況下,如果我們沒有傳遞值或者如果我們傳遞`undefined`,`name`總是等於字符`Lydia`
@@ -2614,11 +2614,11 @@ setTimeout(() => {
-#### 答案: B
+#### 答案:B
`this`關鍵字的指向取決於使用它的位置。在**函數**中,比如`getStatus`,`this`指向的是呼叫它的物件,上述例子中`data`物件呼叫了`getStatus`,因此`this`指向的就是`data`物件。當我們輸出`this.status`時,`data`物件的`status`屬性被輸出,即`"🥑"`。
-使用`call`方法,可以更改`this`指向的物件。 `data.getStatus.call(this)`是將`this`的指向由`data`物件更改為全局物件。在全局物件上,有一個名為`status`的變數,其值為`”😎“`。因此輸出`this.status`時,會輸出`“😎”`。
+使用`call`方法,可以更改`this`指向的物件。`data.getStatus.call(this)`是將`this`的指向由`data`物件更改為全局物件。在全局物件上,有一個名為`status`的變數,其值為`”😎“`。因此輸出`this.status`時,會輸出`“😎”`。
-#### 答案: A
+#### 答案:A
我們將變數`city`設置為等於`person`物件上名為`city`的屬性的值。這個物件上沒有名為`city`的屬性,因此變數`city`的值為`undefined`。
請注意,我們沒有引用`person`物件本身,只是將變數`city`設置為等於`person`物件上`city`屬性的當前值。
-然後,我們將`city`設置為等於字串`“Amsterdam”`。這不會更改person物件:沒有對該物件的引用。
+然後,我們將`city`設置為等於字串`“Amsterdam”`。這不會更改 person 物件:沒有對該物件的引用。
因此輸出`person`物件時,會回傳未修改的物件。
@@ -2683,9 +2683,9 @@ console.log(checkAge(21))
-#### 答案: C
+#### 答案:C
-`const`和`let`定義的變數是具有**區塊作用域**的,區塊是大括號(`{}`)之間的任何東西, 即上述情況`if / else`語句的大括號。由於區塊作用域,我們無法在定義的塊之外引用變數,因此拋出`ReferenceError`。
+`const`和`let`定義的變數是具有**區塊作用域**的,區塊是大括號(`{}`)之間的任何東西,即上述情況`if / else`語句的大括號。由於區塊作用域,我們無法在定義的塊之外引用變數,因此拋出`ReferenceError`。
-#### 答案: C
+#### 答案:C
第二個`.then`中`res`的值等於前一個`.then`中函數回傳的值。你可以像這樣繼續連接`.then`,將值傳遞給下一個處理程序。
@@ -2715,7 +2715,7 @@ fetch('https://www.website.com/api/user/1')
-#### 答案: A
+#### 答案:A
-使用邏輯非運算子`!`,將回傳一個布林值,使用`!! name`,我們可以確定`name`的值是`true`還是`false`。如果`name`是`true`,那麼`!name`回傳`false`。 `!false`回傳`true`。
+使用邏輯非運算子`!`,將回傳一個布林值,使用`!! name`,我們可以確定`name`的值是`true`還是`false`。如果`name`是`true`,那麼`!name`回傳`false`。`!false`回傳`true`。
通過將`hasName`設置為`name`,可以將`hasName`設置為等於傳遞給`getName`函數的值,而不是布林值`true`。
@@ -2759,11 +2759,11 @@ console.log("I want pizza"[0])
-#### 答案: B
+#### 答案:B
-可以使用雙括號表示法獲取字串中特定索引的字串,字串中的第一個字串具有索引0,依此類推。在這種情況下,我們想要得到索引為0的元素,字串`'I'`被記錄。
+可以使用雙括號表示法獲取字串中特定索引的字串,字串中的第一個字串具有索引 0,依此類推。在這種情況下,我們想要得到索引為 0 的元素,字串`'I'`被記錄。
-請注意,IE7及更低版本不支援此方法。應該使用`.charAt()`
+請注意,IE7 及更低版本不支援此方法。應該使用`.charAt()`
-#### 答案: B
+#### 答案:B
-您可以將預設參數的值設置為函數的另一個參數,只要另一個參數定義在其之前即可。我們將值`10`傳遞給`sum`函數。如果`sum`函數只接收1個參數,則意味著沒有傳遞`num2`的值,這種情況下,`num1`的值等於傳遞的值`10`。 `num2`的預設值是`num1`的值,即`10`。 ```num1 + num2```回傳`20`。
+您可以將預設參數的值設置為函數的另一個參數,只要另一個參數定義在其之前即可。我們將值`10`傳遞給`sum`函數。如果`sum`函數只接收 1 個參數,則意味著沒有傳遞`num2`的值,這種情況下,`num1`的值等於傳遞的值`10`。`num2`的預設值是`num1`的值,即`10`。```num1 + num2```回傳`20`。
如果您嘗試將預設參數的值設置為後面定義的參數,則可能導致參數的值尚未初始化,從而引發錯誤。比如:
```js
@@ -2826,11 +2826,11 @@ console.log(data)
-#### 答案: A
+#### 答案:A
使用`import * as name`語法,我們將`module.js`文件中所有`export`匯入到`index.js`文件中,並且建立了一個名為`data`的新物件。在`module.js`文件中,有兩個匯出:預設匯出和命名匯出。預設匯出是一個回傳字串“Hello World”的函數,命名匯出是一個名為`name`的變數,其值為字串`“Lydia”`。
-`data`物件具有預設匯出的`default`屬性,其他屬性具有指定exports的名稱及其對應的值。
+`data`物件具有預設匯出的`default`屬性,其他屬性具有指定 exports 的名稱及其對應的值。
-#### 答案: C
+#### 答案:C
-class是建構函數的語法糖,如果用建構函數的方式來重寫`Person`class則會是:
+class 是建構函數的語法糖,如果用建構函數的方式來重寫`Person`class 則會是:
```javascript
function Person() {
@@ -2889,11 +2889,11 @@ console.log(newList.push(5))
-#### 答案: D
+#### 答案:D
`.push`函數回傳陣列的長度,而不是陣列本身!通過將`newList`設置為`[1,2,3].push(4)`,實際上`newList`等於陣列的新長度:`4`。
-然後,嘗試在`newList`上使用`.push`函數。由於`newList`是數值`4`,拋出TypeError。
+然後,嘗試在`newList`上使用`.push`函數。由於`newList`是數值`4`,拋出 TypeError。
-#### 答案: D
+#### 答案:D
正規式函數,例如`giveLydiaPizza`函數,有一個`prototype`屬性,它是一個帶有`constructor`屬性的物件(原型物件)。然而,箭頭函數,例如`giveLydiaChocolate`函數,沒有這個`prototype`屬性。嘗試使用`giveLydiaChocolate.prototype`存取`prototype`屬性時會得到`undefined`。
@@ -2949,12 +2949,12 @@ for (const [x, y] of Object.entries(person)) {
-#### 答案: A
+#### 答案:A
`Object.entries()`函數回傳一個給定物件本身可枚舉屬性的鍵值對陣列,上述情況回傳一個二維陣列,陣列每個元素是一個包含鍵和值的陣列:
-`[['name','Lydia'],['age',21]]`
+`[['name','Lydia'],['age', 21]]`
-使用`for-of`循環,我們可以迭代陣列中的每個元素,上述情況是子陣列。我們可以使用`const [x,y]`在`for-of`循環中解構子陣列。 `x`等於子陣列中的第一個元素,`y`等於子陣列中的第二個元素。
+使用`for-of`循環,我們可以迭代陣列中的每個元素,上述情況是子陣列。我們可以使用`const [x,y]`在`for-of`循環中解構子陣列。`x`等於子陣列中的第一個元素,`y`等於子陣列中的第二個元素。
第一個子陣列是`[“name”,“Lydia”]`,其中`x`等於`name`,而`y`等於`Lydia`。
第二個子陣列是`[“age”,21]`,其中`x`等於`age`,而`y`等於`21`。
@@ -2981,7 +2981,7 @@ getItems(["banana", "apple"], "pear", "orange")
-#### 答案: D
+#### 答案:D
`... args`是剩餘參數,剩餘參數的值是一個包含所有剩餘參數的陣列,**並且只能作為最後一個參數**。上面示範中,剩餘參數是第二個參數,這是不可能的,並會拋出語法錯誤。
@@ -3023,19 +3023,19 @@ console.log(nums(1, 2))
-#### 答案: B
+#### 答案:B
-在JavaScript中,我們不必硬性寫分號(`;`),但是JavaScript引擎仍然在語法之後自動補上分號。這稱為**自動分號插入**。例如,一個語法可以是變數,或者像`throw`、`return`、`break`這樣的關鍵字。
+在 JavaScript 中,我們不必硬性寫分號 (`;`),但是 JavaScript 引擎仍然在語法之後自動補上分號。這稱為**自動分號插入**。例如,一個語法可以是變數,或者像`throw`、`return`、`break`這樣的關鍵字。
-在這裡,我們在新的一行上寫了一個`return`語法和另一個值`a + b `。然而,由於它是一個新的一行,引擎並不知道它實際上是我們想要回傳的值。相反,它會在`return`後面自動補上分號。你可以這樣看:
+在這裡,我們在新的一行上寫了一個`return`語法和另一個值`a + b `。然而,由於它是一個新的一行,引擎並不知道它實際上是我們想要回傳的值。相反,它會在`return`後面自動補上分號。你可以這樣看:
```javascript
return;
a + b
```
-這意味著永遠不會到達`a + b`,因為函數在`return`關鍵字之後停止執行。如果沒有回傳值,就像這裡,函數回傳`undefined`。注意,在`if/else`語法之後沒有自動插入!
+這意味著永遠不會到達`a + b`,因為函數在`return`關鍵字之後停止執行。如果沒有回傳值,就像這裡,函數回傳`undefined`。注意,在`if/else`語法之後沒有自動插入!
-#### 答案: B
+#### 答案:B
我們可以將class設置為等於其他class/函數建構函數。在這種情況下,我們將`Person`設置為`AnotherPerson`。這個建構函數的名字是`Sarah`,所以新的`Person`實例`member`上的name屬性是`Sarah`。
@@ -3097,12 +3097,12 @@ console.log(Object.keys(info))
-#### 答案: D
+#### 答案:D
-`Symbol`類型是不可枚舉的。 `Object.keys`函數回傳物件上的所有可枚舉的鍵屬性。 `Symbol`類型是不可見的,並回傳一個空陣列。記錄整個物件時,所有屬性都是可見的,甚至是不可枚舉的屬性。
+`Symbol`類型是不可枚舉的。`Object.keys`函數回傳物件上的所有可枚舉的鍵屬性。`Symbol`類型是不可見的,並回傳一個空陣列。記錄整個物件時,所有屬性都是可見的,甚至是不可枚舉的屬性。
-這是`Symbol`的眾多特性之一:除了表示完全唯一的值(防止物件意外名稱衝突,例如當使用2個想要向同一物件添加屬性的庫時),您還可以`隱藏`這種方式物件的屬性(儘管不完全。你仍然可以使用`Object.getOwnPropertySymbols()`函數存取`Symbol`。
+這是`Symbol`的眾多特性之一:除了表示完全唯一的值(防止物件意外名稱衝突,例如當使用 2 個想要向同一物件添加屬性的庫時),您還可以`隱藏`這種方式物件的屬性(儘管不完全。你仍然可以使用`Object.getOwnPropertySymbols()`函數存取`Symbol`。
-#### 答案: A
+#### 答案:A
`getList`函數接收一個陣列作為其參數。在`getList`函數的括號之間,我們立即解構這個陣列。您可以這樣表達:
@@ -3138,7 +3138,7 @@ console.log(getUser(user))
使用剩餘的參數`... y`,我們將所有剩餘參數放在一個陣列中。在這種情況下,其餘的參數是`2`,`3`和`4`。 `y`的值是一個陣列,包含所有其餘參數。在這種情況下,`x`的值等於`1`,所以當我們輸出`[x,y]`時,會輸出`[1,[2,3,4]]`。
- `getUser`函數接收一個物件。對於箭頭函數,如果只回傳一個值,我們不必編寫大括號。但是,如果您想從一個箭頭函數回傳一個物件,您必須在小括號之間編寫它,否則不會回傳任何值!下面的函數將回傳一個物件:
+ `getUser`函數接收一個物件。對於箭頭函數,如果只回傳一個值,我們不必編寫大括號。但是,如果您想從一個箭頭函數回傳一個物件,您必須在小括號之間編寫它,否則不會回傳任何值!下面的函數將回傳一個物件:
```const getUser = user => ({ name: user.name, age: user.age })```
@@ -3164,14 +3164,14 @@ console.log(name())
-#### 答案: C
+#### 答案:C
變數`name`保存字串的值,該字串不是函數,因此無法呼叫。
-當值不是預期類型時,會拋出`TypeErrors`。 JavaScript期望`name`是一個函數,因為我們試圖呼叫它。但它是一個字串,因此拋出`TypeError`:`name is not a function`
+當值不是預期類型時,會拋出`TypeErrors`。JavaScript 期望`name`是一個函數,因為我們試圖呼叫它。但它是一個字串,因此拋出`TypeError`:`name is not a function`
-當你編寫了一些非有效的JavaScript時,會拋出語法錯誤,例如當你把`return`這個詞寫成`retrun`時。
-當JavaScript無法找到您嘗試存取的值的引用時,拋出`ReferenceErrors`。
+當你編寫了一些非有效的 JavaScript 時,會拋出語法錯誤,例如當你把`return`這個詞寫成`retrun`時。
+當 JavaScript 無法找到您嘗試存取的值的引用時,拋出`ReferenceErrors`。
-#### 答案: B
+#### 答案:B
`[]`是一個真值。使用`&&`運算子,如果左側值是真值,則回傳右側值。在這種情況下,左側值`[]`是一個真值,所以回傳`Im`。
-`""`是一個假值。如果左側值是假的,則不回傳任何內容。 `n't`不會被退回。
+`""`是一個假值。如果左側值是假的,則不回傳任何內容。`n't`不會被退回。
-#### 答案: C
+#### 答案:C
使用`||`運算子,我們可以得到第一個真值。如果所有值都是假值,則得到最後一個值。
-`(false || {} || null)`:空物件`{}`是一個真值。這是第一個(也是唯一的)真值,它將被得到。 `one`等於`{}`。
+`(false || {} || null)`:空物件`{}`是一個真值。這是第一個(也是唯一的)真值,它將被得到。`one`等於`{}`。
-`(null || false ||“”)`:所有值都是假值。這意味著得到傳遞的值`""`。 `two`等於`""`。
+`(null || false ||“”)`:所有值都是假值。這意味著得到傳遞的值`""`。`two`等於`""`。
-`([] || 0 ||“”)`:空陣列`[]`是一個真值。這是第一個得到的真值。 `three`等於`[]`。
+`([] || 0 ||“”)`:空陣列`[]`是一個真值。這是第一個得到的真值。`three`等於`[]`。
-#### 答案: D
+#### 答案:D
-有了promise,我們通常會說:當我想要呼叫某個函數,但是由於它可能需要一段時間,因此暫時將它放在一邊。只有當某個值被resolved/rejected,並且執行序為空時才使用這個值。
+有了 promise,我們通常會說:當我想要呼叫某個函數,但是由於它可能需要一段時間,因此暫時將它放在一邊。只有當某個值被 resolved/rejected,並且執行序為空時才使用這個值。
-我們可以在`async`函數中通過`.then`和`await`關鍵字獲得該值。儘管我們可以通過`.then`和`await`獲得promise的值,但是它們的運作方式不同。
+我們可以在`async`函數中通過`.then`和`await`關鍵字獲得該值。儘管我們可以通過`.then`和`await`獲得 promise 的值,但是它們的運作方式不同。
-在`firstFunction`中,當執行到`myPromise`函數時我們將其放在一邊,即promise進入微任務佇列,其他後面的程式(`console.log('second')`)照常執行,因此`second `被輸出,`firstFunction`函數到此執行完畢,執行序中任務佇列被清空,此時開始執行微任務佇列中的任務,`I have resolved`被輸出。
+在`firstFunction`中,當執行到`myPromise`函數時我們將其放在一邊,即 promise 進入微任務佇列,其他後面的程式(`console.log('second')`)照常執行,因此`second `被輸出,`firstFunction`函數到此執行完畢,執行序中任務佇列被清空,此時開始執行微任務佇列中的任務,`I have resolved`被輸出。
在`secondFunction`函數中,我們通過`await`關鍵字,暫停了後面程式的執行,直到異步函數的值被解析才開始後面程式的執行。這意味著,它會等著直到 `myPromise` 以值`I have resolved`被`resolve`之後,下一行`second`才開始執行。
@@ -3302,15 +3302,15 @@ for (let item of set) {
-#### 答案: C
+#### 答案:C
-“+”運算子不僅用於相加數字,還可以使用它來連接字串。每當JavaScript引擎發現一個或多個值不是數字時,就會將數字強制為字串。
+“+”運算子不僅用於相加數字,還可以使用它來連接字串。每當 JavaScript 引擎發現一個或多個值不是數字時,就會將數字強制為字串。
-第一個是數字1。 1 + 2得到數字3。
+第一個是數字 1。1 + 2 得到數字 3。
-但是,第二個是字串“Lydia”。 “Lydia”是一個字串,2是一個數字:2被強制轉換為字串。 “Lydia”和“2”被連接起來,產生字串“Lydia2”。
+但是,第二個是字串“Lydia”。 “Lydia”是一個字串,2 是一個數字:2 被強制轉換為字串。 “Lydia”和“2”被連接起來,產生字串“Lydia2”。
-`{name:“ Lydia”}`是一個物件。數字和物件都不是字串,因此將二者都字串化。每當我們對正規式物件進行字串化時,它就會變成`[Object object]`。與“2”串聯的“ [Object object]”成為“[Object object]2”。
+`{name:“Lydia”}`是一個物件。數字和物件都不是字串,因此將二者都字串化。每當我們對正規式物件進行字串化時,它就會變成`[Object object]`。與“2”串聯的“ [Object object]”成為“[Object object]2”。
-#### 答案: C
+#### 答案:C
-我們可以將我們想要的任何類型的值傳遞`Promise.resolve`,無論是否`promise`。該函數本身回傳帶有已解析值的`Promise` (`
-#### 答案: B
+#### 答案:B
物件通過參考位址傳遞。當我們檢查物件的嚴格相等性(===)時,我們正在比較它們的參考位址。
@@ -3372,7 +3372,7 @@ compareMembers(person)
這意味著兩個值都引用緩存中的同一位置,因此它們是相等的。
-執行“ else”語句中的代碼塊,並記錄`They are the same!` 。
+執行“else”語句中的代碼塊,並記錄`They are the same!`。
-#### 答案: D
+#### 答案:D
-在JavaScript中,我們有兩種存取物件屬性的方法:括號表示法或點表示法。在此範例中,我們使用點表示法(`colorConfig.colors`)代替括號表示法(`colorConfig [“ colors”]`)。
+在 JavaScript 中,我們有兩種存取物件屬性的方法:括號表示法或點表示法。在此範例中,我們使用點表示法(`colorConfig.colors`)代替括號表示法(`colorConfig [“colors”]`)。
-使用點表示法,JavaScript會嘗試使用該確切名稱在物件上查找屬性。在此範例中,JavaScript嘗試在colorconfig物件上找到名為colors的屬性。沒有名為“colors”的屬性,因此得到“undefined”。
+使用點表示法,JavaScript 會嘗試使用該確切名稱在物件上查找屬性。在此範例中,JavaScript 嘗試在 colorConfig 物件上找到名為 colors 的屬性。沒有名為“colors”的屬性,因此得到“undefined”。
然後,我們嘗試使用`[1]`存取第一個元素的值。我們無法對未定義的值執行此操作,因此會拋出`Cannot read property '1' of undefined`。
-JavaScript解釋(或取消裝箱)語句。當我們使用中括號表示法時,它會看到第一個左方括號`[`並一直進行下去,直到找到右方括號`]`。只有這樣,它才會評估該語句。如果我們使用了colorConfig [colors [1]],它將得到colorConfig物件上red屬性的值。
+JavaScript 解釋(或取消裝箱)語句。當我們使用中括號表示法時,它會看到第一個左方括號`[`並一直進行下去,直到找到右方括號`]`。只有這樣,它才會評估該語句。如果我們使用了 colorConfig [colors [1]],它將得到 colorConfig 物件上 red 屬性的值。
-#### 答案: A
+#### 答案:A
-在內部,表情符號是unicode。 heat表情符號的unicode是`“ U + 2764 U + FE0F”`。對於相同的表情符號,它們總是相同的,因此我們將兩個相等的字串相互比較,這將回傳true。
+在內部,表情符號是 unicode。heat 表情符號的 unicode 是`“U + 2764 U + FE0F”`。對於相同的表情符號,它們總是相同的,因此我們將兩個相等的字串相互比較,這將回傳 true。
-#### 答案: D
+#### 答案:D
-使用`splice`方法,我們透過刪除,取代或增加元素來修改原始陣列。在這種情況下,我們從索引1中刪除了2個元素(我們刪除了`'🥑'`和`'😍'`),同時增加了✨emoji表情。
+使用`splice`方法,我們透過刪除,取代或增加元素來修改原始陣列。在這種情況下,我們從索引 1 中刪除了 2 個元素(我們刪除了`'🥑'`和`'😍'`),同時增加了✨emoji 表情。
`map`,`filter`和`slice`回傳一個新陣列,`find`回傳一個元素,而`reduce`回傳一個計算過的值。
@@ -3488,11 +3488,11 @@ console.log(food)
-#### 答案: A
+#### 答案:A
-我們將`info`物件上的`favoriteFood`屬性的值設置為披薩表情符號“🍕”的字串。字串是原始內容類型。在JavaScript中,原始內容類型通過值起作用
+我們將`info`物件上的`favoriteFood`屬性的值設置為披薩表情符號“🍕”的字串。字串是原始內容類型。在 JavaScript 中,原始內容類型通過值起作用
-在這種情況下,我們將`info`物件上的`favoriteFood`屬性的值設置為等於`food`陣列中的第一個元素的值,字串為披薩表情符號(`'🍕'` )。字串是原始內容類型,並且通過值進行交換,我們更改`info`物件上`favoriteFood`屬性的值。 food陣列沒有改變,因為favoriteFood的值只是該陣列中第一個元素的值的複製,並且與該元素上的元素沒有相同的緩存引用食物`[0]`。當我們記錄食物時,它仍然是原始陣列`['🍕','🍫','🥑','🍔']`。
+在這種情況下,我們將`info`物件上的`favoriteFood`屬性的值設置為等於`food`陣列中的第一個元素的值,字串為披薩表情符號(`'🍕'`)。字串是原始內容類型,並且通過值進行交換,我們更改`info`物件上`favoriteFood`屬性的值。food 陣列沒有改變,因為 favoriteFood 的值只是該陣列中第一個元素的值的複製,並且與該元素上的元素沒有相同的緩存引用食物`[0]`。當我們記錄食物時,它仍然是原始陣列`['🍕','🍫','🥑','🍔']`。
-#### 答案: A
+#### 答案:A
-使用`JSON.parse()`函數,我們可以將JSON字串解析為JavaScript值。
+使用`JSON.parse()`函數,我們可以將 JSON 字串解析為 JavaScript 值。
```javascript
-// 將數字字串化為有效的JSON,然後將JSON字串解析為JavaScript值:
+// 將數字字串化為有效的 JSON,然後將 JSON 字串解析為 JavaScript 值:
const jsonNumber = JSON.stringify(4) // '4'
JSON.parse(jsonNumber) // 4
-// 將陣列值字串化為有效的JSON,然後將JSON字串解析為JavaScript值:
+// 將陣列值字串化為有效的 JSON,然後將 JSON 字串解析為 JavaScript 值:
const jsonArray = JSON.stringify([1, 2, 3]) // '[1, 2, 3]'
JSON.parse(jsonArray) // [1, 2, 3]
-// 將物件字串化為有效的JSON,然後將JSON字串解析為JavaScript值:
+// 將物件字串化為有效的 JSON,然後將 JSON 字串解析為 JavaScript 值:
const jsonArray = JSON.stringify({ name: "Lydia" }) // '{"name":"Lydia"}'
JSON.parse(jsonArray) // { name: 'Lydia' }
```
@@ -3554,13 +3554,13 @@ getName()
-#### 答案: D
+#### 答案:D
-每個函數都有其自己的執行上下文。 `getName`函數首先在其自身的上下文(範圍)內查找,以查看其是否包含我們嘗試存取的變數`name`。上述情況,`getName`函數包含其自己的`name`變數:我們用`let`關鍵字和`Sarah`的值定義變數`name`。
+每個函數都有其自己的執行上下文。`getName`函數首先在其自身的上下文(範圍)內查找,以查看其是否包含我們嘗試存取的變數`name`。上述情況,`getName`函數包含其自己的`name`變數:我們用`let`關鍵字和`Sarah`的值定義變數`name`。
-帶有`let`關鍵字(和`const`)的變數被提升,但是與`var`不同,它不會被***初始化***。在我們定義(初始化)它們之前,無法存取它們。這稱為“暫時性死區”。當我們嘗試在定義變數之前存取變數時,JavaScript會拋出`ReferenceError: Cannot access 'name' before initialization`。
+帶有`let`關鍵字(和`const`)的變數被提升,但是與`var`不同,它不會被***初始化***。在我們定義(初始化)它們之前,無法存取它們。這稱為“暫時性死區”。當我們嘗試在定義變數之前存取變數時,JavaScript 會拋出`ReferenceError: Cannot access 'name' before initialization`。
-如果我們不在`getName`函數中定義`name`變數,則javascript引擎會查看原型鏈。會找到其外部作用域有一個名為`name`的變數,其值為`Lydia`。在這種情況下,它將輸出`Lydia`:
+如果我們不在`getName`函數中定義`name`變數,則 javascript 引擎會查看原型鏈。會找到其外部作用域有一個名為`name`的變數,其值為`Lydia`。在這種情況下,它將輸出`Lydia`:
```javascript
let name = 'Lydia'
@@ -3602,18 +3602,18 @@ console.log(two.next().value)
-#### 答案: C
+#### 答案:C
-透過`yield` 關鍵字, 我們在`Generator` 函數裡執行`yield`語法. 透過`yield*` 關鍵字, 我們可以在一個`Generator` 函數裡面執行(`yield`語法)另一個`Generator ` 函數, 或可遍歷的物件(如陣列).
+透過`yield` 關鍵字,我們在`Generator` 函數裡執行`yield`語法。透過`yield*` 關鍵字,我們可以在一個`Generator` 函數裡面執行(`yield`語法)另一個`Generator ` 函數,或可遍歷的物件 (如陣列).
-在函數 `generatorOne` 中, 我們透過 `yield` 關鍵字 yield 了一個完整的陣列 `['a', 'b', 'c']`。函數`one`透過`next`方法回傳的物件的`value` 屬性的值 (`one.next().value`) 等價於陣列 `['a', 'b', 'c']`.
+在函數 `generatorOne` 中,我們透過 `yield` 關鍵字 yield 了一個完整的陣列 `['a', 'b', 'c']`。函數`one`透過`next`方法回傳的物件的`value` 屬性的值 (`one.next().value`) 等價於陣列 `['a', 'b', 'c']`.
```javascript
console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined
```
-在函數 `generatorTwo` 中, 我們使用 `yield*` 關鍵字。就相當於函數`two`第一個`yield`的值, 等價於在迭代器中第一個 `yield` 的值。陣列`['a', 'b', 'c']`就是這個迭代器. 第一個`yield` 的值就是`a`, 所以我們第一次呼叫`two.next().value`時, 就回傳`a`。
+在函數 `generatorTwo` 中,我們使用 `yield*` 關鍵字。就相當於函數`two`第一個`yield`的值,等價於在迭代器中第一個 `yield` 的值。陣列`['a', 'b', 'c']`就是這個迭代器。第一個`yield` 的值就是`a`, 所以我們第一次呼叫`two.next().value`時,就回傳`a`。
```javascript
console.log(two.next().value) // 'a'
@@ -3641,9 +3641,9 @@ console.log(`${(x => x)('I love')} to program`)
-#### 答案: A
+#### 答案:A
-帶有模板字面量的表達式優先被執行。相當於字串會包含表達式,這個立即執行函數`(x => x)('I love')` 回傳的值. 我們向箭頭函數`x => x` 傳遞`'I love'` 作為參數。 `x` 等價於回傳的 `'I love'`。這就是結果 `I love to program`。
+帶有模板字面量的表達式優先被執行。相當於字串會包含表達式,這個立即執行函數`(x => x)('I love')` 回傳的值。我們向箭頭函數`x => x` 傳遞`'I love'` 作為參數。 `x` 等價於回傳的 `'I love'`。這就是結果 `I love to program`。
-#### 答案: C
+#### 答案:C
-一般情況下當我們將物件賦值為 `null`, 那些物件會被進行 _垃圾回收(garbage collected)_ 因為已經沒有對這些物件的引用了。然而,`setInterval`的參數是一個箭頭函數(所以上下文綁定到物件 `config` 了),函數仍然保留著對 `config`的引用。只要存在引用,物件就不會被垃圾回收。因為沒有被垃圾回收,`setInterval` 的每1000ms (1s)會被呼叫一次。
+一般情況下當我們將物件賦值為 `null`, 那些物件會被進行 _垃圾回收(garbage collected)_ 因為已經沒有對這些物件的引用了。然而,`setInterval`的參數是一個箭頭函數(所以上下文綁定到物件 `config` 了),函數仍然保留著對 `config`的引用。只要存在引用,物件就不會被垃圾回收。因為沒有被垃圾回收,`setInterval` 的每 1000ms (1s) 會被呼叫一次。
-#### 答案: B
+#### 答案:B
-當透過 `set` 函數增加一個鍵值對,一個傳遞給 `set`函數的參數將會是鍵名,第二個參數將會是值。在這個case裡,鍵名為 _函數_ `() => 'greeting'`,值為`'Hello world'`。 `myMap` 現在就是 `{ () => 'greeting' => 'Hello world!' }`。
+當透過 `set` 函數增加一個鍵值對,一個傳遞給 `set`函數的參數將會是鍵名,第二個參數將會是值。在這個 case 裡,鍵名為 _函數_ `() => 'greeting'`,值為`'Hello world'`。 `myMap` 現在就是 `{ () => 'greeting' => 'Hello world!' }`。
1 是錯的,因為鍵名不是 `'greeting'` 而是 `() => 'greeting'`。
3 是錯的,因為我們給`get` 函數傳遞了一個新的函數。物件受 _引用_ 影響。函數也是物件,因此兩個函數嚴格上並不等價,儘管他們相同:他們有兩個不同的緩存引用地址。
@@ -3740,13 +3740,13 @@ console.log(person)
-#### 答案: C
+#### 答案:C
函數 `changeAge` 和函數 `changeAgeAndName` 有著不同的參數,定義一個 _新_ 生成的物件 `{ ...person }`。這個物件有著所有 `person` 物件 中 k/v 值的副本。
-首項, 我們呼叫 `changeAge` 函數並傳遞 `person` 物件作為它的參數。這個函數對 `age` 屬性進行加一操作。 `person` 現在是 `{ name: "Lydia", age: 22 }`。
+首項,我們呼叫 `changeAge` 函數並傳遞 `person` 物件作為它的參數。這個函數對 `age` 屬性進行加一操作。`person` 現在是 `{ name: "Lydia", age: 22 }`。
-然後,我們呼叫函數 `changeAgeAndName` ,然而我們沒有傳遞參數。取而代之,`x` 的值等價 _new_ 生成的物件: `{ ...person }`。因為它是一個新生成的物件,它並不會對物件 `person` 造成任何副作用。 `person` 仍然等價於 `{ name: "Lydia", age: 22 }`。
+然後,我們呼叫函數 `changeAgeAndName`,然而我們沒有傳遞參數。取而代之,`x` 的值等價 _new_ 生成的物件:`{ ...person }`。因為它是一個新生成的物件,它並不會對物件 `person` 造成任何副作用。`person` 仍然等價於 `{ name: "Lydia", age: 22 }`。
-#### 答案: C
+#### 答案:C
-通過展開語法 `...`,我們可以 _展開_ 單個可迭代的元素。函數 `sumValues` function 接收三個參數: `x`, `y` 和 `z`。 `...[1, 2, 3]` 的執行結果為 `1, 2, 3`,將會傳遞給函數 `sumValues`。
+通過展開語法 `...`,我們可以 _展開_ 單個可迭代的元素。函數 `sumValues` function 接收三個參數:`x`, `y` 和 `z`。`...[1, 2, 3]` 的執行結果為 `1, 2, 3`,將會傳遞給函數 `sumValues`。
-#### 答案: B
+#### 答案:B
-透過 `+=` 運算子,我們對變數 `num` 進行加 `1` 操作。 `num` 有初始值 `1`,因此 `1 + 1` 的執行結果為 `2`。陣列 `list` 的第二項為 🥰,`console.log(list[2])` 輸出 🥰.
+透過 `+=` 運算子,我們對變數 `num` 進行加 `1` 操作。`num` 有初始值 `1`,因此 `1 + 1` 的執行結果為 `2`。陣列 `list` 的第二項為 🥰,`console.log(list[2])` 輸出 🥰.
-#### 答案: B
+#### 答案:B
-通過ES10 或TS3.7+[可選鏈運算子`?.`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/%E5%8F%AF% E9%80%89%E9%93%BE),我們不再需要顯式檢測更深層的嵌套值是否有效。如果我們嘗試存取 `undefined` 或 `null` 的值 (_nullish_),表達將會短路並回傳 `undefined`.
+通過 ES10 或 TS3.7+[可選鏈運算子`?.`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/%E5%8F%AF% E9%80%89%E9%93%BE),我們不再需要顯式檢測更深層的嵌套值是否有效。如果我們嘗試存取 `undefined` 或 `null` 的值 (_nullish_),表達將會短路並回傳 `undefined`.
-`person.pet?.name`: `person` 有一個名為 `pet` 的屬性: `person.pet` 不是 nullish。它有個名為 `name` 的屬性,並回傳字串 `Mara`。
-`person.pet?.family?.name`: `person` 有一個名為`pet` 的屬性: `person.pet` 不是nullish. `pet` _並沒有_ 一個名為`family` 的屬性, ` person.pet.family` 是nullish。表達式回傳 `undefined`。
-`person.getFullName?.()`: `person` 有一個名為 `getFullName` 的屬性: `person.getFullName()` 不是 nullish 並可以被呼叫,回傳字串 `Lydia Hallie`。
+`person.pet?.name`:`person` 有一個名為 `pet` 的屬性:`person.pet` 不是 nullish。它有個名為 `name` 的屬性,並回傳字串 `Mara`。
+`person.pet?.family?.name`:`person` 有一個名為`pet` 的屬性:`person.pet` 不是 nullish. `pet` _並沒有_ 一個名為`family` 的屬性,` person.pet.family` 是 nullish。表達式回傳 `undefined`。
+`person.getFullName?.()`:`person` 有一個名為 `getFullName` 的屬性:`person.getFullName()` 不是 nullish 並可以被呼叫,回傳字串 `Lydia Hallie`。
`member.getLastName?.()`: `member` is not defined: `member.getLastName()` is nullish. The expression returns `undefined`.
-#### 答案: B
+#### 答案:B
-我們傳遞了一個狀態 `groceries.indexOf("banana")` 給if語法。 `groceries.indexOf("banana")` 回傳 `0`, 一個 falsy 的值。因為if語法的狀態為 falsy,`else` 塊區內的代碼執行,並且 `We don't have to buy bananas!` 被輸出.
+我們傳遞了一個狀態 `groceries.indexOf("banana")` 給 if 語法。`groceries.indexOf("banana")` 回傳 `0`,一個 falsy 的值。因為 if 語法的狀態為 falsy,`else` 塊區內的代碼執行,並且 `We don't have to buy bananas!` 被輸出。
-#### 答案: D
+#### 答案:D
-函數 `language` 是一個 `setter`。 Setters 並不保存一個實際值,它們的使命在於 _修改_ 屬性。當呼叫函數 `setter`, 回傳 `undefined`。
+函數 `language` 是一個 `setter`。Setters 並不保存一個實際值,它們的使命在於 _修改_ 屬性。當呼叫函數 `setter`,回傳 `undefined`。
-#### 答案: C
+#### 答案:C
-`typeof name` 回傳 `"string"`。字串 `"string"` 是一個 truthy 的值,因此 `!typeof name` 回傳一個布林值 `false`。 `false === "object"` 和 `false === "string"` 都回傳 `false`。
+`typeof name` 回傳 `"string"`。字串 `"string"` 是一個 truthy 的值,因此 `!typeof name` 回傳一個布林值 `false`。`false === "object"` 和 `false === "string"` 都回傳 `false`。
(如果我們想檢測一個值的類型,我們應該用 `!==` 而不是 `!typeof`)
@@ -3947,7 +3947,7 @@ add(4)(5)(6);
-#### 答案: A
+#### 答案:A
函數 `add` 是一個回傳 回傳箭頭函數的箭頭函數 的箭頭函數(still with me?)。第一個函數接收一個值為 `4` 的參數 `x`。我們呼叫第二個函數,它接收一個值為 `5` 的參數 `y`。然後我們呼叫第三個函數,它接收一個值為 `6` 的參數 `z`。當我們嘗試在最後一個箭頭函數中獲取 `x`, `y` 和 `z` 的值,JS 引擎根據作用域鏈去找 `x` 和 `y` 的值。得到 `4` `5` `6`.
@@ -3980,9 +3980,9 @@ async function* range(start, end) {
-#### 答案: C
+#### 答案:C
-我們給 函數range 傳遞: `Promise{1}`, `Promise{2}`, `Promise{3}`,Generator 函數 `range` 回傳一個全是 async object promise 陣列。我們將 async object 賦值給變數 `gen`,之後我們使用`for await ... of` 進行循環遍歷。我們將回傳的 Promise 實例賦值給 `item`: 第一個回傳 `Promise{1}`, 第二個回傳 `Promise{2}`,之後是 `Promise{3}`。因為我們正 _awaiting_ `item` 的值,resolved 狀態的 promsie,promise陣列的resolved _值_ 以此為: `1`,`2`,`3`.
+我們給 函數 range 傳遞:`Promise{1}`, `Promise{2}`, `Promise{3}`,Generator 函數 `range` 回傳一個全是 async object promise 陣列。我們將 async object 賦值給變數 `gen`,之後我們使用`for await ... of` 進行循環遍歷。我們將回傳的 Promise 實例賦值給 `item`:第一個回傳 `Promise{1}`,第二個回傳 `Promise{2}`,之後是 `Promise{3}`。因為我們正 _awaiting_ `item` 的值,resolved 狀態的 promise,promise 陣列的 resolved _值_ 以此為:`1`,`2`,`3`.
-#### 答案: D
+#### 答案:D
-`myFunc` 預期接收一個包含 `x`, `y` 和 `z` 屬性的物件作為它的參數。因為我們僅僅傳遞三個單獨的數字值(1, 2, 3) 而不是一個含有`x`, `y` 和`z` 屬性的物件({x: 1, y: 2, z: 3}) , `x`, `y` 和`z` 有著各自的預設值`undefined`.
+`myFunc` 預期接收一個包含 `x`, `y` 和 `z` 屬性的物件作為它的參數。因為我們僅僅傳遞三個單獨的數字值 (1, 2, 3) 而不是一個含有`x`, `y` 和`z` 屬性的物件 ({x: 1, y: 2, z: 3}) ,`x`, `y` 和`z` 有著各自的預設值`undefined`.
-#### 答案: B
+#### 答案:B
-通過函數 `Intl.NumberFormat`,我們可以格式化任意區域的數字值。我們對數字值 `130` 進行 `mile-per-hour` 作為 `unit` 的 `en-US` 區域 格式化,結果為 `130 mph`。對數字值 `300` 進行 `USD` 作為 `currentcy` 的 `en-US` 區域格式化,結果為 `$300.00`.
+通過函數 `Intl.NumberFormat`,我們可以格式化任意區域的數字值。我們對數字值 `130` 進行 `mile-per-hour` 作為 `unit` 的 `en-US` 區域 格式化,結果為 `130 mph`。對數字值 `300` 進行 `USD` 作為 `currency` 的 `en-US` 區域格式化,結果為 `$300.00`.
-#### 答案: B
+#### 答案:B
通過解構物件們,我們可以從右手邊的物件中拆出值,並且將拆出的值分配給左手邊物件同名的屬性。在這種情況下,我們將值 "💀" 分配給 `spookyItems[3]`。相當於我們正在篡改陣列 `spookyItems`,我們給它添加了值 "💀"。當輸出 `spookyItems` 時,結果為 `["👻", "🎃", "🕸", "💀"]`。
@@ -4098,11 +4098,11 @@ console.log(isNaN(age));
-#### 答案: C
+#### 答案:C
-通過函數 `Number.isNaN`,你可以檢測你傳遞的值是否為 _數字值_ 並且是否等於 `NaN`。 `name` 不是一個數字值,因此 `Number.isNaN(name)` 回傳 `false`。 `age` 是一個數字值,但它不等於 `NaN`,因此 `Number.isNaN(age)` 回傳 `false`.
+通過函數 `Number.isNaN`,你可以檢測你傳遞的值是否為 _數字值_ 並且是否等於 `NaN`。`name` 不是一個數字值,因此 `Number.isNaN(name)` 回傳 `false`。`age` 是一個數字值,但它不等於 `NaN`,因此 `Number.isNaN(age)` 回傳 `false`.
-通過函數 `isNaN`, 你可以檢測你傳遞的值是否一個 number。 `name` 不是一個 `number`,因此 `isNaN(name)` 回傳 `true`. `age` 是一個 `number` 因此 `isNaN(age)` 回傳 `false`.
+通過函數 `isNaN`,你可以檢測你傳遞的值是否一個 number。`name` 不是一個 `number`,因此 `isNaN(name)` 回傳 `true`. `age` 是一個 `number` 因此 `isNaN(age)` 回傳 `false`.
-#### 答案: D
+#### 答案:D
-通過 `const` 關鍵字定義的變數在被初始化之前不可被引用:這被稱之為 _暫時性死區_。在函數 `getInfo` 中, 變數 `randomValue` 定義在`getInfo` 的作用域的此法環境中。在想要對`typeof randomValue` 進行log之前,變數`randomValue` 仍未被初始化: 錯誤`ReferenceError` 被拋出! JS引擎並不會根據作用域鍊網上尋找該變數,因為我們已經在`getInfo`函數中定義了`randomValue` 變數。
+通過 `const` 關鍵字定義的變數在被初始化之前不可被引用:這被稱之為 _暫時性死區_。在函數 `getInfo` 中,變數 `randomValue` 定義在`getInfo` 的作用域的此法環境中。在想要對`typeof randomValue` 進行 log 之前,變數`randomValue` 仍未被初始化:錯誤`ReferenceError` 被拋出!JS 引擎並不會根據作用域鍊網上尋找該變數,因為我們已經在`getInfo`函數中定義了`randomValue` 變數。
-#### 答案: C
+#### 答案:C
-在 `try` 塊區,我們輸出 `myPromise` 變數的 awaited 值: `"Woah some cool data"`。因為`try` 塊區沒有錯誤拋出,`catch` 塊區的代碼並不執行。 `finally` 塊區的代碼 _總是_ 執行,`"Oh finally!"` 被輸出。
+在 `try` 塊區,我們輸出 `myPromise` 變數的 awaited 值:`"Woah some cool data"`。因為`try` 塊區沒有錯誤拋出,`catch` 塊區的代碼並不執行。`finally` 塊區的代碼 _總是_ 執行,`"Oh finally!"` 被輸出。
-#### 答案: B
+#### 答案:B
-通過函數 `flat`, 我們可以建立一個新的, 已被扁平化的陣列。被扁平化的深度取決於我們傳遞的值。在這個case裡,我們傳遞了值 `1` (並不必要,這是預設值),相當於只有第一層的陣列才會被連接。即這個 case 裡的 `['🥑']` and `['✨', '✨', ['🍕', '🍕']]`。連接這兩個陣列得到結果 `['🥑', '✨', '✨', ['🍕', '🍕']]`.
+通過函數 `flat`,我們可以建立一個新的,已被扁平化的陣列。被扁平化的深度取決於我們傳遞的值。在這個 case 裡,我們傳遞了值 `1` (並不必要,這是預設值),相當於只有第一層的陣列才會被連接。即這個 case 裡的 `['🥑']` and `['✨', '✨', ['🍕', '🍕']]`。連接這兩個陣列得到結果 `['🥑', '✨', '✨', ['🍕', '🍕']]`.
-#### 答案: D
+#### 答案:D
-`counterOne` 是類 `Counter` 的一個實例。類 Counter 包含一個`count` 屬性在它的建構函數里, 和一個 `increment` 函數。首先,我們通過 `counterOne.increment()` 呼叫函數 `increment` 兩次。現在, `counterOne.count` 為 `2`.
+`counterOne` 是類 `Counter` 的一個實例。類 Counter 包含一個`count` 屬性在它的建構函數里,和一個 `increment` 函數。首先,我們通過 `counterOne.increment()` 呼叫函數 `increment` 兩次。現在,`counterOne.count` 為 `2`.
-#### 答案: D
+#### 答案:D
-首先,我們呼叫 `funcOne`。在函數 `funcOne` 的第一行,我們呼叫`myPromise` promise _異步操作_。當JS引擎在忙於執行 promise,它繼續執行函數 `funcOne`。下一行 _異步操作_ `setTimeout`,其回呼函數被 Web API 呼叫。 (詳情請參考我關於event loop的文章.)
+首先,我們呼叫 `funcOne`。在函數 `funcOne` 的第一行,我們呼叫`myPromise` promise _異步操作_。當 JS 引擎在忙於執行 promise,它繼續執行函數 `funcOne`。下一行 _異步操作_ `setTimeout`,其回呼函數被 Web API 呼叫。 (詳情請參考我關於 event loop 的文章.)
-promise 和 timeout 都是異步操作,函數繼續執行當JS引擎忙於執行promise 和 處理 `setTimeout` 的呼叫。相當於 `Last line!` 首先被輸出, 因為它不是異步操作。執行完 `funcOne` 的最後一行,promise 狀態轉變為 resolved,`Promise!` 被輸出。然而,因為我們呼叫了 `funcTwo()`, 呼叫堆疊不為空,`setTimeout` 的回呼仍不能入堆疊。
+promise 和 timeout 都是異步操作,函數繼續執行當 JS 引擎忙於執行 promise 和 處理 `setTimeout` 的呼叫。相當於 `Last line!` 首先被輸出,因為它不是異步操作。執行完 `funcOne` 的最後一行,promise 狀態轉變為 resolved,`Promise!` 被輸出。然而,因為我們呼叫了 `funcTwo()`, 呼叫堆疊不為空,`setTimeout` 的回呼仍不能入堆疊。
-我們現在處於 `funcTwo`,先 _awaiting_ myPromise。通過 `await` 關鍵字, 我們暫停了函數的執行直到 promise 狀態變為 resolved (或 rejected)。然後,我們輸出 `res` 的 awaited 值(因為 promise 本身回傳一個 promise)。接著輸出 `Promise!`。
+我們現在處於 `funcTwo`,先 _awaiting_ myPromise。通過 `await` 關鍵字,我們暫停了函數的執行直到 promise 狀態變為 resolved (或 rejected)。然後,我們輸出 `res` 的 awaited 值(因為 promise 本身回傳一個 promise)。接著輸出 `Promise!`。
下一行就是 _異步操作_ `setTimeout`,其回呼函數被 Web API 呼叫。
@@ -4312,7 +4312,7 @@ import * as sum from "./sum";
-#### 答案: C
+#### 答案:C
使用符號 `*`,我們引入文件中的所有值,包括預設和具名。如果我們有以下文件:
@@ -4372,13 +4372,13 @@ person.name;
-#### 答案: C
+#### 答案:C
使用 Proxy 物件,我們可以給一個物件添加自定義行為。在這個 case,我們傳遞一個包含以下屬性的物件 `handler` : `set` and `get`。每當我門 _設置_ 屬性值時 `set` 被呼叫,每當我們 _獲取_ 時 `get` 被呼叫。
-第一個參數是一個空物件 `{}`,作為 `person` 的值。對於這個物件,自定義行為被定義在物件 `handler`。如果我們向物件 `person` 添加屬性,`set` 將被呼叫。如果我們獲取 `person` 的屬性, `get` 將被呼叫。
+第一個參數是一個空物件 `{}`,作為 `person` 的值。對於這個物件,自定義行為被定義在物件 `handler`。如果我們向物件 `person` 添加屬性,`set` 將被呼叫。如果我們獲取 `person` 的屬性,`get` 將被呼叫。
-首先,我們向 proxy 物件(`person.name = "Lydia"`)添加一個屬性 `name`。 `set` 被呼叫並輸出 `"Added a new property!"`。
+首先,我們向 proxy 物件 (`person.name = "Lydia"`) 添加一個屬性 `name`。`set` 被呼叫並輸出 `"Added a new property!"`。
然後,我們獲取 proxy 物件的一個屬性,物件 handler 的屬性 `get` 被呼叫。輸出 `"Accessed a property!"`。
@@ -4403,7 +4403,7 @@ Object.seal(person);
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
@@ -899,7 +899,7 @@ baz()
-`foo` 从栈中弹出,`baz` 被调用. 打印 `"Third"`。
+`foo` 从栈中弹出,`baz` 被调用。打印 `"Third"`。
@@ -918,7 +918,7 @@ WebAPI 不能随时向栈内添加内容。相反,它将回调函数推到名
---
-###### 31. 当点击按钮时,event.target是什么?
+###### 31. 当点击按钮时,event.target 是什么?
```html
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
-然后我们又声明了一个变量`members`. 将首个元素赋值为变量`person`。 当设置两个对象彼此相等时,它们会通过 _引用_ 进行交互。但是当你将引用从一个变量分配至另一个变量时,其实只是执行了一个 _复制_ 操作。(注意一点,他们的引用 _并不相同_!)
+然后我们又声明了一个变量`members`. 将首个元素赋值为变量`person`。当设置两个对象彼此相等时,它们会通过 _引用_ 进行交互。但是当你将引用从一个变量分配至另一个变量时,其实只是执行了一个 _复制_ 操作。(注意一点,他们的引用 _并不相同_!)
@@ -1389,14 +1389,14 @@ console.log(members);
-我们没有修改数组第一个元素的值,而只是修改了变量`person`的值,因为元素(复制而来)的引用与`person`不同。`members`的第一个元素仍然保持着对原始对象的引用。当我们输出`members`数组时,第一个元素会将引用的对象打印出来。
+我们没有修改数组第一个元素的值,而只是修改了变量`person`的值,因为元素(复制而来)的引用与`person`不同。`members`的第一个元素仍然保持着对原始对象的引用。当我们输出`members`数组时,第一个元素会将引用的对象打印出来。
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
-`a`的值现在是`1`,`b`的值现在是`2`.而在题目中,我们是这么做的:
+`a`的值现在是`1`,`b`的值现在是`2`.而在题目中,我们是这么做的:
```javascript
[y] = [1, 2, 3, 4, 5];
@@ -1817,14 +1817,14 @@ console.log(y);
-也就是说,`y`等于数组的第一个值就是数字`1`.我们输出`y`, 返回`1`.
+也就是说,`y`等于数组的第一个值就是数字`1`.我们输出`y`,返回`1`.
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
然后,我们创建一个新的变量 `counterTwo` 并将 `counterOne` 的引用地址赋值给它。因为对象受引用地址的影响,我们刚刚创建了一个新的对象,其引用地址和 `counterOne` 的等价。因此它们指向同一块内存地址,任何对其的副作用都会影响 `counterTwo`。现在 `counterTwo.count` 为 `2`。
-我们调用 `counterTwo.increment()` 将 `count` 的值设为 `3`。然后,我们打印 `counterOne` 里的count,结果为 `3`。
+我们调用 `counterTwo.increment()` 将 `count` 的值设为 `3`。然后,我们打印 `counterOne` 里的 count,结果为 `3`。
@@ -4291,13 +4291,13 @@ funcTwo();
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
-a 的值現在為 `1` 且b 的值現在為`2`。我們針對此問題所做的動作為:
+a 的值現在為 `1` 且 b 的值現在為`2`。我們針對此問題所做的動作為:
```javascript
[y] = [1, 2, 3, 4, 5];
@@ -1869,9 +1869,9 @@ console.log(admin);
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
答案
然後,我們建立一個新的變數 `counterTwo` 並將 `counterOne` 的引用地址賦值給它。因為物件受引用地址的影響,我們剛剛建立了一個新的物件,其引用地址和 `counterOne` 的等價。因此它們指向同一塊緩存地址,任何對其的副作用都會影響 `counterTwo`。現在 `counterTwo.count` 為 `2`。
-我們呼叫 `counterTwo.increment()` 將 `count` 的值設為 `3`。然後,我們輸出 `counterOne` 裡的count,結果為 `3`。
+我們呼叫 `counterTwo.increment()` 將 `count` 的值設為 `3`。然後,我們輸出 `counterOne` 裡的 count,結果為 `3`。
@@ -4275,13 +4275,13 @@ funcTwo();
答案
答案
答案