Я публікую щодня завдання з JavaScript в моєму Instagram, які також додаю тут!
Від базового до просунутого: перевірте, наскільки добре ви знаєте JavaScript, трохи оновіть свої знання або підготуйтеся до інтерв'ю! 💪 🚀 Щотижня я доповнюю цей репозиторій новими питаннями.
Відповіді знаходяться в згорнутій секції нижче питань. Просто натисни на відповідь, щоб розгорнути. Успіхів! ❤️
- 🇸🇦 العربية
- 🇪🇬 اللغة العامية
- 🇧🇦 Bosanski
- 🇩🇪 Deutsch
- 🇬🇧 English
- 🇪🇸 Español
- 🇫🇷 Français
- 🇮🇩 Indonesia
- 🇮🇹 Italiano
- 🇯🇵 日本語
- 🇰🇷 한국어
- 🇳🇱 Nederlands
- 🇵🇱 Polski
- 🇧🇷 Português Brasil
- 🇷🇺 Русский
- 🇹🇭 ไทย
- 🇹🇷 Türkçe
- 🇻🇳 Tiếng Việt
- 🇨🇳 简体中文
- 🇹🇼 繁體中文
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
- A:
Lydia
таundefined
- B:
Lydia
таReferenceError
- C:
ReferenceError
та21
- D:
undefined
таReferenceError
Відповідь
Всередині функції ми спершу визначаємо змінну name
за допомогою ключового слова var
. Це означає, що змінна буде знайдена (область пам'яті під змінну буде виділена під час створення) зі значенням undefined
за замовчуванням, до тих пір поки виконання коду не дійде до рядка, де визначається змінна. Ми ще не визначили значення name
, коли намагаємося вивести її в консоль, тому в консолі буде undefined
.
Змінні, визначені за допомогою let
(і const
), також знаходяться, але на відміну від var
, не створюються. Доступ до них неможливий до тих пір, поки не виконається рядок їх визначення (ініціалізації). Це називається "тимчасова мертва зона". Коли ми намагаємося звернутися до змінних до того моменту як вони визначені, JavaScript видає ReferenceError
.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
- A:
0 1 2
та0 1 2
- B:
0 1 2
та3 3 3
- C:
3 3 3
та0 1 2
Відповідь
Через черги подій в JavaScript, функція setTimeout
викликається після того як цикл буде завершено. Так як змінна i
в першому циклі була визначена за допомогою var
, вона буде глобальною. У циклі ми кожен раз збільшуємо значення i
на 1
, використовуючи унарний оператор ++.
До моменту виконання функції setTimeout
значення i
дорівнюватиме 3
, як показано в першому прикладі.
У другому циклі змінна i
визначена за допомогою let
. Такі змінні (а також const
) мають блокову область видимості (блок це що завгодно між {}
). З кожною ітерацією i
матиме нове значення, і кожне значення буде замкнуто у своїй області видимості всередині циклу.
const shape = {
radius: 10,
diameter() {
return this.radius * 2;
},
perimeter: () => 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter();
- A:
20
та62.83185307179586
- B:
20
таNaN
- C:
20
та63
- D:
NaN
та63
Відповідь
Зауваж, що diameter
це звичайна функція, в той час як perimeter
це стрілкова функція.
У стрілкових функцій значення this
вказує на навколишню область видимості, на відміну від звичайних функцій! Це означає, що при виклику perimeter
значення this
у цій функції вказує не на об'єкт shape
, а на зовнішню область видимості (наприклад, window).
У цього об'єкта немає ключа radius
, тому повертається undefined
.
+true;
!"Lydia";
- A:
1
таfalse
- B:
false
таNaN
- C:
false
таfalse
Відповідь
Унарний плюс призводить операнд до числа. true
це 1
, а false
це 0
.
Строка 'Lydia'
це "справжнє" значення. Ми запитуємо "справжнє значення є помилковим"? Відповідь: false
.
const bird = {
size: "small"
};
const mouse = {
name: "Mickey",
small: true
};
- A:
mouse.bird.size
не є коректно - B:
mouse[bird.size]
не є коректно - C:
mouse[bird["size"]]
не є коректно - D: Все варіант коректні
Відповідь
В JavaScript все ключі об'єкта є рядками (крім Symbol
). І хоча ми не набираємо їх як рядки, вони завжди перетворюються до рядків під капотом.
JavaScript інтерпретує (або розпаковує) оператори. При використанні квадратних дужок JS зауважує [
і продовжує поки не зустріне ]
. Тільки після цього він вирахує то, що знаходиться всередині дужок.
mouse[bird.size]
: Спершу визначається bird.size
, що дорівнює "small"
. mouse["small"]
повертає true
.
Але із записом через крапку так не відбувається. У mouse
немає ключа bird
. Таким чином, mouse.bird
дорівнює undefined
. Потім ми запитуємо ключ size
, використовуючи крапкову нотацію: mouse.bird.size
. Так як mouse.bird
це undefined
, ми запитуємо undefined.size
. Це не є дійсним, тому ми отримуємо помилку типу: Can not read property "size" of undefined
.
let c = { greeting: "Hey!" };
let d;
d = c;
c.greeting = "Hello";
console.log(d.greeting);
- A:
Hello
- B:
Hey
- C:
undefined
- D:
ReferenceError
- E:
TypeError
Відповідь
В JavaScript всі об'єкти є посилальними типами даних.
Спершу змінна c
вказує на об'єкт. Потім ми вказуємо змінної d
посилатися на той самий об'єкт, що і c
.
Коли ти змінюєш один об'єкт, то змінюються значення всіх посилань, що вказують на цей об'єкт.
let a = 3;
let b = new Number(3);
let c = 3;
console.log(a == b);
console.log(a === b);
console.log(b === c);
- A:
true
false
true
- B:
false
false
true
- C:
true
false
false
- D:
false
true
true
Відповідь
new Number()
це вбудований конструктор функції. І хоча він виглядає як число, це не справжнє число: у нього є ряд додаткових фіч і це об'єкт.
Оператор ==
призводить типи даних до якогось одного і перевіряє рівність значень. Обидва значення рівні 3
, тому повертається true
.
При використанні оператора ===
значення і тип повинні бути однаковими. Але в нашому випадку це не так: new Number()
це не число, це об'єкт. Тому обидва повертають false
.
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor;
return this.newColor;
}
constructor({ newColor = "green" } = {}) {
this.newColor = newColor;
}
}
const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
- A:
orange
- B:
purple
- C:
green
- D:
TypeError
Відповідь
Функція colorChange
є статичною. Статичні методи не мають доступу до екземплярів класу. Так як freddie
це екземпляр, то статичний метод там не доступний. Тому результатом є помилка TypeError
.
let greeting;
greetign = {}; // Typo!
console.log(greetign);
- A:
{}
- B:
ReferenceError: greetign is not defined
- C:
undefined
Відповідь
В консолі виведеться об'єкт, тому що ми щойно створили порожній об'єкт в глобальному об'єкті! Коли ми замість greeting
написали greetign
, інтерпретатор JS насправді виконав global.greetign = {}
(або window.greetign = {}
в браузері).
Потрібно використовувати "use strict"
, щоб уникнути такої поведінки. Цей запис допоможе бути впевненим в тому, що змінна була визначена перед тим як їй присвоїли значення.
function bark() {
console.log("Woof!");
}
bark.animal = "dog";
- A: Нічого, все ок.
- B:
SyntaxError
. Не можна додавати властивості функцій таким способом. - C:
undefined
- D:
ReferenceError
Відповідь
В JavaScript це можливо, тому що функції це об'єкти! (Все є об'єктами крім примітивів).
Функція - це спеціальний тип об'єкта, який можна викликати. Крім того, функція - це об'єкт з властивостями. Властивість такого об'єкта не можна викликати, так як воно не є функцією.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = function() {
return `${this.firstName} ${this.lastName}`;
};
console.log(member.getFullName());
- A:
TypeError
- B:
SyntaxError
- C:
Lydia Hallie
- D:
undefined
undefined
Відповідь
Не можна додавати властивості конструктору, як звичайному об'єкту. Якщо потрібно додати фічу до всіх об'єктів, то необхідно використовувати прототипи. В даному випадку,
Person.prototype.getFullName = function() {
return `${this.firstName} ${this.lastName}`;
};
зробить метод member.getFullName()
чинним. У чому тут перевага? Припустимо, що ми додали цей метод до конструктора. Можливо, не кожному екземпляру Person
потрібен цей метод. Це призведе до великих втрат пам'яті, тому що всі екземпляри будуть мати цю властивість. Навпаки, якщо ми додамо цей метод тільки до прототипу, у нас буде тільки одне місце в пам'яті, до якого зможуть звертатися всі екземпляри!
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");
console.log(lydia);
console.log(sarah);
- A:
Person {firstName: "Lydia", lastName: "Hallie"}
таundefined
- B:
Person {firstName: "Lydia", lastName: "Hallie"}
таPerson {firstName: "Sarah", lastName: "Smith"}
- C:
Person {firstName: "Lydia", lastName: "Hallie"}
та{}
- D:
Person {firstName: "Lydia", lastName: "Hallie"}
таReferenceError
Відповідь
Для sarah
ми не використали ключове слово new
. Використання new
призводить до створення нового об'єкта. Але без new
він вказує на глобальний об'єкт!
Ми вказали, що this.firstName
дорівнює "Sarah"
і this.lastName
дорівнює "Smith"
. Насправді ми визначили global.firstName = 'Sarah'
і global.lastName = 'Smith'
. sarah
залишилася undefined
.
- A: Мета (Target) > Захоплення (Capturing) > Спливання (Bubbling)
- B: Спливання (Bubbling) > Мета (Target) > Захоплення (Capturing)
- C: Мета (Target) > Спливання (Bubbling) > Захоплення (Capturing)
- D: Захоплення (Capturing) > Мета (Target) > Спливання (Bubbling)
Відповідь
Під час фази захоплення подія поширюється від батьківського елемента до елемента мети. Після досягнення мети починається фаза спливання.
- A: Так
- B: Ні
Відповідь
Всі об'єкти мають прототипи, крім базового об'єкта. Базовий об'єкт має доступ до деяких методів і властивостей, таких як .toString
. Саме тому ми можемо використовувати вбудовані методи JavaScript! Всі ці методи доступні в прототипі. Якщо JavaScript не може знайти метод безпосередньо у об'єкту, він продовжує пошук по ланцюжку прототипів поки не знайде.
function sum(a, b) {
return a + b;
}
sum(1, "2");
- A:
NaN
- B:
TypeError
- C:
"12"
- D:
3
Відповідь
JavaScript це динамічно типізована мова: ми не визначаємо тип змінних. Змінні можуть автоматично бути перетворені з одного типу в інший без нашої участі, що називається неявним приведенням типів. Приведення це перетворення з одного типу в інший.
У цьому прикладі, JavaScript конвертувати число 1
в рядок, щоб операція всередині функції мала сенс і повернула значення. Під час складання числа (1
) і рядки ('2'
) число перетворюється до рядка. Ми можемо додавати рядки ось так: "Hello" + "World"
. Таким чином, "1"
+ "2"
повертає "12"
.
let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
- A:
1
1
2
- B:
1
2
2
- C:
0
2
2
- D:
0
1
2
Відповідь
Постфіксний унарний оператор ++
:
- Повертає значення (
0
) - Інкрементує значення (тепер число дорівнює
1
)
Префіксний унарний оператор ++
:
- Інкрементує значення (тепер число дорівнює
2
) - Повертає значення (
2
)
Результат: 0 2 2
.
function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
- A:
"Lydia"
21
["", " is ", " years old"]
- B:
["", " is ", " years old"]
"Lydia"
21
- C:
"Lydia"
["", " is ", " years old"]
21
Відповідь
При використанні тегованих шаблонних літералів першим аргументом завжди буде масив строкових значень. Решта аргументів будуть значення мати переданих виразів!
function checkAge(data) {
if (data === { age: 18 }) {
console.log("You are an adult!");
} else if (data == { age: 18 }) {
console.log("You are still an adult.");
} else {
console.log(`Hmm.. You don't have an age I guess`);
}
}
checkAge({ age: 18 });
- A:
You are an adult!
- B:
You are still an adult.
- C:
Hmm.. You don't have an age I guess
Відповідь
В операціях порівняння примітиви порівнюються за їх значенням, а об'єкти за посиланнями. JavaScript перевіряє, щоб об'єкти вказували на одну і ту ж область пам'яті.
Порівнювані об'єкти в нашому прикладі не такі: об'єкт, переданий як параметр, вказує на іншу область пам'яті, ніж об'єкти, що використовуються в порівнянні.
Тому {age: 18} === {age: 18}
і {age: 18} == {age: 18}
повертають false
.
function getAge(...args) {
console.log(typeof args);
}
getAge(21);
- A:
"number"
- B:
"array"
- C:
"object"
- D:
"NaN"
Відповідь
Оператор поширення (... args
) повертає масив з аргументами. Масив це об'єкт, тому typeof args
повертає "object"
.
function getAge() {
"use strict";
age = 21;
console.log(age);
}
getAge();
- A:
21
- B:
undefined
- C:
ReferenceError
- D:
TypeError
Відповідь
Використовуючи "use strict"
, можна бути впевненим, що ми помилково не оголосимо глобальні змінні. Ми раніше ніде не оголошували змінну age
, тому з використанням "use strict"
виникне ReferenceError. Без використання "use strict"
помилки не виникне, а змінна age
додасться в глобальний об'єкт.
const sum = eval("10*10+5");
- A:
105
- B:
"105"
- C:
TypeError
- D:
"10*10+5"
Відповідь
eval
виконує код, переданий у вигляді рядка. Якщо це рядок (як в такому випадку), то обчислюється вираз. Вираз 10 * 10 + 5
поверне число 105
.
sessionStorage.setItem("cool_secret", 123);
- A: Завжди, дані не загубляться.
- B: Поки користувач не закриває вкладку.
- C: Поки користувач не закриє браузер, а не тільки вкладку.
- D: Поки користувач не вимикає комп'ютер.
Відповідь
Дані, збережені в sessionStorage
очищаються після закриття вкладки.
При використанні localStorage
дані зберігаються назавжди. Очистити їх можна, наприклад, використовуючи localStorage.clear()
.
var num = 8;
var num = 10;
console.log(num);
- A:
8
- B:
10
- C:
SyntaxError
- D:
ReferenceError
Відповідь
За допомогою ключового слова var
, можна визначати скільки завгодно змінних з одним і тим же ім'ям. Змінна зберігатиме останнє присвоєне значення.
Ви не можете зробити це з let
або const
, оскільки вони блочні.
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
- A:
false
true
false
true
- B:
false
true
true
true
- C:
true
true
false
true
- D:
true
true
true
true
Відповідь
Всі ключі об'єктів (крім Symbols
) є рядками, навіть якщо задано не в вигляді рядків. Тому obj.hasOwnProperty('1')
так само повертає true
.
Але це не працює для set
. Значення "1"
немає в set
: set.has ('1')
, тому повертається false
. Але set.has(1)
поверне true
.
const obj = { a: "one", b: "two", a: "three" };
console.log(obj);
- A:
{ a: "one", b: "two" }
- B:
{ b: "two", a: "three" }
- C:
{ a: "three", b: "two" }
- D:
SyntaxError
Відповідь
Якщо є два ключі з однаковим ім'ям, то ключ буде перезаписаний. Його позиція збережеться, але значенням буде встановлено останнім.
- A: Так
- B: Ні
- C: В залежності від ситуації
Відповідь
Базовий контекст виконання це глобальний контекст виконання: це те, що є де завгодно у твоєму коді.
for (let i = 1; i < 5; i++) {
if (i === 3) continue;
console.log(i);
}
- A:
1
2
- B:
1
2
3
- C:
1
2
4
- D:
1
3
4
String.prototype.giveLydiaPizza = () => {
return "Just give Lydia pizza already!";
};
const name = "Lydia";
console.log(name.giveLydiaPizza())
- A:
"Just give Lydia pizza already!"
- B:
TypeError: not a function
- C:
SyntaxError
- D:
undefined
Відповідь
String
це вбудований конструктор, до якого можна додавати властивості. Я додала метод до його прототипу. Рядки-примітиви автоматично конвертуються до рядків-об'єктів. Тому всі рядки (строкові об'єкти) мають доступ до цього методу!
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]);
- A:
123
- B:
456
- C:
undefined
- D:
ReferenceError
Відповідь
Ключі об'єкта автоматично конвертуються в рядки. Ми збираємося додати об'єкт в якості ключа до об'єкта a
зі значенням 123
.
Проте, коли ми наводимо об'єкт до рядка, він стає "[object Object]"
. Таким чином, ми говоримо, що a["object Object"] = 123
. Потім ми робимо те ж саме. c
це інший об'єкт, який ми неявно наводимо до рядка. Тому a["object Object"] = 456
.
Потім, коли ми виводимо a[b]
, ми маємо на увазі a["object Object"]
. Ми тільки що встановили туди значення 456
, тому в результаті отримуємо 456
.
const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");
bar();
foo();
baz();
- A:
First
Second
Third
- B:
First
Third
Second
- C:
Second
First
Third
- D:
Second
Third
First
Відповідь
Ми викликаємо функцію setTimeout
першою. Тим не менш, вона виводиться в консоль останньою.
Це відбувається через те, що в браузерах у нас є не тільки рантайм движок, але і WebAPI
. WebAPI
надає нам функцію setTimeout
і багато інших можливостей. Наприклад, DOM.
Після того як коллбек відправлений в WebAPI
, функція setTimeout
(але не коллбек!) виймається з стека.
Тепер викликається foo
, і "First"
виводиться в консоль.
foo
дістається з стека, і викликається baz
. "Third"
виводиться в консоль.
WebAPI
не може додавати вміст в стек коли захоче. Замість цього він відправляє коллбек-функцію в так звану чергу.
Тут на сцену виходить цикл подій (event loop). Event loop перевіряє стек і черга завдань. Якщо стек порожній, то він бере перший елемент з черги і відправляє його в стек.
Викликається bar
, в консоль виводиться "Second"
і ця функція дістається з стека.
<div onclick="console.log('first div')">
<div onclick="console.log('second div')">
<button onclick="console.log('button')">
Click!
</button>
</div>
</div>
- A: Зовнішній
div
- B: Внутрішній
div
- C:
button
- D: Масив з усіма вкладеними елементами
Відповідь
Метою події є найглибший вкладений елемент. Зупинити поширення подій можна за допомогою event.stopPropagation
<div onclick="console.log('div')">
<p onclick="console.log('p')">
Click here!
</p>
</div>
- A:
p
div
- B:
div
p
- C:
p
- D:
div
Відповідь
Після кліка по p
буде виведено p
та div
. У циклі життя події є три фази: захоплення, мета і спливання. За замовчуванням обробники подій виконуються на фазі спливання (якщо не встановлено параметр useCapture
в true
). Спливання йде з найглибшого елемента вгору.
const person = { name: "Lydia" };
function sayHi(age) {
console.log(`${this.name} is ${age}`);
}
sayHi.call(person, 21);
sayHi.bind(person, 21);
- A:
undefined is 21
Lydia is 21
- B:
function
function
- C:
Lydia is 21
Lydia is 21
- D:
Lydia is 21
function
Відповідь
В обох випадках ми передаємо об'єкт, на який буде вказувати this
. Але .call
виконується відразу ж!
.bind
повертає копію функції, але з прив'язаним контекстом. Вона не виконується негайно.
function sayHi() {
return (() => 0)();
}
typeof sayHi();
- A:
"object"
- B:
"number"
- C:
"function"
- D:
"undefined"
Відповідь
Функція sayHi
повертає значення, що повертається з негайно викликаного функціонального виразу (IIFE). Результатом є 0
типу "number"
.
Для інформації: в JS 7 вбудованих типів: null
, undefined
, boolean
, number
, string
, object
, symbol
, та bigint
. "Function"
не є окремим типом, тому що функції є об'єктами типу "object"
.
0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
- A:
0
,''
,undefined
- B:
0
,new Number(0)
,''
,new Boolean(false)
,undefined
- C:
0
,''
,new Boolean(false)
,undefined
- D: Всі значення.
Відповідь
Є тільки шість "помилкових" значень:
undefined
null
NaN
0
''
(порожній рядок)false
Конструктори функцій, такі як new Number
та new Boolean
є "істинними".
console.log(typeof typeof 1);
- A:
"number"
- B:
"string"
- C:
"object"
- D:
"undefined"
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
- A:
[1, 2, 3, 7 x null, 11]
- B:
[1, 2, 3, 11]
- C:
[1, 2, 3, 7 x empty, 11]
- D:
SyntaxError
Відповідь
Коли в масив додається значення, яке виходить за межі довжини масиву, JavaScript створює так звані "порожні клітинки". Насправді вони мають значення undefined
, але в консолі виводяться так:
[1, 2, 3, 7 x empty, 11]
в залежності від місця використання (може відрізнятися для браузерів, Node, і т.д.).
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1), (y = 2);
console.log(x);
}
console.log(x);
console.log(y);
})();
- A:
1
undefined
2
- B:
undefined
undefined
undefined
- C:
1
1
2
- D:
1
undefined
undefined
Відповідь
Блок catch
отримує аргумент x
. Це не той же x
, який визначено в якості змінної перед рядком try
.
Потім ми присвоюємо даному аргументу значення 1
та встановлюємо значення для змінної y
. Потім виводимо в консоль значення аргументу x
, що дорівнює 1
.
За межами блоку catch
змінна x
все ще undefined
, а y
дорівнює 2
. Коли ми викликаємо console.log(x)
за межами блоку catch
, цей виклик повертає undefined
, а y
повертає 2
.
- A: примітив або об'єкт
- B: функція або об'єкт
- C: питання з підступом! тільки об'єкти
- D: число або об'єкт
Відповідь
В JavaScript є тільки примітиви й об'єкти.
Типи примітивів: boolean
, null
, undefined
, bigint
, number
, string
, та symbol
.
Відмінністю примітиву від об'єкта є те, що примітиви не мають властивостей або методів. Проте, 'foo'.toUpperCase()
перетворюється в 'FOO'
та не викликає TypeError
. Це відбувається тому, що при спробі отримання властивості або методу у примітиву (наприклад, рядки), JavaScript неявно оберне примітив об'єктом, використовуючи один з класів-обгорток (наприклад, String
), а потім відразу ж знищить обгортку після обчислення виразу. Всі примітиви крім null
та undefined
поводяться таким чином.
[[0, 1], [2, 3]].reduce(
(acc, cur) => {
return acc.concat(cur);
},
[1, 2]
);
- A:
[0, 1, 2, 3, 1, 2]
- B:
[6, 1, 2]
- C:
[1, 2, 0, 1, 2, 3]
- D:
[1, 2, 6]
Відповідь
[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]
.
!!null;
!!"";
!!1;
- A:
false
true
false
- B:
false
false
true
- C:
false
true
true
- D:
true
true
false
Відповідь
null
"НЕправдивий". !null
повертає true
. !true
повертає false
.
""
"НЕправдивий". !""
повертає true
. !true
повертає false
.
1
"правдивий". !1
повертає false
. !false
повертає true
.
setInterval(() => console.log("Hi"), 1000);
- A: унікальний id
- B: вказану кількість мілісекунд
- C: передану функцію
- D:
undefined
Відповідь
Цей метод повертає унікальний id, який може бути використаний для очищення інтервалу за допомогою функції clearInterval()
.
[..."Lydia"];
- A:
["L", "y", "d", "i", "a"]
- B:
["Lydia"]
- C:
[[], "Lydia"]
- D:
[["L", "y", "d", "i", "a"]]
Відповідь
Рядок є ітерабельною сутністю. Оператор поширення перетворює кожен символ в окремий елемент.
function* generator(i) {
yield i;
yield i * 2;
}
const gen = generator(10);
console.log(gen.next().value);
console.log(gen.next().value);
- A:
[0, 10], [10, 20]
- B:
20, 20
- C:
10, 20
- D:
0, 10 and 10, 20
Answer
Звичайні функції не можна зупинити "на півдорозі" після виклику. Однак функція-генератор може зупинитися "на півдорозі", а потім продовжити з того місця, де вона зупинилась. Кожного разу, коли функція-генератор зустрічає ключове слово yield
, функція видає значення, що вказане після нього. Зауважте, що функція-генератор в цьому випадку не повертає (return) значення, вона дає (yields) значення.
Спочатку ми ініціалізуємо функцію-генератор з i
рівним 10
. Ми викликаємо функцію-генератор за допомогою методу next()
. Коли ми вперше викликаємо функцію генератора, i
дорівнює 10
. Перше ключове слово yield
: воно дає значення i
. Генератор тепер "призупинено", і 10
записується у консоль.
Потім ми знову викликаємо функцію за допомогою методу next()
. Виконання коду продовжується там, де зупинилося раніше, все ще з i
що дорівнює 10
. Тепер функція зустрічає наступне ключове слово yield
і дає i * 2
. i
дорівнює 10
, тож віддається 10 * 2
, що дорівнює 20
. У результаті: 10, 20
.
const firstPromise = new Promise((res, rej) => {
setTimeout(res, 500, 'one');
});
const secondPromise = new Promise((res, rej) => {
setTimeout(res, 100, 'two');
});
Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
- A:
"one"
- B:
"two"
- C:
"two" "one"
- D:
"one" "two"
Answer
Коли ми передаємо кілька промісів методу Promise.race
, він вирішує/відхиляє перший проміс, яки вирішився/відхилився. Методу setTimeout
ми передаємо таймер: 500 мс для першого промісу (firstPromise
) та 100 мс для другого промісу (secondPromise
). Це означає, що secondPromise
вирішиться першим зі значенням 'two'
. res
тепер містить значення 'two'
, яке буде зображено у консолі.
let person = { name: 'Lydia' };
const members = [person];
person = null;
console.log(members);
- A:
null
- B:
[null]
- C:
[{}]
- D:
[{ name: "Lydia" }]
Answer
Спочатку ми оголошуємо змінну person
що містить об'єкта, який має властивість name
.
Потім ми оголошуємо змінну members
. Ми встановлюємо перший елемент масиву рівним значенню змінної person
. Об'єкти взаємодіють за допомогою посилання, коли їх встановлюють рівними один одному. Коли ви призначаєте посилання з однієї змінної на іншу, ви робите копію цього посилання. (зверніть увагу, що вони не мають однакового посилання!)
Далі ми встановлюємо змінну person
рівною null
.
Ми лише змінюємо значення змінної person
, а не перший елемент у масиві, оскільки цей елемент має інше (скопійоване) посилання на об’єкт.Перший елемент у members
все ще містить своє посилання на вихідний об’єкт. Коли ми виводимо у консоль масив members
, перший елемент усе ще містить значення об'єкта, який і показується у консолі.