Я ежедневно публикую вопросы по JavaScript с вариантами ответов в своем Instagram, которые дублируются в этом репозитории.
От базового до продвинутого: проверьте, насколько хорошо вы знаете JavaScript, немного освежите свои знания или подготовьтесь к собеседованию! 💪 🚀 Я обновляю репозиторий еженедельно новыми вопросами. Последнее обновление: 26 июля
Ответы находятся в свернутой секции ниже вопросов. Просто нажми на "Ответ", чтобы развернуть. Удачи! ❤️
Хотите получать электронную почту всякий раз, когда я добавляю новые вопросы?
✨✉Подпишитесь на обновления✉✨
Список доступных переводов:
- English
- العربية
- اللغة العامية - Egyptian Arabic
- Bosanski
- Deutsch
- Español
- Français
- 日本語
- 한국어
- Português Brasil
- Русский
- Українська мова
- Tiếng Việt
- 中文版本
- Türkçe
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. Это не является валидным, и мы получаем ошибку типа Cannot 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:
truefalsetrue - B:
falsefalsetrue - C:
truefalsefalse - D:
falsetruetrue
Ответ
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 = {}; // Опечатка!
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:
undefinedundefined
Ответ
Нельзя добавлять свойства конструктору, как обычному объекту. Если нужно добавить фичу всем объектам, то необходимо использовать прототипы. В данном случае
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, поскольку мы не возвращаем значение из функции Person.
- A: Цель > Захват > Всплытие
- B: Всплытие > Цель > Захват
- C: Цель > Всплытие > Захват
- D: Захват > Цель > Всплытие
Ответ
Во время фазы захвата событие распространяется с элементов родителей до элемента цели. После достижения цели начинается фаза всплытия.
- 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:
112 - B:
122 - C:
022 - D:
012
Ответ
Постфиксный унарный оператор ++:
- Возвращает значение (
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("Ты взрослый!");
} else if (data == { age: 18 }) {
console.log("Ты все еще взрослый.");
} else {
console.log(`Хмм.. Кажется, у тебя нет возраста.`);
}
}
checkAge({ age: 18 });- A:
Ты взрослый! - B:
Ты все еще взрослый. - C:
Хмм.. Кажется, у тебя нет возраста.
Ответ
В операциях сравнения примитивы сравниваются по их значениям, а объекты по ссылкам. 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:
falsetruefalsetrue - B:
falsetruetruetrue - C:
truetruefalsetrue - D:
truetruetruetrue
Ответ
Все ключи объектов (кроме 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:
12 - B:
123 - C:
124 - D:
134
String.prototype.giveLydiaPizza = () => {
return "Just give Lydia pizza already!";
};
const name = "Lydia";
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:
FirstSecondThird - B:
FirstThirdSecond - C:
SecondFirstThird - D:
SecondThirdFirst
Ответ
Мы вызываем функцию 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')">
Кликни!
</button>
</div>
</div>- A: Внешний
div - B: Внутренний
div - C:
button - D: Массив со всеми вложенными элементами
Ответ
Целью события является самый глубокий вложенный элемент. Остановить распространение событий можно с помощью event.stopPropagation
<div onclick="console.log('div')">
<p onclick="console.log('p')">
Кликни меня!
</p>
</div>- A:
pdiv - B:
divp - 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 21Lydia is 21 - B:
functionfunction - C:
Lydia is 21Lydia is 21 - D:
Lydia is 21function
Ответ
В обоих случаях мы передаем объект, на который будет указывать 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. "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: Все являются "ложными"
Ответ
Есть только шесть "ложных" значений:
undefinednullNaN0''(empty string)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:
1undefined2 - B:
undefinedundefinedundefined - C:
112 - D:
1undefinedundefined
Ответ
Блок 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:
falsetruefalse - B:
falsefalsetrue - C:
falsetruetrue - D:
truetruefalse
Ответ
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. Этот 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
Ответ
Обычные функции не могут быть остановлены на полпути после вызова. Однако функцию генератор можно "остановить" на полпути, а затем продолжить с того места, где она остановилась. Каждый раз, когда в функции-генераторе встречает ключевое слово 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, "один");
});
const secondPromise = new Promise((res, rej) => {
setTimeout(res, 100, "два");
});
Promise.race([firstPromise, secondPromise]).then(res => console.log(res));- A:
"один" - B:
"два" - C:
"два" "один" - D:
"один" "два"
Ответ
Когда мы передаем несколько промисов методу Promise.race, он разрешает/отклоняет первый промис, который разрешает/отклоняет. В метод setTimeout мы передаем таймер: 500 мс для первого промиса (firstPromise) и 100 мс для второго промиса (secondPromise). Это означает, что secondPromise разрешается первым со значением 'два'. res теперь содержит значение 'два', которое выводиться в консоль.
let person = { name: "Lydia" };
const members = [person];
person = null;
console.log(members);- A:
null - B:
[null] - C:
[{}] - D:
[{ name: "Lydia" }]
Ответ
Сначала мы объявляем переменную person со значением объекта, у которого есть свойство name.
Затем мы объявляем переменную с именем members. Мы устанавливаем первый элемент этого массива равным значению переменной person. Объекты взаимодействуют посредством ссылок при установке их равными друг другу. Когда вы назначаете ссылку из одной переменной в другую, вы создаете копию этой ссылки. (обратите внимание, что у них не одинаковые ссылки!)
Затем мы присваиваем переменной person значение null.
Мы изменили только значение переменной person, а не первый элемент в массиве, поскольку этот элемент имеет другую (скопированную) ссылку на объект. Первый элемент в members по-прежнему содержит ссылку на исходный объект. Когда мы выводим в консоль массив members, первый элемент по-прежнему содержит значение объекта, который выводится в консоль.
const person = {
name: "Lydia",
age: 21
};
for (const item in person) {
console.log(item);
}- A:
{ name: "Lydia" }, { age: 21 } - B:
"name", "age" - C:
"Lydia", 21 - D:
["name", "Lydia"], ["age", 21]
Ответ
С помощью цикла for-in мы можем перебирать ключи объекта, в данном случае name и age. Под капотом ключи объекта являются строками (если они не являются Symbol). В каждом цикле мы устанавливаем значение item равным текущему ключу, по которому он перебирается. Сначала, item равен name, и выводится в консоль. Затем item равен age, который выводится в консоль.
console.log(3 + 4 + "5");- A:
"345" - B:
"75" - C:
12 - D:
"12"
Ответ
Ассоциативность операторов - это порядок, в котором компилятор оценивает выражения, слева направо или справа налево. Это происходит только в том случае, если все операторы имеют одинаковый приоритет. У нас есть только один тип оператора: +. Кроме того, ассоциативность слева направо.
3 + 4 оценивается первым. Это приводит к числу 7.
7 + '5' приводит к "75" из-за принуждения. JavaScript преобразует число 7 в строку, см. вопрос 15. Мы можем объединить две строки, используя оператор +. "7" + "5" приводит к "75".
const num = parseInt("7*6", 10);- A:
42 - B:
"42" - C:
7 - D:
NaN
Ответ
Только первые числа в строке возвращаются. На основе системы счисления (второй аргумент, чтобы указать, к какому типу чисел мы хотим его анализировать: основание 10, шестнадцатеричное, восьмеричное, двоичное и т.д.), ParseInt проверяет, являются ли символы в строке допустимыми. Как только он встречает символ, который не является допустимым числом в основании, он прекращает синтаксический анализ и игнорирует следующие символы.
* не является допустимым числом. Он только разбирает "7" в десятичную 7. num теперь содержит значение 7.
[1, 2, 3].map(num => {
if (typeof num === "number") return;
return num * 2;
});- A:
[] - B:
[null, null, null] - C:
[undefined, undefined, undefined] - D:
[ 3 x empty ]
Ответ
При использовании метода map, значение num равно элементу, над которым он в данный момент зацикливается. В этом случае элементы являются числами, поэтому условие оператора if typeof num === "number" возвращает true. Функция map создает новый массив и вставляет значения, возвращаемые функцией.
Однако мы не возвращаем значение. Когда мы не возвращаем значение из функции, функция возвращает значение undefined. Для каждого элемента в массиве вызывается функциональный блок, поэтому для каждого элемента мы возвращаем undefined.
function getInfo(member, year) {
member.name = "Lydia";
year = 1998;
}
const person = { name: "Sarah" };
const birthYear = "1997";
getInfo(person, birthYear);
console.log(person, birthYear);- A:
{ name: "Lydia" }, "1997" - B:
{ name: "Sarah" }, "1998" - C:
{ name: "Lydia" }, "1998" - D:
{ name: "Sarah" }, "1997"
Ответ
Аргументы передаются значением, если их значение не является объектом, то они передаются ссылкой. birthYear передается по значению, поскольку это строка, а не объект. Когда мы передаем аргументы по значению, создается копия этого значения (см. вопрос 46).
Переменная birthYear имеет ссылку на значение "1997". Аргумент year также имеет ссылку на значение"1997", но это не то же самое значение, на которое имеется ссылка для birthYear. Когда мы обновляем значение year, устанавливая year равным "1998", мы обновляем только значение year. birthYear по-прежнему равно "1997".
Значение person является объектом. Аргумент member имеет (скопированную) ссылку на тот же объект. Когда мы изменяем свойство объекта, на который member ссылается, значение person также будет изменено, поскольку они оба имеют ссылку на один и тот же объект. Свойство name объекта person теперь равно значению "Lydia".
function greeting() {
throw "Hello world!";
}
function sayHi() {
try {
const data = greeting();
console.log("It worked!", data);
} catch (e) {
console.log("Oh no an error!", e);
}
}
sayHi();- A:
"It worked! Hello world!" - B:
"Oh no an error: undefined - C:
SyntaxError: can only throw Error objects - D:
"Oh no an error: Hello world!
Ответ
С помощью оператора throw мы можем создавать собственные ошибки. С этим оператором вы можете генерировать исключения. Исключением может быть строка, число, логическое значение или объект. В этом случае нашим исключением является строка 'Hello world'.
С помощью оператора catch мы можем указать, что делать, если в блоке try выдается исключение. Исключение: строка 'Hello world'. e теперь равно той строке, которую мы записываем. Это приводит к 'Oh error: Hello world'.
function Car() {
this.make = "Lamborghini";
return { make: "Maserati" };
}
const myCar = new Car();
console.log(myCar.make);- A:
"Lamborghini" - B:
"Maserati" - C:
ReferenceError - D:
TypeError
Ответ
Когда вы возвращаете свойство, значение свойства равно возвращаемому значению, а не значению, установленному в функции конструктора. Мы возвращаем строку "Maserati", поэтому myCar.make равно "Maserati".
(() => {
let x = (y = 10);
})();
console.log(typeof x);
console.log(typeof y);- A:
"undefined", "number" - B:
"number", "number" - C:
"object", "number" - D:
"number", "undefined"
Ответ
let x = y = 10; на самом деле является сокращением для:
y = 10;
let x = y;Когда мы устанавливаем y равным 10, мы фактически добавляем свойство y к глобальному объекту (window в браузере, global в Node). В браузере window.y теперь равен 10.
Затем мы объявляем переменную 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".
class Dog {
constructor(name) {
this.name = name;
}
}
Dog.prototype.bark = function() {
console.log(`Woof I am ${this.name}`);
};
const pet = new Dog("Mara");
pet.bark();
delete Dog.prototype.bark;
pet.bark();- A:
"Woof I am Mara",TypeError - B:
"Woof I am Mara","Woof I am Mara" - C:
"Woof I am Mara",undefined - D:
TypeError,TypeError
Ответ
Мы можем удалить свойства из объектов, используя ключевое слово delete, также в прототипе. Удаляя свойство в прототипе, оно больше не доступно в цепочке прототипов. В этом случае функция bark больше не доступна в прототипе послеdelete Dog.prototype.bark, но мы все еще пытаемся получить к ней доступ.
Когда мы пытаемся вызвать что-то, что не является функцией, выдается TypeError. В этом случае TypeError: pet.bark не является функцией, поскольку pet.bark является undefined.
const set = new Set([1, 1, 2, 3, 4]);
console.log(set);- A:
[1, 1, 2, 3, 4] - B:
[1, 2, 3, 4] - C:
{1, 1, 2, 3, 4} - D:
{1, 2, 3, 4}
Ответ
Объект Set является коллекцией unique значений: значение может появляться только один раз в наборе.
Мы передали последовательность [1, 1, 2, 3, 4] с повторяющимся значением 1. Поскольку в наборе не может быть двух одинаковых значений, одно из них удаляется. Это приводит к {1, 2, 3, 4}.
// counter.js
let counter = 10;
export default counter;// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);- A:
10 - B:
11 - C:
Error - D:
NaN
Ответ
Импортированный модуль является read-only: вы не можете изменить импортированный модуль. Только модуль, который их экспортирует, может изменить его значение.
Когда мы пытаемся увеличить значение myCounter, выдается ошибка: myCounter доступен только для чтения и не может быть изменен.
const name = "Lydia";
age = 21;
console.log(delete name);
console.log(delete age);- A:
false,true - B:
"Lydia",21 - C:
true,true - D:
undefined,undefined
Ответ
Оператор delete возвращает логическое значение: true при успешном удалении, иначе он вернет false. Однако переменные, объявленные с ключевым словом var, const или let, не могут быть удалены с помощью оператора delete.
Переменная name была объявлена с ключевым словом const, поэтому ее удаление не было успешным: возвращается false. Когда мы устанавливаем age равным 21, мы фактически добавляем свойство с именем age к глобальному объекту. Вы можете успешно удалить свойства из объектов, в том числе из глобального объекта, поэтому delete age возвращает true.
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;
console.log(y);- A:
[[1, 2, 3, 4, 5]] - B:
[1, 2, 3, 4, 5] - C:
1 - D:
[1]
Ответ
Мы можем распаковать значения из массивов или свойств из объектов путем деструктуризации. Например:
[a, b] = [1, 2];
Значение a теперь равно 1, а значение b теперь равно 2. Что мы на самом деле сделали в этом вопросе, так это:
[y] = [1, 2, 3, 4, 5];
Это означает, что значение y равно первому значению в массиве, которое является числом 1. Когда мы регистрируем y, возвращается 1.
const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };
console.log(admin);- A:
{ admin: true, user: { name: "Lydia", age: 21 } } - B:
{ admin: true, name: "Lydia", age: 21 } - C:
{ admin: true, user: ["Lydia", 21] } - D:
{ admin: true }
Ответ
Можно комбинировать объекты с помощью оператора распространения .... Это позволяет создавать копии пар ключ/значение одного объекта и добавлять их в другой объект. В этом случае мы создаем копии объекта user и добавляем их в объект admin. Объект admin теперь содержит скопированные пары ключ/значение, что приводит к {admin: true, name: "Lydia", age: 21}.
const person = { name: "Lydia" };
Object.defineProperty(person, "age", { value: 21 });
console.log(person);
console.log(Object.keys(person));- A:
{ name: "Lydia", age: 21 },["name", "age"] - B:
{ name: "Lydia", age: 21 },["name"] - C:
{ name: "Lydia"},["name", "age"] - D:
{ name: "Lydia"},["age"]
Ответ
С помощью метода defineProperty мы можем добавлять новые свойства к объекту или изменять существующие. Когда мы добавляем свойство к объекту с помощью метода defineProperty, они по умолчанию не перечисляемые. Метод Object.keys возвращает все имена enumerable свойств объекта, в данном случае только "name".
Свойства, добавленные с помощью метода defineProperty, по умолчанию неизменны. Вы можете переопределить это поведение, используя свойства writable, configurable и enumerable. Таким образом, метод defineProperty дает вам гораздо больший контроль над свойствами, которые вы добавляете к объекту.
const settings = {
username: "lydiahallie",
level: 19,
health: 90
};
const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);- A:
"{"level":19, "health":90}" - B:
"{"username": "lydiahallie"}" - C:
"["level", "health"]" - D:
"{"username": "lydiahallie", "level":19, "health":90}"
Ответ
Второй аргумент JSON.stringify - это replacer. Заменитель может быть либо функцией, либо массивом, и позволяет вам контролировать, что и как должны быть преобразованы в значения.
Если заменитель является массивом, только свойства, имена которых включены в массив, будут добавлены в строку JSON. В этом случае включаются только свойства с именами "level" и "health", "username" исключается. data теперь равен "{"level":19, "health":90}".
Если заменитель является function, эта функция вызывается для каждого свойства объекта, который вы преобразуете. Значение, возвращаемое из этой функции, будет значением свойства при добавлении в строку JSON. Если значение равно undefined, это свойство исключается из строки JSON.
let num = 10;
const increaseNumber = () => num++;
const increasePassedNumber = number => number++;
const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);
console.log(num1);
console.log(num2);- A:
10,10 - B:
10,11 - C:
11,11 - D:
11,12
Ответ
Унарный оператор ++ first возвращает значение операнда, then приращивает значение операнда. Значение num1 равно 10, так как функция увеличений вначале возвращает значение num, которое равно 10, и только затем увеличивает значение num.
num2 - это 10, так как мы передали num1 в incpasePassedNumber. number равно 10 (значение num1. Опять же, унарный оператор ++ first возвращает значение операнда, _then увеличивает значение операнда. Значение number равно 10, поэтому num2 равно 10.
const value = { number: 10 };
const multiply = (x = { ...value }) => {
console.log((x.number *= 2));
};
multiply();
multiply();
multiply(value);
multiply(value);- A:
20,40,80,160 - B:
20,40,20,40 - C:
20,20,20,40 - D:
NaN,NaN,20,40
Ответ
В ES6 мы можем инициализировать параметры значением по умолчанию. Значением параметра будет значение по умолчанию, если никакое другое значение не было передано функции, или если значение параметра равно "undefined". В этом случае мы распространяем свойства объекта value на новый объект, поэтому значение x по умолчанию равно {number: 10}.
Аргумент по умолчанию реализуется в момент call time! Каждый раз, когда мы вызываем функцию, создается new объект. Мы вызываем функцию multiply первые два раза, не передавая значение: x имеет значение по умолчанию {number: 10}. Затем мы записываем умноженное значение этого числа, которое равно 20.
В третий раз, когда мы вызываем multiply, мы передаем аргумент: объект с именем value. Оператор *= на самом деле является сокращением для x.number = x.number * 2: мы изменяем значение x.number и записываем умноженное значение 20.
В четвертый раз мы снова передаем объект value. x.number ранее был изменен на 20, поэтому x.number * = 2 записывает 40.
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));- A:
12and33and64 - B:
12and23and34 - C:
1undefinedand2undefinedand3undefinedand4undefined - D:
12andundefined3andundefined4
Ответ
Первым аргументом, который получает метод reduce, является аккумулятором, в данном случае x. Второй аргумент - это текущее значение, y. С помощью метода reduce мы выполняем функцию обратного вызова для каждого элемента в массиве, что в конечном итоге может привести к единственному значению.
В этом примере мы не возвращаем никаких значений, мы просто регистрируем значения аккумулятора и текущее значение.
Значение аккумулятора равно ранее возвращенному значению функции обратного вызова. Если вы не передадите необязательный аргумент initialValue методу reduce, аккумулятор будет равен первому элементу при первом вызове.
При первом вызове аккумулятор (x) равен 1, а текущее значение (y) равно 2. Мы не возвращаемся из функции обратного вызова, мы регистрируем аккумулятор и текущее значение: 1 и 2 регистрируются.
Если вы не возвращаете значение из функции, она возвращает значение undefined. При следующем вызове аккумулятор равен undefined, а текущее значение равно 3. undefined и 3 будут зарегистрированы.
При четвертом вызове мы снова не возвращаемся из функции обратного вызова. Аккумулятор снова равен undefined, а текущее значение равно 4. undefined и 4 будут зарегистрированы.
class Dog {
constructor(name) {
this.name = name;
}
};
class Labrador extends Dog {
// 1
constructor(name, size) {
this.size = size;
}
// 2
constructor(name, size) {
super(name);
this.size = size;
}
// 3
constructor(size) {
super(name);
this.size = size;
}
// 4
constructor(name, size) {
this.name = name;
this.size = size;
}
};- A: 1
- B: 2
- C: 3
- D: 4
Ответ
В производном классе вы не можете получить доступ к ключевому слову this до вызова super. Если вы попытаетесь это сделать, он выдаст ReferenceError: 1 и 4 приведут к ошибке ссылки.
С ключевым словом super мы вызываем конструктор родительского класса с заданными аргументами. Конструктор родителя получает аргумент name, поэтому нам нужно передать name в super.
Класс Labrador получает два аргумента: name, поскольку он расширяет Dog, и size в качестве дополнительного свойства класса Labrador. Они оба должны быть переданы в функцию конструктора в Labrador, что делается правильно с помощью конструктора 2.
// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));
// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;- A:
running index.js,running sum.js,3 - B:
running sum.js,running index.js,3 - C:
running sum.js,3,running index.js - D:
running index.js,undefined,running sum.js
Ответ
С ключевым словом import все импортируемые модули являются pre-parsed. Это означает, что импортированные модули запускаются первыми, код в файле, который импортирует модуль, исполняется после.
В этом разница между require() в CommonJS и import! С помощью require() вы можете загружать зависимости по требованию во время выполнения кода. Если бы мы использовали require вместо import, в консоль были бы записаны running index.js, running sum.js, 3.
console.log(Number(2) === Number(2))
console.log(Boolean(false) === Boolean(false))
console.log(Symbol('foo') === Symbol('foo'))- A:
true,true,false - B:
false,true,false - C:
true,false,true - D:
true,true,true
Ответ
Каждый Symbol совершенно уникален. Цель аргумента, переданного Symbol, состоит в том, чтобы дать Symbol описание. Значение Symbol не зависит от переданного аргумента. Когда мы проверяем равенство, мы создаем два совершенно новых Symbol: первый Symbol('foo') и второй Symbol('foo'). Эти два значения уникальны и не равны друг другу, Symbol('foo') === Symbol('foo') возвращает false.
const name = "Lydia Hallie"
console.log(name.padStart(13))
console.log(name.padStart(2))- A:
"Lydia Hallie","Lydia Hallie" - B:
" Lydia Hallie"," Lydia Hallie"("[13x whitespace]Lydia Hallie","[2x whitespace]Lydia Hallie") - C:
" Lydia Hallie","Lydia Hallie"("[1x whitespace]Lydia Hallie","Lydia Hallie") - D:
"Lydia Hallie","Lyd",
Ответ
С помощью метода padStart мы можем добавить отступ в начало строки. Значение, передаваемое этому методу, представляет собой общую длину строки вместе с отступом. Строка "Lydia Hallie" имеет длину 12. name.padStart (13) вставляет 1 пробел в начале строки, потому что 12 + 1 равно 13.
Если аргумент, переданный методу padStart, меньше длины строки, заполнение не будет добавлено.
console.log("🥑" + "💻");- A:
"🥑💻" - B:
257548 - C: A string containing their code points
- D: Error
Ответ
С помощью оператора + вы можете объединять строки. В этом случае мы объединяем строку "" со строкой "💻", что приводит к "💻".
function* startGame() {
const answer = yield "Do you love JavaScript?";
if (answer !== "Yes") {
return "Oh wow... Guess we're gone here";
}
return "JavaScript loves you back ❤️";
}
const game = startGame();
console.log(/* 1 */); // Do you love JavaScript?
console.log(/* 2 */); // JavaScript loves you back ❤️- A:
game.next("Yes").valueandgame.next().value - B:
game.next.value("Yes")andgame.next.value() - C:
game.next().valueandgame.next("Yes").value - D:
game.next.value()andgame.next.value("Yes")
Ответ
Функция генератора "приостанавливает" выполнение, когда видит ключевое слово yield. Во-первых, мы должны позволить функции выдать строку "Do you love JavaScript?", Что можно сделать, вызвав game.next (). Value.
Каждая строка выполняется до тех пор, пока не найдет первое ключевое слово yield. В первой строке функции есть ключевое слово yield на первом месте: выполнение останавливается с первым выходом! Это означает, что переменная answer еще не определена!
Когда мы вызываем game.next("Yes").value, предыдущий yield заменяется значением параметров, переданных функции next(), в данном случае "Yes". Значение переменной answer теперь равно "Yes". Условие if возвращает false, а JavaScript loves you back ❤️, регистрируется.
console.log(String.raw`Hello\nworld`);- A:
Hello world! - B:
Hello
world - C:
Hello\nworld - D:
Hello\n
world
Ответ
String.raw возвращает строку, в которой экранированные символы (\n, \v, \t и т.д.) игнорируются! Обратная косая черта может быть проблемой, так как вы можете получить что-то вроде:
const path = `C:\Documents\Projects\table.html`
Что приведет к:
"C:DocumentsProjects able.html"
С String.raw он просто проигнорирует управляющий знак и напечатает:
C:\Documents\Projects\table.html
В этом случае строка Hello\nworld, которая и выводится.
async function getData() {
return await Promise.resolve("I made it!");
}
const data = getData();
console.log(data);- A:
"I made it!" - B:
Promise {<resolved>: "I made it!"} - C:
Promise {<pending>} - D:
undefined
Ответ
Асинхронная функция всегда возвращает обещание. await все еще должен ждать разрешения обещания: ожидаемое обещание возвращается, когда мы вызываем getData(), чтобы установить data равным ему.
Если бы мы хотели получить доступ к разрешенному значению "I made it", мы могли бы использовать метод .then() для data:
data.then(res => console.log(res))
Тогда это бы вывело "I made it!"
function addToList(item, list) {
return list.push(item);
}
const result = addToList("apple", ["banana"]);
console.log(result);- A:
['apple', 'banana'] - B:
2 - C:
true - D:
undefined
Ответ
Метод .push() возвращает длину нового массива! Ранее массив содержал один элемент (строка "banana") и имел длину 1. После добавления в массив строки "apple", массив содержит два элемента и имеет длину 2. Это возвращается из функции addToList.
Метод push изменяет исходный массив. Если вы хотите вернуть массив из функции, а не длину массива, вы должны были вернуть list после добавления в нее item.
const box = { x: 10, y: 20 };
Object.freeze(box);
const shape = box;
shape.x = 100;
console.log(shape);- A:
{ x: 100, y: 20 } - B:
{ x: 10, y: 20 } - C:
{ x: 100 } - D:
ReferenceError
Ответ
Object.freeze делает невозможным добавление, удаление или изменение свойств объекта (если только значение свойства не является другим объектом).
Когда мы создаем переменную shape и устанавливаем ее равной замороженному объекту box, shape также ссылается на замороженный объект. Вы можете проверить, заморожен ли объект, используя Object.isFrozen. В этом случае Object.isFrozen(shape) возвращает true, поскольку переменная shape имеет ссылку на замороженный объект.
Поскольку shape заморожен, и поскольку значение x не является объектом, мы не можем изменить свойство x. x по-прежнему равно 10, и {x: 10, y: 20} регистрируется.
const { name: myName } = { name: "Lydia" };
console.log(name);- A:
"Lydia" - B:
"myName" - C:
undefined - D:
ReferenceError
Ответ
Когда мы распаковываем свойство name из правого объекта, мы присваиваем его значение "Lydia" переменной с именем myName.
С помощью {name: myName} мы сообщаем JavaScript, что хотим создать новую переменную с именем myName со значением свойства name в правой части.
Поскольку мы пытаемся зарегистрировать name, переменную, которая не определена, выдается ReferenceError.
function sum(a, b) {
return a + b;
}- A: Yes
- B: No
Ответ
Чистая функция - это функция, которая всегда возвращает тот же результат, если переданы одинаковые аргументы.
Функция sum всегда возвращает один и тот же результат. Если мы передадим 1 и 2, он всегда вернет 3 без побочных эффектов. Если мы передадим 5 и 10, он всегда вернет 15 и так далее. Это определение чистой функции.
const add = () => {
const cache = {};
return num => {
if (num in cache) {
return `From cache! ${cache[num]}`;
} else {
const result = num + 10;
cache[num] = result;
return `Calculated! ${result}`;
}
};
};
const addFunction = add();
console.log(addFunction(10));
console.log(addFunction(10));
console.log(addFunction(5 * 2));- A:
Calculated! 20Calculated! 20Calculated! 20 - B:
Calculated! 20From cache! 20Calculated! 20 - C:
Calculated! 20From cache! 20From cache! 20 - D:
Calculated! 20From cache! 20Error
Ответ
Функция add является функцией запоминателем. С помощью запоминания мы можем кэшировать результаты функции, чтобы ускорить ее выполнение. В этом случае мы создаем объект cache, в котором хранятся ранее возвращенные значения.
Если мы снова вызываем функцию addFunction с тем же аргументом, она сначала проверяет, получило ли оно уже это значение в своем кеше. В этом случае будет возвращено значение кэша, что экономит время выполнения. Иначе, если он не кэшируется, он вычислит значение и сохранит его после.
Мы вызываем функцию addFunction три раза с одним и тем же значением: при первом вызове значение функции, когда num равно 10, еще не кэшировано. Условие оператора if num in cache возвращает false, и выполняется блок else: Calculated! 20 регистрируется, и значение результата добавляется в объект кеша. cache теперь выглядит как {10: 20}.
Во второй раз объект cache содержит значение, возвращаемое для 10. Условие оператора if num in cache возвращает true, а 'From cache! 20' выводится в лог.
В третий раз мы передаем 5 * 2 в функцию, которая оценивается как 10. Объект cache содержит значение, возвращаемое для 10. Условие оператора if num in cache возвращает true, а 'From cache! 20' регистрируется.
const myLifeSummedUp = ["☕", "💻", "🍷", "🍫"]
for (let item in myLifeSummedUp) {
console.log(item)
}
for (let item of myLifeSummedUp) {
console.log(item)
}- A:
0123и"☕""💻""🍷""🍫" - B:
"☕""💻""🍷""🍫"и"☕""💻""🍷""🍫" - C:
"☕""💻""🍷""🍫"и0123 - D:
0123и{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
Ответ
С помощью цикла for-in мы можем перебирать перечисляемые свойства. В массиве перечисляемые свойства являются "ключами" элементов массива, которые фактически являются их индексами. Вы можете увидеть массив как:
{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
Где ключи - перечисляемые свойства. 0 1 2 3 войти в систему.
С помощью цикла for-of мы можем выполнять итерацию итераций. Массив является итеративным. Когда мы выполняем итерацию по массиву, переменная "item" равна элементу, по которому она итерируется в данный момент, "☕" "💻" "🍷" "🍫" выводится в лог.
const list = [1 + 2, 1 * 2, 1 / 2]
console.log(list)- A:
["1 + 2", "1 * 2", "1 / 2"] - B:
["12", 2, 0.5] - C:
[3, 2, 0.5] - D:
[1, 1, 1]
Ответ
Элементы массива могут содержать любые значения. Числа, строки, объекты, другие массивы, ноль, логические значения, неопределенные и другие выражения, такие как даты, функции и вычисления.
Элемент будет равен возвращаемому значению. 1 + 2 вернет 3, 1 * 2 вернет 2, а 1 / 2 вернет 0.5.
function sayHi(name) {
return `Hi there, ${name}`
}
console.log(sayHi())- A:
Hello there, - B:
Hello there, undefined - C:
Hello there, null - D:
ReferenceError
Ответ
По умолчанию аргументы имеют значение undefined, если только значение не было передано функции. В этом случае мы не передали значение для аргумента name. name равно логгируемому undefined.
В ES6 мы можем перезаписать значение по умолчанию undefined параметрами по умолчанию. Например:
function sayHi(name = "Lydia") { ... }
В этом случае, если мы не передали значение или если мы передали undefined, name всегда будет равно строке Lydia
var status = "😎"
setTimeout(() => {
const status = "😍"
const data = {
status: "🥑",
getStatus() {
return this.status
}
}
console.log(data.getStatus())
console.log(data.getStatus.call(this))
}, 0)- A:
"🥑"и"😍" - B:
"🥑"и"😎" - C:
"😍"и"😎" - D:
"😎"и"😎"
Ответ
Значение ключевого слова this зависит от того, где вы его используете. В методе, как и в методе getStatus, ключевое слово this ссылается на объект, которому принадлежит метод. Метод принадлежит объекту data, поэтому this относится к объекту data. Когда мы регистрируем this.status, регистрируется свойство status объекта data, которое является "🥑".
С помощью метода call мы можем изменить объект, на который ссылается ключевое слово this. В функциях ключевое слово this относится к объекту, которому принадлежит функция. Мы объявили функцию setTimeout для объекта global, поэтому в функции setTimeout ключевое слово this ссылается на объект global. В глобальном объекте есть переменная с именем status со значением "😎". При регистрации this.status выводится "😎".
const person = {
name: "Lydia",
age: 21
}
let city = person.city
city = "Amsterdam"
console.log(person)- A:
{ name: "Lydia", age: 21 } - B:
{ name: "Lydia", age: 21, city: "Amsterdam" } - C:
{ name: "Lydia", age: 21, city: undefined } - D:
"Amsterdam"
Ответ
Мы устанавливаем переменную city равной значению свойства с именем city для объекта person. У этого объекта нет свойства с именем city, поэтому переменная city имеет значение undefined.
Обратите внимание, что мы не ссылаемся на сам объект person! Мы просто устанавливаем переменную city равной текущему значению свойства city объекта person.
Затем мы устанавливаем city равным строке "Amsterdam". Это не меняет объект person - нет ссылки на этот объект.
При регистрации объекта person возвращается неизмененный объект.
function checkAge(age) {
if (age < 18) {
const message = "Sorry, you're too young."
} else {
const message = "Yay! You're old enough!"
}
return message
}
console.log(checkAge(21))- A:
"Sorry, you're too young." - B:
"Yay! You're old enough!" - C:
ReferenceError - D:
undefined
Ответ
Переменные с ключевыми словами const и let являются block-scoped. Блок - это что-то между фигурными скобками ({}). В этом случае в фигурных скобках операторов if/else. Вы не можете ссылаться на переменную за пределами блока, в котором она объявлена, вызывается ReferenceError.
fetch('https://www.website.com/api/user/1')
.then(res => res.json())
.then(res => console.log(res))- A: The result of the
fetchmethod. - B: The result of the second invocation of the
fetchmethod. - C: The result of the callback in the previous
.then(). - D: It would always be undefined.
Ответ
Значение res во втором .then равно возвращенному значению предыдущего .then. Вы можете продолжать цепочку .then таким образом; значение передается следующему обработчику.
86. Какая опция позволяет установить hasName равным true, если вы не можете передатьtrue в качестве аргумента?
function getName(name) {
const hasName = //
}- A:
!!name - B:
name - C:
new Boolean(name) - D:
name.length
Ответ
С помощью !!name мы определяем, является ли значение name истинным или ложным. Если имя истинное, которое мы хотим проверить, то !name возвращает false. А !false (это то, чем на самом деле является !! name) возвращает true.
Устанавливая hasName равным name, вы устанавливаете hasName равным любому значению, которое вы передали функции getName, а не логическому значению true.
new Boolean (true) возвращает объектную оболочку, а не само логическое значение.
name.length возвращает длину переданного аргумента, независимо от того, является ли он true.