Skip to content

Latest commit

 

History

History
5146 lines (3464 loc) · 197 KB

README.md

File metadata and controls

5146 lines (3464 loc) · 197 KB

Вопросы по JavaScript


Я (Lydia Hallie) ежедневно публикую вопросы по JavaScript с вариантами ответов в своем Instagram сторис, которые дублируются в этом репозитории! Последнее обновление: 12 июня.

От базового до продвинутого: проверьте, насколько хорошо вы знаете JavaScript, немного освежите свои знания или подготовьтесь к собеседованию! 💪 🚀 Я регулярно обновляю этот репозиторий новыми вопросами. Ответы находятся в свернутой секции под каждым вопросом. Просто нажми на "Ответ", чтобы развернуть. Удачи! ❤️

Не стесняйтесь обращаться ко мне (Lydia Hallie)! 😊
Instagram || Twitter || LinkedIn || Blog

Не стесняйтесь использовать эти примеры в проектах! 😃 Я (Lydia Hallie) была бы действительно признателена за ссылку на этот репозиторий. Я добавляю вопросы и объяснения, и сообщество очень помогает мне поддерживать и улучшать все это! 💪🏼 Спасибо и приятного просмотра!

Доступно в 20 переводах 🇸🇦🇪🇬🇧🇦🇩🇪🇪🇸🇫🇷🇮🇩🇯🇵🇰🇷🇳🇱🇧🇷🇷🇺🇹🇭🇹🇷🇺🇦🇻🇳🇨🇳🇹🇼🇽🇰


1. Что будет в консоли?
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
Ответ

Ответ: D

Внутри функции мы сперва определяем переменную name с помощью ключевого слова var. Это означает, что переменная будет поднята (область памяти под переменную будет выделена во время фазы создания) со значением undefined по умолчанию, до тех пора пока исполнение кода не дойдет до строчки, где определяется переменная. Мы еще не определили значение name когда пытаемся вывести её в консоль, поэтому в консоли будет undefined.

Переменные, определенные с помощью letconst), также поднимаются, но в отличие от var, не инициализируются. Доступ к ним не возможен до тех пор, пока не выполнится строка их определения (инициализации). Это называется "временная мертвая зона". Когда мы пытаемся обратиться к переменным до того момента как они определены, JavaScript выбрасывает исключение ReferenceError.


2. Что будет в консоли?
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
Ответ

Ответ: C

Из-за очереди событий в JavaScript, функция setTimeout вызывается после того как цикл будет завершен. Так как переменная i в первом цикле была определена с помощью var, она будет глобальной. В цикле мы каждый раз увеличиваем значение i на 1, используя унарный оператор ++. К моменту выполнения функции setTimeout значение i будет равно 3 в первом примере.

Во втором цикле переменная i определена с помощью let. Такие переменные (а также const) имеют блочную область видимости (блок это что угодно между { }). С каждой итерацией i будет иметь новое значение, и каждое значение будет замкнуто в своей области видимости внутри цикла.


3. Что будет в консоли?
const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2;
  },
  perimeter: () => 2 * Math.PI * this.radius
};

console.log(shape.diameter());
console.log(shape.perimeter());
  • A: 20 и 62.83185307179586
  • B: 20 и NaN
  • C: 20 и 63
  • D: NaN и 63
Ответ

Ответ: B

Заметьте, что diameter это обычная функция, в то время как perimeter это стрелочная функция.

У стрелочных функций значение this указывает на окружающую область видимости, в отличие от обычных функций! Это значит, что при вызове perimeter значение this у этой функции указывает не на объект shape, а на внешнюю область видимости (например, window).

У этого объекта нет ключа radius, поэтому возвращается undefined.


4. Что будет в консоли?
+true;
!'Lydia';
  • A: 1 и false
  • B: false и NaN
  • C: false и false
Ответ

Ответ: A

Унарный плюс приводит операнд к числу. true это 1, а false это 0.

Строка 'Lydia' это "истинное" значение. На самом деле мы спрашиваем "является ли это истинное значение ложным"? Ответ: false.


5. Что НЕ является валидным?
const bird = {
  size: 'small'
};

const mouse = {
  name: 'Mickey',
  small: true
};
  • A: mouse.bird.size
  • B: mouse[bird.size]
  • C: mouse[bird["size"]]
  • D: Все варианты валидны
Ответ

Ответ: A

В 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.


6. Что будет в консоли?
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
Ответ

Ответ: A

В JavaScript все объекты являются ссылочными типами данных.

Сперва переменная c указывает на объект. Затем мы указываем переменной d ссылаться на тот же объект, что и c.

Когда вы изменяете один объект, то изменяются значения всех ссылок, указывающих на этот объект.


7. Что будет в консоли?
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
Ответ

Ответ: C

new Number() это встроенный конструктор функции. И хотя он выглядит как число, это не настоящее число: у него есть ряд дополнительных особеннстей, и это объект.

Оператор == разрешает приведение типов, он проверяет равенство значений. Оба значения равны 3, поэтому возвращается true.

При использовании оператора === значение и тип должны быть одинаковыми. Но в нашем случае это не так: new Number() это не число, это объект. Оба возвращают false.


8. Каким будет результат?
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
Ответ

Ответ: D

Функция colorChange является статической. Статические методы предназначены для работы только в конструкторе, в котором они созданы, и не могут передаваться каким-либо дочерним элементам или вызываться в экземплярах класса. Так как freddie является экземпляром класса Chameleon, функция не может быть вызвана для него. Будет выдана ошибка TypeError.


9. Что будет в консоли?
let greeting;
greetign = {}; // Опечатка!
console.log(greetign);
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined
Ответ

Ответ: A

В консоли выведется объект, потому что мы только что создали пустой объект в глобальном объекте! Когда мы вместо greeting написали greetign, интерпретатор JS на самом деле увидел:

  1. global.greetign = {} в Node.js
  2. window.greetign = {}, frames.geetign = {} и self.greetign в браузерах.
  3. self.greetign в веб-воркерах.
  4. globalThis.greetign во всех окружениях.

Нужно использовать "use strict", чтобы избежать такого поведения. Эта запись поможет быть уверенным в том, что переменная была определена перед тем как ей присвоили значение.


10. Что произойдет?
function bark() {
  console.log('Woof!');
}

bark.animal = 'dog';
  • A: Ничего, всё в порядке!
  • B: SyntaxError. Нельзя добавлять свойства функциям таким способом.
  • C: undefined
  • D: ReferenceError
Ответ

Ответ: A

В JavaScript это возможно, т.к. функции это объекты! (Всё есть объект кроме примитивов).

Функция — это специальный тип объекта, который можно вызвать. Кроме того, функция — это объект со свойствами. Свойство такого объекта нельзя вызвать, так как оно не является функцией.


11. Что будет в консоли?
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
Ответ

Ответ: A

В JavaScript функции являются объектами, поэтому метод getFullName добавляется к самому объекту функции-конструктора. По этой причине мы можем вызвать Person.getFullName(), но member.getFullName выдает TypeError.

Если вы хотите, чтобы метод был доступен для всех экземпляров объекта, вы должны добавить его в свойство прототипа:

Person.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}


12. Что будет в консоли?
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
Ответ

Ответ: A

Для sarah мы не использовали ключевое слово new. Использование new приводит к созданию нового объекта. Но без new он указывает на глобальный объект!

Мы указали, что this.firstName равно "Sarah" и this.lastName равно "Smith". На самом деле мы определили global.firstName = 'Sarah' и global.lastName = 'Smith'. sarah осталась undefined, поскольку мы не возвращаем значение из функции Person.


13. Назовите три фазы распространения событий
  • A: Цель > Захват > Всплытие
  • B: Всплытие > Цель > Захват
  • C: Цель > Всплытие > Захват
  • D: Захват > Цель > Всплытие
Ответ

Ответ: D

Во время фазы захвата событие распространяется с элементов родителей до элемента цели. После достижения цели начинается фаза всплытия.


14. Все объекты имеют прототипы
  • A: Да
  • B: Нет
Ответ

Ответ: B

Все объекты имеют прототипы, кроме базового объекта. Базовый объект — это объект, созданный пользователем, или объект, созданный с использованием ключевого слова new. Базовый объект имеет доступ к некоторым методам и свойствам, таким как .toString. Вот почему вы можете использовать встроенные методы JavaScript! Все такие способы доступны в прототипе. Хотя JavaScript не может найти метод непосредственно в вашем объекте, он идет вниз по цепочке прототипов и находит его там, что делает его доступным.


15. Каким будет результат?
function sum(a, b) {
  return a + b;
}

sum(1, '2');
  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3
Ответ

Ответ: C

JavaScript это динамически типизированный язык: мы не определяем тип переменных. Переменные могут автоматически быть преобразованы из одного типа в другой без нашего участия, что называется неявным приведением типов. Приведение это преобразование из одного типа в другой.

В этом примере JavaScript сконвертировал число 1 в строку, чтобы операция внутри функции имела смысл и вернула значение. Во время сложения числа (1) и строки ('2') число преобразовывается к строке. Мы можем конкатенировать строки вот так: "Hello" + "World". Таким образом, "1" + "2" возвращает "12".


16. Что будет в консоли?
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
Ответ

Ответ: C

Постфиксный унарный оператор ++:

  1. Возвращает значение (0)
  2. Инкрементирует значение (теперь число равно 1)

Префиксный унарный оператор ++:

  1. Инкрементирует значение (число теперь равно 2)
  2. Возвращает значение (2)

Результат: 0 2 2.


17. Что будет в консоли?
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
Ответ

Ответ: B

При использовании шаблонных строк первым аргументом всегда будет массив строковых значений. Оставшимися аргументами будут значения переданных выражений!


18. Что будет в консоли?
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: Хмм.. Кажется, у тебя нет возраста.
Ответ

Ответ: C

В операциях сравнения примитивы сравниваются по их значениям, а объекты по ссылкам. JavaScript проверяет, чтобы объекты указывали на одну и ту же область памяти.

Сравниваемые объекты в нашем примере не такие: объект, переданный в качестве параметра, указывает на другую область памяти, чем объекты, используемые в сравнениях.

Поэтому { age: 18 } === { age: 18 } и { age: 18 } == { age: 18 } возвращают false.


19. Что будет в консоли?
function getAge(...args) {
  console.log(typeof args);
}

getAge(21);
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"
Ответ

Ответ: C

Оператор распространения (...args) возвращает массив с аргументами. Массив это объект, поэтому typeof args возвращает "object".


20. Что будет в консоли?
function getAge() {
  'use strict';
  age = 21;
  console.log(age);
}

getAge();
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError
Ответ

Ответ: C

Используя "use strict", можно быть уверенным, что мы по ошибке не побъявим глобальные переменные. Мы ранее нигде не объявляли переменную age, поэтому с использованием "use strict" возникнет ReferenceError. Без использования "use strict" ошибки не возникнет, а переменная age добавится в глобальный объект.


21. Чему будет равно sum?
const sum = eval('10*10+5');
  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10*10+5"
Ответ

Ответ: A

eval выполняет код, переданный в виде строки. Если это выражение (как в данном случае), то вычисляется выражение. Выражение 10 * 10 + 5 вернет число 105.


22. Как долго будет доступен cool_secret?
sessionStorage.setItem('cool_secret', 123);
  • A: Всегда, данные не потеряются.
  • B: Пока пользователь не закроет вкладку.
  • C: Пока пользователь не закроет браузер, а не только вкладку.
  • D: Пока пользователь не выключит компьютер.
Ответ

Ответ: B

Данные, сохраненные в sessionStorage очищаются после закрытия вкладки.

При использовании localStorage данные сохраняются навсегда. Очистить их можно, например, используя localStorage.clear().


23. Что будет в консоли?
var num = 8;
var num = 10;

console.log(num);
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError
Ответ

Ответ: B

С помощью ключевого слова var можно определять сколько угодно переменных с одним и тем же именем. Переменная будет хранить последнее присвоенное значение.

Но такой трюк нельзя проделать с let и const, т.к. у них блочная область видимости.


24. Каким будет результат?
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
Ответ

Ответ: C

Все ключи объектов (кроме Symbols) являются строками, даже если заданы не в виде строк. Поэтому obj.hasOwnProperty('1') так же возвращает true.

Но это не работает для set. Значения '1' нет в set: set.has('1') возвращает false. Но set.has(1) вернет true.


25. Что будет в консоли?
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
Ответ

Ответ: C

Если есть два ключа с одинаковым именем, то ключ будет перезаписан. Его позиция сохранится, но значением будет последнее указанное.


26. Глобальный контекст исполнения создает две вещи: глобальный объект и this
  • A: Да
  • B: Нет
  • C: Это зависит от ...
Ответ

Ответ: A

Базовый контекст исполнения это глобальный контекст исполнения: это то, что доступно где угодно в твоем коде.


27. Что будет в консоли?
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
Ответ

Ответ: C

Оператор continue пропускает итерацию, если условие возвращает true.


28. Каким будет результат?
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
Ответ

Ответ: A

String это встроенный конструктор, к которому можно добавлять свойства. Я добавила метод к его прототипу. Строки-примитивы автоматически конвертируются к строкам-объектам. Поэтому все строки (строковые объекты) имеют доступ к этому методу!


29. Что будет в консоли?
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
Ответ

Ответ: B

Ключи объекта автоматически конвертируются в строки. Мы собираемся добавить объект в качестве ключа к объекту a со значением 123.

Тем не менее, когда мы приводим объект к строке, он становится "[object Object]". Таким образом, мы говорим, что a["object Object"] = 123. Потом мы делаем то же самое. c это другой объект, который мы неявно приводим к строке. Поэтому a["object Object"] = 456.

Затем, когда мы выводим a[b], мы имеем в виду a["object Object"]. Мы только что установили туда значение 456, поэтому в результате получаем 456.


30. Каким будет результат?
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
Ответ

Ответ: B

Мы вызываем функцию setTimeout первой. Тем не менее, она выводится в консоль последней

Это происходит из-за того, что в браузерах у нас есть не только рантайм движок, но и WebAPI. WebAPI предоставляет нам функцию setTimeout и много других возможностей. Например, DOM.

После того как коллбек отправлен в WebAPI, функция setTimeout (но не коллбек!) вынимается из стека.

Теперь вызывается foo, и "First" выводится в консоль.

foo достается из стека, и вызывается baz. "Third" выводится в консоль.

WebAPI не может добавлять содержимое в стек когда захочет. Вместо этого он отправляет коллбек-функцию в так называемую очередь.

Здесь на сцену выходит цикл событий (event loop). Event loop проверяет стек и очередь задач. Если стек пустой, то он берет первый элемент из очереди и отправляет его в стек.

Вызывается bar, в консоль выводится "Second" и эта функция достается из стека.


31. Что будет в event.target после клика на кнопку?
<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: Массив со всеми вложенными элементами
Ответ

Ответ: C

Целью события является самый глубокий вложенный элемент. Остановить распространение событий можно с помощью event.stopPropagation


32. Что будет в консоли после клика по параграфу?
<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Кликни меня!
  </p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div
Ответ

Ответ: A

После клика по p будет выведено p и div. В цикле жизни события есть три фазы: захват, цель и всплытие. По умолчанию обработчики событий выполняются на фазе всплытия (если не установлен параметр useCapture в true). Всплытие идет с самого глубокого элемента вверх.


33. Что будет в консоли?
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
Ответ

Ответ: D

В обоих случаях мы передаем объект, на который будет указывать this. Но .call выполняется сразу же!

.bind возвращает копию функции, но с привязанным контекстом. Она не выполняется незамедлительно.


34. Каким будет результат?
function sayHi() {
  return (() => 0)();
}

console.log(typeof sayHi());
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"
Ответ

Ответ: B

Функция sayHi возвращает значение, возвращаемое из немедленно вызываемого функционального выражения (IIFE). Результатом является 0 типа "number".

Для информации: в JS 8 встроенных типов: null, undefined, boolean, number, string, object, symbol и bigint. "function" не является отдельным типом, т.к. функции являются объектами типа "object".


35. Какие из этих значений являются "ложными"?
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: Все являются "ложными"
Ответ

Ответ: A

Есть только восемь (8) "ложных" значений:

  • undefined
  • null
  • NaN
  • false
  • '' (пустая строка)
  • 0
  • -0
  • 0n (BigInt(0))

Конструкторы функций, такие как new Number и new Boolean являются "истинными".


36. Что будет в консоли
console.log(typeof typeof 1);
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"
Ответ

Ответ: B

typeof 1 возвращает "number". typeof "number" возвращает "string"


37. Что будет в консоли?
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
Ответ

Ответ: C

Когда в массив добавляется значение, которое выходит за пределы длины массива, JavaScript создает так называемые "пустые ячейки". На самом деле они имеют значения undefined, но в консоли выводятся так:

[1, 2, 3, 7 x empty, 11]

в зависимости от окружения (может отличаться для браузеров, Node, и т.д.).


38. Что будет в консоли?
(() => {
  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
Ответ

Ответ: A

Блок catch получает аргумент x. Это не тот же x, который определен в качестве переменной перед строкой try {

Затем мы присваиваем этому аргументу значение 1 и устанавливаем значение для переменной y. Потом выводим в консоль значение аргумента x, которое равно 1.

За пределами блока catch переменная x все еще undefined, а y равно 2. Когда мы вызываем console.log(x) за пределами блока catch, этот вызов возвращает undefined, а y возвращает 2.


39. Всё в JavaScript это...
  • A: примитив или объект
  • B: функция или объект
  • C: вопрос с подвохом! только объекты
  • D: число или объект
Ответ

Ответ: A

В JavaScript есть только примитивы и объекты.

Типы примитивов: boolean, null, undefined, bigint, number, string, и symbol.

Отличием примитива от объекта является то, что примитивы не имеют свойств или методов. Тем не менее, 'foo'.toUpperCase() преобразуется в 'FOO' и не вызывает TypeError. Это происходит потому, что при попытке получения свойства или метода у примитива (например, строки), JavaScript неявно обернет примитив объектом, используя один из классов-оберток (например, String), а затем сразу же уничтожит обертку после вычисления выражения. Все примитивы кроме null и undefined ведут себя таким образом.


40. Каким будет результат?
[[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]
Ответ

Ответ: 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].


41. Каким будет результат?
!!null;
!!'';
!!1;
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false
Ответ

Ответ: B

null - "ложный". !null возвращает true. !true возвращает false.

"" - "ложный". !"" возвращает true. !true возвращает false.

1 - "истинный". !1 возвращает false. !false возвращает true.


42. Что возвращает метод setInterval в браузере?
setInterval(() => console.log('Hi'), 1000);
  • A: уникальный id
  • B: указанное количество миллисекунд
  • C: переданную функцию
  • D: undefined
Ответ

Ответ: A

Это метод возвращает уникальный id. Этот id может быть использован для очищения интервала с помощью функции clearInterval().


43. Каким будет результат?
[...'Lydia'];
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]
Ответ

Ответ: A

Строка является итерируемой сущностью. Оператор распространения преобразовывает каждый символ в отдельный элемент.


44. Каким будет результат?
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
Ответ

Ответ: 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.


45. Каким будет результат?
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: "один" "два"
Ответ

Ответ: B

Когда мы передаем несколько промисов методу Promise.race, он разрешает/отклоняет первый промис, который разрешается/отклоняется. В метод setTimeout мы передаем таймер: 500 мс для первого промиса (firstPromise) и 100 мс для второго промиса (secondPromise). Это означает, что secondPromise разрешается первым со значением 'два'. res теперь содержит значение 'два', которое выводиться в консоль.


46. Каким будет результат?
let person = { name: 'Lydia' };
const members = [person];
person = null;

console.log(members);
  • A: null
  • B: [null]
  • C: [{}]
  • D: [{ name: "Lydia" }]
Ответ

Ответ: D

Сначала мы объявляем переменную person со значением объекта, у которого есть свойство name.

Затем мы объявляем переменную с именем members. Мы устанавливаем первый элемент этого массива равным значению переменной person. Объекты взаимодействуют посредством ссылок при установке их равными друг другу. Когда вы назначаете ссылку из одной переменной в другую, вы создаете копию этой ссылки. (обратите внимание, что у них не одинаковые ссылки!)

Затем мы присваиваем переменной person значение null.

Мы изменили только значение переменной person, а не первый элемент в массиве, поскольку этот элемент имеет другую (скопированную) ссылку на объект. Первый элемент в members по-прежнему содержит ссылку на исходный объект. Когда мы выводим в консоль массив members, первый элемент по-прежнему содержит значение объекта, который выводится в консоль.


47. Каким будет результат?
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]
Ответ

Ответ: B

С помощью цикла for-in мы можем перебирать ключи объекта, в данном случае name и age. Под капотом ключи объекта являются строками (если они не являются Symbol). В каждом цикле мы устанавливаем значение item равным текущему ключу, по которому он перебирается. Сначала, item равен name, и выводится в консоль. Затем item равен age, который выводится в консоль.


48. Каким будет результат?
console.log(3 + 4 + '5');
  • A: "345"
  • B: "75"
  • C: 12
  • D: "12"
Ответ

Ответ: B

Ассоциативность операторов - это порядок, в котором компилятор оценивает выражения, слева направо или справа налево. Это происходит только в том случае, если все операторы имеют одинаковый приоритет. У нас есть только один тип оператора: +. Кроме того, ассоциативность слева направо.

3 + 4 оценивается первым. Это приводит к числу 7.

7 + '5' приводит к "75" из-за принуждения. JavaScript преобразует число 7 в строку, см. вопрос 15. Мы можем объединить две строки, используя оператор +. "7" + "5" приводит к "75".


49. Какое значение num?
const num = parseInt("7*6", 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN
Ответ

Ответ: C

Только первые числа в строке возвращаются. На основе системы счисления (второй аргумент, чтобы указать, к какому типу чисел мы хотим его анализировать: основание 10, шестнадцатеричное, восьмеричное, двоичное и т.д.), ParseInt проверяет, являются ли символы в строке допустимыми. Как только он встречает символ, который не является допустимым числом в основании, он прекращает синтаксический анализ и игнорирует следующие символы.

* не является допустимым числом. Он только разбирает "7" в десятичную 7. num теперь содержит значение 7.


50. Каким будет результат?
[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 ]
Ответ

Ответ: C

При использовании метода map, значение num равно элементу, над которым он в данный момент зацикливается. В этом случае элементы являются числами, поэтому условие оператора if typeof num === "number" возвращает true. Функция map создает новый массив и вставляет значения, возвращаемые функцией.

Однако мы не возвращаем значение. Когда мы не возвращаем значение из функции, функция возвращает значение undefined. Для каждого элемента в массиве вызывается функциональный блок, поэтому для каждого элемента мы возвращаем undefined.


51. Каким будет результат?
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"
Ответ

Ответ: A

Аргументы передаются значением, если их значение не является объектом, то они передаются ссылкой. birthYear передается по значению, поскольку это строка, а не объект. Когда мы передаем аргументы по значению, создается копия этого значения (см. вопрос 46).

Переменная birthYear имеет ссылку на значение "1997". Аргумент year также имеет ссылку на значение"1997", но это не то же самое значение, на которое имеется ссылка для birthYear. Когда мы обновляем значение year, устанавливая year равным "1998", мы обновляем только значение year. birthYear по-прежнему равно "1997".

Значение person является объектом. Аргумент member имеет (скопированную) ссылку на тот же объект. Когда мы изменяем свойство объекта, на который member ссылается, значение person также будет изменено, поскольку они оба имеют ссылку на один и тот же объект. Свойство name объекта person теперь равно значению "Lydia".


52. Каким будет результат?
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!
Ответ

Ответ: D

С помощью оператора throw мы можем создавать собственные ошибки. С этим оператором вы можете генерировать исключения. Исключением может быть строка, число, логическое значение или объект. В этом случае нашим исключением является строка 'Hello world'.

С помощью оператора catch мы можем указать, что делать, если в блоке try выдается исключение. Исключение: строка 'Hello world'. e теперь равно той строке, которую мы записываем. Это приводит к 'Oh no an error: Hello world'.


53. Каким будет результат?
function Car() {
  this.make = 'Lamborghini';
  return { make: 'Maserati' };
}

const myCar = new Car();
console.log(myCar.make);
  • A: "Lamborghini"
  • B: "Maserati"
  • C: ReferenceError
  • D: TypeError
Ответ

Ответ: B

Когда вы возвращаете свойство, значение свойства равно возвращаемому значению, а не значению, установленному в функции конструктора. Мы возвращаем строку "Maserati", поэтому myCar.make равно "Maserati".


54. Каким будет результат?
(() => {
  let x = (y = 10);
})();

console.log(typeof x);
console.log(typeof y);
  • A: "undefined", "number"
  • B: "number", "number"
  • C: "object", "number"
  • D: "number", "undefined"
Ответ

Ответ: A

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".


55. Какой будет вывод?
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
Ответ

Ответ: A

Мы можем удалить свойства из объектов, используя ключевое слово delete, также в прототипе. Удаляя свойство в прототипе, оно больше не доступно в цепочке прототипов. В этом случае функция bark больше не доступна в прототипе послеdelete Dog.prototype.bark, но мы все еще пытаемся получить к ней доступ.

Когда мы пытаемся вызвать что-то, что не является функцией, выдается TypeError. В этом случае TypeError: pet.bark не является функцией, поскольку pet.bark является undefined.


56. Какой будет вывод?
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}
Ответ

Ответ: D

Объект Set является коллекцией unique значений: значение может появляться только один раз в наборе.

Мы передали последовательность [1, 1, 2, 3, 4] с повторяющимся значением 1. Поскольку в наборе не может быть двух одинаковых значений, одно из них удаляется. Это приводит к {1, 2, 3, 4}.


57. Какой будет вывод?
// 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
Ответ

Ответ: C

Импортированный модуль является read-only: вы не можете изменить импортированный модуль. Только модуль, который их экспортирует, может изменить его значение.

Когда мы пытаемся увеличить значение myCounter, выдается ошибка: myCounter доступен только для чтения и не может быть изменен.


58. Какой будет вывод?
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
Ответ

Ответ: A

Оператор delete возвращает логическое значение: true при успешном удалении, иначе он вернет false. Однако переменные, объявленные с ключевым словом var, const или let, не могут быть удалены с помощью оператора delete.

Переменная name была объявлена ​​с ключевым словом const, поэтому ее удаление не было успешным: возвращается false. Когда мы устанавливаем age равным 21, мы фактически добавляем свойство с именем age к глобальному объекту. Вы можете успешно удалить свойства из объектов, в том числе из глобального объекта, поэтому delete age возвращает true.


59. Какой будет вывод?
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]
Ответ

Ответ: C

Мы можем распаковать значения из массивов или свойств из объектов путем деструктуризации. Например:

[a, b] = [1, 2];

Значение a теперь равно 1, а значение b теперь равно 2. Что мы на самом деле сделали в этом вопросе, так это:

[y] = [1, 2, 3, 4, 5];

Это означает, что значение y равно первому значению в массиве, которое является числом 1. Когда мы регистрируем y, возвращается 1.


60. Какой будет вывод?
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 }
Ответ

Ответ: B

Можно комбинировать объекты с помощью оператора распространения .... Это позволяет создавать копии пар ключ/значение одного объекта и добавлять их в другой объект. В этом случае мы создаем копии объекта user и добавляем их в объект admin. Объект admin теперь содержит скопированные пары ключ/значение, что приводит к {admin: true, name: "Lydia", age: 21}.


61. Какой будет вывод?
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"]
Ответ

Ответ: B

С помощью метода defineProperty мы можем добавлять новые свойства к объекту или изменять существующие. Когда мы добавляем свойство к объекту с помощью метода defineProperty, они по умолчанию не перечисляемые. Метод Object.keys возвращает все имена enumerable свойств объекта, в данном случае только "name".

Свойства, добавленные с помощью метода defineProperty, по умолчанию неизменны. Вы можете переопределить это поведение, используя свойства writable, configurable и enumerable. Таким образом, метод defineProperty дает вам гораздо больший контроль над свойствами, которые вы добавляете к объекту.


62. Какой будет вывод?
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}"
Ответ

Ответ: A

Второй аргумент JSON.stringify - это replacer. Заменитель может быть либо функцией, либо массивом, и позволяет вам контролировать, что и как должны быть преобразованы в значения.

Если заменитель является массивом, только свойства, имена которых включены в массив, будут добавлены в строку JSON. В этом случае включаются только свойства с именами "level" и "health", "username" исключается. data теперь равен "{"level":19, "health":90}".

Если заменитель является function, эта функция вызывается для каждого свойства объекта, который вы преобразуете. Значение, возвращаемое из этой функции, будет значением свойства при добавлении в строку JSON. Если значение равно undefined, это свойство исключается из строки JSON.


63. Какой будет вывод?
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
Ответ

Ответ: A

Унарный оператор ++ сначала возвращает значение операнда, затем приращивает значение операнда. Значение num1 равно 10, так как функция увеличений вначале возвращает значение num, которое равно 10, и только затем увеличивает значение num.

num2 - это 10, так как мы передали num1 в incpasePassedNumber. number равно 10 (значение num1. Опять же, унарный оператор ++ сначала возвращает значение операнда, затем увеличивает значение операнда. Значение number равно 10, поэтому num2 равно 10.


64. Какой будет вывод?
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
Ответ

Ответ: C

В 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.


65. Какой будет вывод?
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
  • A: 1 2, 3 3 и 6 4
  • B: 1 2, 2 3 и 3 4
  • C: 1 undefined, 2 undefined, 3 undefined и 4 undefined
  • D: 1 2, undefined 3 и undefined 4
Ответ

Ответ: D

Первым аргументом, который получает метод reduce, является аккумулятором, в данном случае x. Второй аргумент - это текущее значение, y. С помощью метода reduce мы выполняем функцию обратного вызова для каждого элемента в массиве, что в конечном итоге может привести к единственному значению.

В этом примере мы не возвращаем никаких значений, мы просто регистрируем значения аккумулятора и текущее значение.

Значение аккумулятора равно ранее возвращенному значению функции обратного вызова. Если вы не передадите необязательный аргумент initialValue методу reduce, аккумулятор будет равен первому элементу при первом вызове.

При первом вызове аккумулятор (x) равен 1, а текущее значение (y) равно 2. Мы не возвращаемся из функции обратного вызова, мы регистрируем аккумулятор и текущее значение: 1 и 2 регистрируются.

Если вы не возвращаете значение из функции, она возвращает значение undefined. При следующем вызове аккумулятор равен undefined, а текущее значение равно 3. undefined и 3 будут зарегистрированы.

При четвертом вызове мы снова не возвращаемся из функции обратного вызова. Аккумулятор снова равен undefined, а текущее значение равно 4. undefined и 4 будут зарегистрированы.


66. С помощью какого конструктора мы можем успешно расширить класс Dog?
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
Ответ

Ответ: B

В производном классе вы не можете получить доступ к ключевому слову this до вызова super. Если вы попытаетесь это сделать, он выдаст ReferenceError: 1 и 4 приведут к ошибке ссылки.

С ключевым словом super мы вызываем конструктор родительского класса с заданными аргументами. Конструктор родителя получает аргумент name, поэтому нам нужно передать name в super.

Класс Labrador получает два аргумента: name, поскольку он расширяет Dog, и size в качестве дополнительного свойства класса Labrador. Они оба должны быть переданы в функцию конструктора в Labrador, что делается правильно с помощью конструктора 2.


67. Какой будет вывод?
// 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
Ответ

Ответ: B

С ключевым словом import все импортируемые модули являются pre-parsed. Это означает, что импортированные модули запускаются первыми, код в файле, который импортирует модуль, исполняется после.

В этом разница между require() в CommonJS и import! С помощью require() вы можете загружать зависимости по требованию во время выполнения кода. Если бы мы использовали require вместо import, в консоль были бы записаны running index.js, running sum.js, 3.


68. Какой будет вывод?
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
Ответ

Ответ: A

Каждый Symbol совершенно уникален. Цель аргумента, переданного Symbol, состоит в том, чтобы дать Symbol описание. Значение Symbol не зависит от переданного аргумента. Когда мы проверяем равенство, мы создаем два совершенно новых Symbol: первый Symbol('foo') и второй Symbol('foo'). Эти два значения уникальны и не равны друг другу, Symbol('foo') === Symbol('foo') возвращает false.


69. Какой будет вывод?
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",
Ответ

Ответ: C

С помощью метода padStart мы можем добавить отступ в начало строки. Значение, передаваемое этому методу, представляет собой общую длину строки вместе с отступом. Строка "Lydia Hallie" имеет длину 12. name.padStart(13) вставляет 1 пробел в начале строки, потому что 12 + 1 равно 13.

Если аргумент, переданный методу padStart, меньше длины строки, заполнение не будет добавлено.


70. Какой будет вывод?
console.log("🥑" + "💻");
  • A: "🥑💻"
  • B: 257548
  • C: Строка, содержащая кодовые обозначения
  • D: Error
Ответ

Ответ: A

С помощью оператора + вы можете объединять строки. В этом случае мы объединяем строку "🥑" со строкой "💻", что приводит к "🥑💻".


71. Как мы можем вывести в лог значения, которые закомментированы после оператора console.log?
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").value и game.next().value
  • B: game.next.value("Yes") и game.next.value()
  • C: game.next().value и game.next("Yes").value
  • D: game.next.value() и game.next.value("Yes")
Ответ

Ответ: C

Функция генератора "приостанавливает" выполнение, когда видит ключевое слово 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 ❤️, регистрируется.


72. Какой будет вывод?
console.log(String.raw`Hello\nworld`);
  • A: Hello world!
  • B: Hello
         world
  • C: Hello\nworld
  • D: Hello\n
         world
Ответ

Ответ: C

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, которая и выводится.


73. Какой будет вывод?
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
Ответ

Ответ: C

Асинхронная функция всегда возвращает обещание. await все еще должен ждать разрешения обещания: ожидаемое обещание возвращается, когда мы вызываем getData(), чтобы установить data равным ему.

Если бы мы хотели получить доступ к разрешенному значению "I made it", мы могли бы использовать метод .then() для data:

data.then(res => console.log(res))

Тогда это бы вывело "I made it!"


74. Какой будет вывод?
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
Ответ

Ответ: B

Метод .push() возвращает длину нового массива! Ранее массив содержал один элемент (строка "banana") и имел длину 1. После добавления в массив строки "apple", массив содержит два элемента и имеет длину 2. Это возвращается из функции addToList.

Метод push изменяет исходный массив. Если вы хотите вернуть массив из функции, а не длину массива, вы должны были вернуть list после добавления в нее item.


75. Какой будет вывод?
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
Ответ

Ответ: B

Object.freeze делает невозможным добавление, удаление или изменение свойств объекта (если только значение свойства не является другим объектом).

Когда мы создаем переменную shape и устанавливаем ее равной замороженному объекту box, shape также ссылается на замороженный объект. Вы можете проверить, заморожен ли объект, используя Object.isFrozen. В этом случае Object.isFrozen(shape) возвращает true, поскольку переменная shape имеет ссылку на замороженный объект.

Поскольку shape заморожен, и поскольку значение x не является объектом, мы не можем изменить свойство x. x по-прежнему равно 10, и {x: 10, y: 20} регистрируется.


76. Какой будет вывод?
const { firstName: myName } = { firstName: 'Lydia' };

console.log(firstName);
  • A: "Lydia"
  • B: "myName"
  • C: undefined
  • D: ReferenceError
Ответ

Ответ: D

Используя деструктурирующее присваивание, мы можем распаковывать значения из массивов или свойства из объектов в отдельные переменные:

const { firstName } = { firstName: 'Lydia' };
// Версия ES5:
// var firstName = { firstName: 'Lydia' }.firstName;

console.log(firstName); // "Lydia"

Также свойство можно распаковать из объекта и присвоить переменной с именем, отличным от имени свойства объекта:

const { firstName: myName } = { firstName: 'Lydia' };
// Версия ES5:
// var myName = { firstName: 'Lydia' }.firstName;

console.log(myName); // "Lydia"
console.log(firstName); // Тут будет ошибка Uncaught ReferenceError: firstName is not defined

В этом случае firstName не существует как переменная, поэтому попытка доступа к ее значению вызовет ReferenceError.

Примечание. Помните о свойствах глобальной области видимости:

const { name: myName } = { name: 'Lydia' };

console.log(myName); // "lydia"
console.log(name); // "" ----- Браузер, например, Chrome
console.log(name); // ReferenceError: name is not defined  ----- NodeJS

Всякий раз, когда Javascript не может найти переменную в текущей области видимости, то поднимается вверх по цепочке областей видимости и ищет ее на каждом уровне, и если достигает области верхнего уровня, также известной как Глобальная область, и все еще не находит нужной ссылки, то выдает ReferenceError.

  • В браузерах, таких как Chrome, name является устаревшим свойством глобальной области. В этом примере код выполняется внутри глобальной области и нет определяемой пользователем локальной переменной name, поэтому интерпретатор ищет предопределенные переменные/свойства в глобальной области видимости, что в случае браузеров происходит через объект window и возвращается значение window.name, которое равно пустой строке.

  • В NodeJS такого свойства в "глобальном" объекте нет, поэтому попытка доступа к несуществующей переменной вызовет ReferenceError.


77. Это чистая функция?
function sum(a, b) {
  return a + b;
}
  • A: Да
  • B: Нет
Ответ

Ответ: A

Чистая функция - это функция, которая всегда возвращает тот же результат, если переданы одинаковые аргументы.

Функция sum всегда возвращает один и тот же результат. Если мы передадим 1 и 2, он всегда вернет 3 без побочных эффектов. Если мы передадим 5 и 10, он всегда вернет 15 и так далее. Это определение чистой функции.


78. Какой будет вывод?
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! 20 Calculated! 20 Calculated! 20
  • B: Calculated! 20 From cache! 20 Calculated! 20
  • C: Calculated! 20 From cache! 20 From cache! 20
  • D: Calculated! 20 From cache! 20 Error
Ответ

Ответ: C

Функция 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' регистрируется.


79. Какой будет вывод?
const myLifeSummedUp = ['☕', '💻', '🍷', '🍫']

for (let item in myLifeSummedUp) {
  console.log(item)
}

for (let item of myLifeSummedUp) {
  console.log(item)
}
  • A: 0 1 2 3 и "☕" "💻" "🍷" "🍫"
  • B: "☕" "💻" "🍷" "🍫" и "☕" "💻" "🍷" "🍫"
  • C: "☕" "💻" "🍷" "🍫" и 0 1 2 3
  • D: 0 1 2 3 и {0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
Ответ

Ответ: A

С помощью цикла for-in мы можем перебирать перечисляемые свойства. В массиве перечисляемые свойства являются "ключами" элементов массива, которые фактически являются их индексами. Вы можете увидеть массив как:

{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}

Где ключи - перечисляемые свойства. 0 1 2 3 войти в систему.

С помощью цикла for-of мы можем выполнять итерацию итераций. Массив является итеративным. Когда мы выполняем итерацию по массиву, переменная "item" равна элементу, по которому она итерируется в данный момент, "☕" "💻" "🍷" "🍫" выводится в лог.


80. Какой будет вывод?
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]
Ответ

Ответ: C

Элементы массива могут содержать любые значения. Числа, строки, объекты, другие массивы, ноль, логические значения, неопределенные и другие выражения, такие как даты, функции и вычисления.

Элемент будет равен возвращаемому значению. 1 + 2 вернет 3, 1 * 2 вернет 2, а 1 / 2 вернет 0.5.


81. Какой будет вывод?
function sayHi(name) {
  return `Hi there, ${name}`
}

console.log(sayHi())
  • A: Hi there,
  • B: Hi there, undefined
  • C: Hi there, null
  • D: ReferenceError
Ответ

Ответ: B

По умолчанию аргументы имеют значение undefined, если только значение не было передано функции. В этом случае мы не передали значение для аргумента name. name равно логгируемому undefined.

В ES6 мы можем перезаписать значение по умолчанию undefined параметрами по умолчанию. Например:

function sayHi(name = "Lydia") { ... }

В этом случае, если мы не передали значение или если мы передали undefined, name всегда будет равно строке Lydia


82. Какой будет вывод?
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: "😎" и "😎"
Ответ

Ответ: B

Значение ключевого слова this зависит от того, где вы его используете. В методе, как и в методе getStatus, ключевое слово this ссылается на объект, которому принадлежит метод. Метод принадлежит объекту data, поэтому this относится к объекту data. Когда мы регистрируем this.status, регистрируется свойство status объекта data, которое является "🥑".

С помощью метода call мы можем изменить объект, на который ссылается ключевое слово this. В функциях ключевое слово this относится к объекту, которому принадлежит функция. Мы объявили функцию setTimeout для объекта global, поэтому в функции setTimeout ключевое слово this ссылается на объект global. В глобальном объекте есть переменная с именем status со значением "😎". При регистрации this.status выводится "😎".


83. Какой будет вывод?
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"
Ответ

Ответ: A

Мы устанавливаем переменную city равной значению свойства с именем city для объекта person. У этого объекта нет свойства с именем city, поэтому переменная city имеет значение undefined.

Обратите внимание, что мы не ссылаемся на сам объект person! Мы просто устанавливаем переменную city равной текущему значению свойства city объекта person.

Затем мы устанавливаем city равным строке "Amsterdam". Это не меняет объект person - нет ссылки на этот объект.

При регистрации объекта person возвращается неизмененный объект.


84. Какой будет вывод?
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
Ответ

Ответ: C

Переменные с ключевыми словами const и let имеют блочную видимость. Блок - это что-то между фигурными скобками ({}). В этом случае в фигурных скобках операторов if/else. Вы не можете ссылаться на переменную за пределами блока, в котором она объявлена, вызывается ReferenceError.


85. Какая информация будетвыведена в лог?
fetch('https://www.website.com/api/user/1')
  .then(res => res.json())
  .then(res => console.log(res))
  • A: Результат метода fetch.
  • B: Результат второго вызова метода fetch.
  • C: Результат коллбэка в предыдущем .then().
  • D: Всегда будет undefined.
Ответ

Ответ: C

Значение res во втором .then равно возвращенному значению предыдущего .then. Вы можете продолжать цепочку .then таким образом; значение передается следующему обработчику.


86. Какая опция позволяет установить hasName равным true, если вы не можете передатьtrue в качестве аргумента?
function getName(name) {
  const hasName = //
}
  • A: !!name
  • B: name
  • C: new Boolean(name)
  • D: name.length
Ответ

Ответ: A

С помощью !!name мы определяем, является ли значение name истинным или ложным. Если имя истинное, которое мы хотим проверить, то !name возвращает false. А !false (это то, чем на самом деле является !! name) возвращает true.

Устанавливая hasName равным name, вы устанавливаете hasName равным любому значению, которое вы передали функции getName, а не логическому значению true.

new Boolean (true) возвращает объектную оболочку, а не само логическое значение.

name.length возвращает длину переданного аргумента, независимо от того, является ли он true.


87. Какой будет вывод?
console.log('I want pizza'[0])
  • A: """
  • B: "I"
  • C: SyntaxError
  • D: undefined
Ответ

Ответ: B

Чтобы получить символ по определенному индексу в строке, вы можете использовать скобочную нотацию. Первый символ в строке имеет индекс 0 и т.д. В этом случае мы хотим получить элемент с индексом 0, символ 'I', который выводится в лог.

Обратите внимание, что этот метод не поддерживается в IE7 и ниже. В этом случае используйте .charAt()


88. Какой будет вывод?
function sum(num1, num2 = num1) {
  console.log(num1 + num2)
}

sum(10)
  • A: NaN
  • B: 20
  • C: ReferenceError
  • D: undefined
Ответ

Ответ: B

Вы можете установить значение параметра по умолчанию равным другому параметру функции, если они были определены до параметров по умолчанию. Мы передаем значение 10 в функцию sum. Если функция sum принимает только один аргумент, это означает, что значение для num2 не передано, и в этом случае значение num1 равно переданному значению 10. Значением по умолчанию num2 является значение num1, которое равно 10. num1 + num2 возвращает 20.

Если вы пытаетесь установить значение параметра по умолчанию равным параметру, который определен после (справа), то значение параметра еще не было инициализировано; это приведет к ошибке.


89. Какой будет вывод?
// module.js
export default () => 'Hello world'
export const name = 'Lydia'

// index.js
import * as data from './module'

console.log(data)
  • A: { default: function default(), name: "Lydia" }
  • B: { default: function default() }
  • C: { default: "Hello world", name: "Lydia" }
  • D: Global object of module.js
Ответ

Ответ: A

С синтаксисом import * as name мы импортируем все exports из файла module.js в файл index.js, тогда и создается новый объект с именем data. В файле module.js есть два экспорта: экспорт по умолчанию и именованный экспорт. Экспорт по умолчанию - это функция, которая возвращает строку "Hello World", а именованный экспорт - это переменная с именем name, которая имеет значение строки "Lydia".

Объект data имеет свойство default для экспорта по умолчанию, другие свойства имеют имена именованных экспортов и их соответствующие значения.


90. Какой будет вывод?
class Person {
  constructor(name) {
    this.name = name
  }
}

const member = new Person('John')
console.log(typeof member)
  • A: "class"
  • B: "function"
  • C: "object"
  • D: "string"
Ответ

Ответ: C

Классы являются синтаксическим сахаром для конструкторов функций. Эквивалентом класса Person в качестве конструктора функции будет:

function Person() {
  this.name = name
}

Вызов конструктора функции с new приводит к созданию экземпляра Person, ключевое слово typeof возвращает "object" для экземпляра. typeof member возвращает "object".


91. Какой будет вывод?
let newList = [1, 2, 3].push(4)

console.log(newList.push(5))
  • A: [1, 2, 3, 4, 5]
  • B: [1, 2, 3, 5]
  • C: [1, 2, 3, 4]
  • D: Error
Ответ

Ответ: D

Метод .push возвращает новую длину массива, а не сам массив! Устанавливая newList равным [1, 2, 3].push(4), мы устанавливаем newList равным новой длине массива: 4.

Затем мы пытаемся использовать метод .push для newList. Поскольку newList является числовым значением 4, мы не можем использовать метод .push: выдается ошибка TypeError.


92. Какой будет вывод?
function giveLydiaPizza() {
  return 'Here is pizza!'
}

const giveLydiaChocolate = () =>
  "Here's chocolate... now go hit the gym already."

console.log(giveLydiaPizza.prototype)
console.log(giveLydiaChocolate.prototype)
  • A: { constructor: ...} { constructor: ...}
  • B: {} { constructor: ...}
  • C: { constructor: ...} {}
  • D: { constructor: ...} undefined
Ответ

Ответ: D

Обычные функции, такие как функция giveLydiaPizza, имеют свойство prototype, которое является объектом (прототипом объекта) со свойством constructor. Однако функции со стрелками, такие как функция giveLydiaChocolate, не имеют этого свойства prototype. undefined возвращается при попытке доступа к свойству prototype с использованием giveLydiaChocolate.prototype.


93. Какой будет вывод?
const person = {
  name: 'Lydia',
  age: 21
}

for (const [x, y] of Object.entries(person)) {
  console.log(x, y)
}
  • A: name Lydia and age 21
  • B: ["name", "Lydia"] and ["age", 21]
  • C: ["name", "age"] and undefined
  • D: Error
Ответ

Ответ: A

Object.entries (person) возвращает массив вложенных массивов, содержащий ключи и объекты:

[ [ 'name', 'Lydia' ], [ 'age', 21 ] ]

Используя цикл for-of, мы можем перебирать каждый элемент массива, в данном случае подмассивы. Мы можем мгновенно деструктурировать подмассивы в цикле for, используя const [x, y]. x равен первому элементу в подмассиве, y равен второму элементу в подмассиве.

Первым подмассивом является [ "name", "Lydia" ], где x равно "name", и y равно "Lydia", которые выводятся в лог. Вторым подмассивом является [ "age", 21 ], где x равно "age", и y равно 21, которые выводятся в лог.


94. Какой будет вывод?
function getItems(fruitList, ...args, favoriteFruit) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")
  • A: ["banana", "apple", "pear", "orange"]
  • B: [["banana", "apple"], "pear", "orange"]
  • C: ["banana", "apple", ["pear"], "orange"]
  • D: SyntaxError
Ответ

Ответ: D

... args - прочие параметры. Значение прочих параметров - это массив, содержащий все оставшиеся аргументы и может быть передан только последним! В этом примере прочие параметры были вторым аргументом. Это невозможно, и это приведет к синтаксической ошибке.

function getItems(fruitList, favoriteFruit, ...args) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")

Приведенный выше пример работает. Это возвращает массив [ 'banana', 'apple', 'orange', 'pear' ]


95. Какой будет вывод?
function nums(a, b) {
  if (a > b) console.log('a is bigger')
  else console.log('b is bigger')
  return
    a + b;
}

console.log(nums(4, 2))
console.log(nums(1, 2))
  • A: a is bigger, 6 and b is bigger, 3
  • B: a is bigger, undefined and b is bigger, undefined
  • C: undefined and undefined
  • D: SyntaxError
Ответ

Ответ: B

В JavaScript мы не должны явно указывать точку с запятой (;), однако движок JavaScript все равно добавляет их после операторов. Это называется автоматической вставкой точек с запятой. Например, оператором могут быть переменные или ключевые слова, такие как throw, return, break и т.д.

Здесь мы написали инструкцию return и другое значение a + b в новой строке. Однако, поскольку это новая линия, движок не знает, что это на самом деле значение, которое мы хотели бы вернуть. Вместо этого он автоматически добавляет точку с запятой после return. Вы можете увидеть это как:

  return;
  a + b

Это означает, что a + b никогда не достигается, так как функция перестает выполняться после ключевого слова return. Если значение не возвращается, как здесь, функция возвращает значение undefined. Обратите внимание, что после операторов if / else автоматической вставки нет!


96. Какой будет вывод?
class Person {
  constructor() {
    this.name = 'Lydia'
  }
}

Person = class AnotherPerson {
  constructor() {
    this.name = 'Sarah'
  }
}

const member = new Person()
console.log(member.name)
  • A: "Lydia"
  • B: "Sarah"
  • C: Error: cannot redeclare Person
  • D: SyntaxError
Ответ

Ответ: B

Мы можем установить классы равными другим классам/конструкторам функций. В этом случае мы устанавливаем Person равным AnotherPerson. Свойство name этого конструктора - Sarah, поэтому свойство name для нового экземпляра класса Person member - это Sarah.


97. Какой будет вывод?
const info = {
  [Symbol('a')]: 'b'
}

console.log(info)
console.log(Object.keys(info))
  • A: {Symbol('a'): 'b'} and ["{Symbol('a')"]
  • B: {} and []
  • C: { a: "b" } and ["a"]
  • D: {Symbol('a'): 'b'} and []
Ответ

Ответ: D

Symbol не является перечисляемый. Метод Object.keys возвращает все перечисляемые свойства ключа для объекта. Symbol не просматривается таким образом, и возвращается пустой массив. При регистрации всего объекта будут видны все свойства, даже не перечисляемые.

Это одно из многих качеств символа: помимо представления совершенно уникального значения (которое предотвращает случайное столкновение имен в объектах, например, при работе с 2 библиотеками, которые хотят добавить свойства к одному и тому же объекту), вы также можете "скрыть" свойства объектов таким образом (хотя и не полностью. Вы можете получить доступ к символам, используя метод Object.getOwnPropertySymbols()).


98. Какой будет вывод?
const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name, age: user.age }

const list = [1, 2, 3, 4]
const user = { name: "Lydia", age: 21 }

console.log(getList(list))
console.log(getUser(user))
  • A: [1, [2, 3, 4]] and undefined
  • B: [1, [2, 3, 4]] and { name: "Lydia", age: 21 }
  • C: [1, 2, 3, 4] and { name: "Lydia", age: 21 }
  • D: Error and { name: "Lydia", age: 21 }
Ответ

Ответ: A

Функция getList получает массив в качестве аргумента. Между скобками функции getList мы сразу же деструктурируем этот массив. Вы можете увидеть это как:

[x, ...y] = [1, 2, 3, 4]

С помощью оставшихся параметров ... y мы помещаем все "оставшиеся" аргументы в массив. Остальные аргументы - это 2, 3 и 4 в этом случае. Значение y является массивом, содержащим все остальные параметры. В этом случае значение x равно 1, поэтому, мы видим в логе [x, y], [1, [2, 3, 4]].

Функция getUser получает объект. В стрелочных функциях нам не нужно писать фигурные скобки, если мы просто возвращаем одно значение. Однако, если вы хотите мгновенно вернуть object из стрелочной функции, вы должны написать его между круглыми скобками, иначе все, что находится между двумя фигурными скобками, будет интерпретироваться как оператор блока. В этом случае код между фигурными скобками не является допустимым кодом JavaScript, поэтому выдается SyntaxError.

Следующая функция вернула бы объект:

const getUser = user => ({ name: user.name, age: user.age })


99. Какой будет вывод?
const name = 'Lydia'

console.log(name())
  • A: SyntaxError
  • B: ReferenceError
  • C: TypeError
  • D: undefined
Ответ

Ответ: C

Переменная name содержит значение строки, которая не является функцией, поэтому не может вызываться.

Ошибки типа выдаются, когда значение не соответствует ожидаемому типу. JavaScript ожидал, что name будет функцией, так как мы пытаемся вызвать ее. Однако это была строка, поэтому выдается ошибка TypeError: name не является функцией!

Синтаксические ошибки генерируются, когда вы написали что-то, что не является допустимым JavaScript, например, когда вы написали слово return как retrun. ReferenceErrors генерируется, когда JavaScript не может найти ссылку на значение, к которому вы пытаетесь получить доступ.


100. Какое значение будет на выходе?
// 🎉✨ This is my 100th question! ✨🎉

const output = `${[] && 'Im'}possible!
You should${'' && `n't`} see a therapist after so much JavaScript lol`
  • A: possible! You should see a therapist after so much JavaScript lol
  • B: Impossible! You should see a therapist after so much JavaScript lol
  • C: possible! You shouldn't see a therapist after so much JavaScript lol
  • D: Impossible! You shouldn't see a therapist after so much JavaScript lol
Ответ

Ответ: B

[] - истинное значение. С оператором && будет возвращено правое значение, если левое значение является истинным значением. В этом случае левое значение [] является истинным значением, поэтому возвращается 'Im'.

"" - ложное значение. Если левое значение ложно, ничего не возвращается. n't не возвращается.


101. Какое значение будет на выходе?
const one = (false || {} || null)
const two = (null || false || '')
const three = ([] || 0 || true)

console.log(one, two, three)
  • A: false null []
  • B: null "" true
  • C: {} "" []
  • D: null null true
Ответ

Ответ: C

С помощью оператора || мы можем вернуть первый истинный операнд. Если все значения ложны, последний операнд возвращается.

(false || {} || null): пустой объект {} является истинным значением. Это первое (и единственное) истинное значение, которое возвращается. one содержит {}.

(null || false || ""): все операнды являются ложными значениями. Это означает, что прошедший операнд "" возвращается. two содержит "".

([] || 0 || ""): пустой массив [] является истинным значением. Это первое истинное значение, которое возвращается. three присвоено [].


102. Какое значение будет на выходе?
const myPromise = () => Promise.resolve('I have resolved!')

function firstFunction() {
  myPromise().then(res => console.log(res))
  console.log('second')
}

async function secondFunction() {
  console.log(await myPromise())
  console.log('second')
}

firstFunction()
secondFunction()
  • A: I have resolved!, second and I have resolved!, second
  • B: second, I have resolved! and second, I have resolved!
  • C: I have resolved!, second and second, I have resolved!
  • D: second, I have resolved! and I have resolved!, second
Ответ

Ответ: D

С обещанием мы в основном говорим: "Я хочу выполнить эту функцию и откладываю ее, пока она выполняется, поскольку это может занять некоторое время. Только когда определенное значение разрешено (или отклонено), и когда стек вызовов пуст, я хочу использовать это значение".

Мы можем получить это значение с помощью ключевого слова .then и await в функции async. Хотя мы можем получить значение обещания с помощью .then и await, они работают немного по-разному.

В firstFunction мы (вроде) отложили функцию myPromise во время ее работы, но продолжили выполнение другого кода, в данном случае console.log ('second'). Затем функция разрешается строкой I have resolved, которая затем логируется после того, как она увидела, что стек вызовов пуст.

Используя ключевое слово await в secondFunction, мы буквально приостанавливаем выполнение асинхронной функции до тех пор, пока значение не будет разрешено до перехода на следующую строку.

Это означает, что мы ожидали разрешения myPromise со значением I have resolved, и только когда это произошло, мы перешли к следующей строке: second была выведена в консоль последней.


103. Какое значение будет на выходе?
const set = new Set()

set.add(1)
set.add('Lydia')
set.add({ name: 'Lydia' })

for (let item of set) {
  console.log(item + 2)
}
  • A: 3, NaN, NaN
  • B: 3, 7, NaN
  • C: 3, Lydia2, [object Object]2
  • D: "12", Lydia2, [object Object]2
Ответ

Ответ: C

Оператор + используется не только для добавления числовых значений, но мы также можем использовать его для объединения строк. Всякий раз, когда движок JavaScript видит, что одно или несколько значений не являются числом, он приводит число к строке.

Первым является 1, который является числовым значением. 1 + 2 возвращает число 3.

Тем не менее, вторая строка "Lydia". "Lydia" является строкой, а 2 является числом: 2 приводится к строке. "Lydia" и "2" объединяются, что приводит к результирующей строке "Lydia2".

{name: "Lydia"} является объектом. Ни число, ни объект не являются строкой, поэтому они приводятся к строке. Всякий раз, когда мы приводим обычный объект, он становится "[object Object]". "[object Object]", объединенный с "2", становится "[object Object]2".


104. Чему равно значение?
Promise.resolve(5)
  • A: 5
  • B: Promise {<pending>: 5}
  • C: Promise {<fulfilled>: 5}
  • D: Error
Ответ

Ответ: C

Мы можем передать любой тип значения, которое мы хотим, в Promise.resolve, либо обещание, либо не обещание. Сам метод возвращает обещание с разрешенным значением (<fulfilled>). Если вы передадите обычную функцию, это будет разрешенное обещание с обычным значением. Если вы передадите обещание, это будет разрешенное обещание с разрешенным значением этого пройденного обещания.

В этом случае мы просто передали числовое значение 5. Возвращается разрешенное обещание со значением 5.


105. Чему равно значение?
function compareMembers(person1, person2 = person) {
  if (person1 !== person2) {
    console.log('Not the same!')
  } else {
    console.log('They are the same!')
  }
}

const person = { name: 'Lydia' }

compareMembers(person)
  • A: Not the same!
  • B: They are the same!
  • C: ReferenceError
  • D: SyntaxError
Ответ

Ответ: B

Объекты передаются по ссылке. Когда мы проверяем объекты на строгое равенство (===), мы сравниваем их ссылки.

Мы устанавливаем значение по умолчанию для person2, равное объекту person, и передаем объект person в качестве значения для person1.

Это означает, что оба значения имеют ссылку на одно и то же место в памяти, поэтому они равны.

Блок кода в операторе else запускается, и в лог выводится They are the same!.


106. Чему равно значение?
const colorConfig = {
  red: true,
  blue: false,
  green: true,
  black: true,
  yellow: false,
}

const colors = ['pink', 'red', 'blue']

console.log(colorConfig.colors[1])
  • A: true
  • B: false
  • C: undefined
  • D: TypeError
Ответ

Ответ: D

В JavaScript у нас есть два способа доступа к свойствам объекта: нотация в скобках или нотация в точках. В этом примере мы используем точечную нотацию (colorConfig.colors) вместо скобочной нотации (colorConfig["colors"]).

В точечной нотации JavaScript пытается найти свойство объекта с таким точным именем. В этом примере JavaScript пытается найти свойство с именем colors в объекте colorConfig. Не существует свойства с именем colors, поэтому возвращается undefined. Затем мы пытаемся получить доступ к значению первого элемента, используя [1]. Мы не можем сделать это для значения, которое undefined, поэтому оно выдает TypeError: Cannot read свойство '1' of undefined.

JavaScript интерпретирует (или распаковывает) операторы. Когда мы используем скобочные обозначения, он видит первую открывающую скобку [ и продолжает работать, пока не найдет закрывающую скобку ]. Только тогда он оценит утверждение. Если бы мы использовали colorConfig[colors [1]], он бы возвратил значение свойства red объекта colorConfig.


107. Чему равно значение?
console.log('❤️' === '❤️')
  • A: true
  • B: false
Ответ

Ответ: A

Под капотом смайлики - это юникоды. Юникод для сердца смайликов "U+2764 U+FE0F". Они всегда одинаковы для одного и того же смайлика, поэтому мы сравниваем две одинаковые строки друг с другом, что возвращает true.


108. Какой из этих методов модифицирует исходный массив?
const emojis = ['✨', '🥑', '😍']

emojis.map(x => x + '✨')
emojis.filter(x => x !== '🥑')
emojis.find(x => x !== '🥑')
emojis.reduce((acc, cur) => acc + '✨')
emojis.slice(1, 2, '✨') 
emojis.splice(1, 2, '✨')
  • A: All of them
  • B: map reduce slice splice
  • C: map slice splice
  • D: splice
Ответ

Ответ: D

Используя метод splice, мы модифицируем исходный массив, удаляя, заменяя или добавляя элементы. В этом случае мы удалили 2 элемента из индекса 1 (мы удалили '🥑' и '😍') и добавили emoji.

map, filter и slice возвращают новый массив, find возвращает элемент, а reduce возвращает аккумулированное значение.


109. Какое значение будет на выходе?
const food = ['🍕', '🍫', '🥑', '🍔']
const info = { favoriteFood: food[0] }

info.favoriteFood = '🍝'

console.log(food)
  • A: ['🍕', '🍫', '🥑', '🍔']
  • B: ['🍝', '🍫', '🥑', '🍔']
  • C: ['🍝', '🍕', '🍫', '🥑', '🍔']
  • D: ReferenceError
Ответ

Ответ: A

Мы устанавливаем значение свойства favourFood для объекта info равным строке со смайликами для пиццы, '🍕'. Строка является примитивным типом данных. В JavaScript примитивные типы данных передаются по ссылке ...

В JavaScript примитивные типы данных (все, что не является объектом) передаются как значение. В этом случае мы устанавливаем значение свойства favourFood объекта info равным значению первого элемента в массиве food, в данном случае это строка с emoji пиццы ('🍕'). Строка является примитивным типом данных и взаимодействует по значению (см. мой пост в блоге, если вы заинтересованы в получении дополнительной информации).

Затем мы меняем значение свойства favourFood объекта info. Массив food не изменился, поскольку значение favourFood было просто скопировано из значения первого элемента в массиве и не имеет ссылки на то же место в памяти, что и элемент на food[0]. Когда мы выводим в лог food, это все равно исходный массив, ['🍕', '🍫', '🥑', '🍔'].


110. Что делает этот метод?
JSON.parse()
  • A: Разбирает JSON в значение JavaScript
  • B: Разбирает объект JavaScript в JSON
  • C: Разбирает любое значение JavaScript в JSON
  • D: Разбирает JSON непосредственно в объект JavaScript
Ответ

Ответ: A

С помощью метода JSON.parse () мы можем разобрать строку JSON в значение JavaScript.

// Преобразование числа в допустимый JSON, затем преобразование строки JSON в значение JavaScript:
const jsonNumber = JSON.stringify(4) // '4'
JSON.parse(jsonNumber) // 4

// Преобразование значения массива в допустимый JSON, затем разбор строки JSON в значение JavaScript:
const jsonArray = JSON.stringify([1, 2, 3]) // '[1, 2, 3]'
JSON.parse(jsonArray) // [1, 2, 3]

// Преобразование объекта в допустимый JSON, затем преобразование строки JSON в значение JavaScript:
const jsonArray = JSON.stringify({ name: 'Lydia' }) // '{"name":"Lydia"}'
JSON.parse(jsonArray) // { name: 'Lydia' }


111. Какое значение будет на выходе?
let name = 'Lydia'

function getName() {
  console.log(name)
  let name = 'Sarah'
}

getName()
  • A: Lydia
  • B: Sarah
  • C: undefined
  • D: ReferenceError
Ответ

Ответ: D

Каждая функция имеет свой собственный контекст исполнения (или область видимости). Функция getName сначала ищет в своем собственном контексте (области видимости), чтобы увидеть, содержит ли она переменную name, к которой мы пытаемся получить доступ. В этом случае функция getName содержит собственную переменную name: мы объявляем переменную name с ключевым словом let и значением 'Sarah'.

Переменные с ключевым словом letconst) поднимаются в начало функции, в отличие от var, которые не инициализируется. Они недоступны до того, как мы объявим (инициализируем) их строку. Это называется "временной мертвой зоной". Когда мы пытаемся получить доступ к переменным до их объявления, JavaScript выдает ReferenceError.

Если бы мы не объявили переменную name в функции getName, движок javascript посмотрел бы вниз по цепочки области действия. Внешняя область имеет переменную с именем name со значением Lydia. В этом случае он бы записал Lydia.

let name = 'Lydia'

function getName() {
  console.log(name)
}

getName() // Lydia


112. Какое значение будет на выходе?
function* generatorOne() {
  yield ['a', 'b', 'c'];
}

function* generatorTwo() {
  yield* ['a', 'b', 'c'];
}

const one = generatorOne()
const two = generatorTwo()

console.log(one.next().value)
console.log(two.next().value)
  • A: a and a
  • B: a and undefined
  • C: ['a', 'b', 'c'] and a
  • D: a and ['a', 'b', 'c']
Ответ

Ответ: C

Используя ключевое слово yield, мы получаем значения в функции генератора. С помощью ключевого слова yield* мы можем получить значения из другой функции-генератора или итерируемого объекта (например, массива).

В generatorOne мы получаем весь массив ['a', 'b', 'c'], используя ключевое слово yield. Значение свойства value для объекта, возвращаемого методом next для one (one.next().value), равно всему массиву ['a', 'b', 'c'].

console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined

В файле generatorTwo мы используем ключевое слово yield*. Это означает, что первое полученное значение two равно первому полученному значению в итераторе. Итератор - это массив ['a', 'b', 'c']. Первым полученным значением является a, поэтому в первый раз, когда мы вызываем two.next().value, возвращается a.

console.log(two.next().value) // 'a'
console.log(two.next().value) // 'b'
console.log(two.next().value) // 'c'
console.log(two.next().value) // undefined


113. Какое значение будет на выходе?
console.log(`${(x => x)('I love')} to program`)
  • A: I love to program
  • B: undefined to program
  • C: ${(x => x)('I love') to program
  • D: TypeError
Ответ

Ответ: A

Выражения внутри литералов шаблона расчитываются первыми. Это означает, что строка будет содержать возвращаемое значение выражения, в данном случае немедленно исполняемую функцию (x => x)('I love'). Мы передаем значение 'I love' в качестве аргумента стрелочной функции x => x. x равно 'I love', которое и возвращается. Это приводит к I love to program.


114. Что произойдет?
let config = {
  alert: setInterval(() => {
    console.log('Alert!')
  }, 1000)
}

config = null
  • A: обратный вызов setInterval не будет вызван
  • B: обратный вызов setInterval будет вызван один раз
  • C: обратный вызов setInterval будет вызываться каждую секунду
  • D: мы никогда не вызовем config.alert(), т.к. config равно null
Ответ

Ответ: C

Обычно, когда мы устанавливаем объекты равными null, эти объекты получают статус собрано в мусор, так как больше нет ссылок на этот объект. Однако, поскольку функция обратного вызова внутри setInterval является стрелочной функцией (таким образом, привязанной к объекту config), функция обратного вызова по-прежнему содержит ссылку на объект config. Пока есть ссылка, объект не будет собирать мусор. Так как это интервал, установка config в null или delete-ing config.alert не приведет к сбору мусора для интервала, поэтому интервал все равно будет вызываться. Его следует очистить с помощью clearInterval(config.alert), чтобы удалить его из памяти. Поскольку он не был очищен, функция обратного вызова setInterval будет по-прежнему вызываться каждые 1000мс (1с).


115. Какие методы вернут значение 'Hello world!'?
const myMap = new Map()
const myFunc = () => 'greeting'

myMap.set(myFunc, 'Hello world!')

//1
myMap.get('greeting')
//2
myMap.get(myFunc)
//3
myMap.get(() => 'greeting')
  • A: 1
  • B: 2
  • C: 2 и 3
  • D: Каждый из них
Ответ

Ответ: B

При добавлении пары ключ/значение с использованием метода set имя ключа будет равно значению первого аргумента, переданного в функцию set, а значением будет второй аргумент, переданный в функцию set. В данном случае ключом является функция () => 'greeting' и значение 'Hello world'. myMap теперь это { () => 'greeting' => 'Hello world!' }.

1 неверно, поскольку ключ не 'greeting', а () => 'greeting'. 3 неверно, так как мы создаем новую функцию, передавая ее в качестве параметра методу get. Объект взаимодействует со ссылкой. Функции - это объекты, поэтому две функции никогда не бывают строго равными, даже если они идентичны: они имеют ссылки на разные места в памяти.


116. Какое значение будет на выходе?
const person = {
  name: 'Lydia',
  age: 21
}

const changeAge = (x = { ...person }) => x.age += 1
const changeAgeAndName = (x = { ...person }) => {
  x.age += 1
  x.name = 'Sarah'
}

changeAge(person)
changeAgeAndName()

console.log(person)
  • A: {name: "Sarah", age: 22}
  • B: {name: "Sarah", age: 23}
  • C: {name: "Lydia", age: 22}
  • D: {name: "Lydia", age: 23}
Ответ

Ответ: C

Функции changeAge и changeAgeAndName имеют параметр по умолчанию, а именно вновь созданный объект { ...person }. Этот объект имеет копии всех ключей/значений объекта person.

Сначала мы вызываем функцию changeAge и передаем объект person в качестве аргумента. Эта функция увеличивает значение свойства age на 1. person теперь {name: "Lydia", age: 22}.

Затем мы вызываем функцию changeAgeAndName, однако мы не передаем параметр. Вместо этого значение x равно новому объекту: { ... person }. Поскольку это новый объект, он не влияет на значения свойств объекта person. person по-прежнему равен {name: "Lydia", age: 22}.


117. Какой из следующих наборов параметров вернет 6?
function sumValues(x, y, z) {
	return x + y + z;
}
  • A: sumValues([...1, 2, 3])
  • B: sumValues([...[1, 2, 3]])
  • C: sumValues(...[1, 2, 3])
  • D: sumValues([1, 2, 3])
Ответ

Ответ: C

С помощью оператора распространения (spread) ... мы можем распределить итерации в отдельньные элементы. sumValues принимает три аргумента:x, y и z. ...[1, 2, 3] приведет к перечню 1, 2, 3, который мы передаем функции sumValues.


118. Что будет на выходе?
let num = 1;
const list = ["🥳", "🤠", "🥰", "🤪"];

console.log(list[(num += 1)]);
  • A: 🤠
  • B: 🥰
  • C: SyntaxError
  • D: ReferenceError
Ответ

Ответ: B

С операндом += мы увеличиваем значение num на 1. num имеет начальное значение 1, поэтому 1 + 1 равно 2. Элементом второго индекса в массиве list и является вывод console.log (list [2])🥰.


119. Что будет на выходе?
const person = {
	firstName: 'Lydia',
	lastName: 'Hallie',
	pet: {
		name: 'Mara',
		breed: 'Dutch Tulip Hound'
	},
	getFullName() {
		return `${this.firstName} ${this.lastName}`;
	}
};

console.log(person.pet?.name);
console.log(person.pet?.family?.name);
console.log(person.getFullName?.());
console.log(member.getLastName?.());
  • A: undefined undefined undefined undefined
  • B: Mara undefined Lydia Hallie undefined
  • C: Mara null Lydia Hallie null
  • D: null ReferenceError null ReferenceError
Ответ

Ответ: B

С необязательным оператором связывания ?. нам больше не нужно явно проверять, действительны ли более глубокие вложенные значения или нет. Если мы пытаемся получить доступ к свойству со (нулевым) значением undefined или null, выражение замыкается и возвращает undefined.

person.pet?.name: person имеет свойство с именем pet: person.pet не нулевое. Оно имеет свойство с именем name, и возвращает Mara. person.pet?.family?.name: person имеет свойство с именем pet: person.pet не нулевое. pet не имеет свойство с именем family, person.pet.family нулевое. Выражение возвращает undefined. person.getFullName?.(): person имеет свойство с именем getFullName: person.getFullName() не нулевое, и может быть вызвано, возвращает Lydia Hallie. member.getLastName?.(): member не определено: member.getLastName() нулевое. Выражение возвращает undefined.


120. Что будет на выходе?
const groceries = ['banana', 'apple', 'peanuts'];

if (groceries.indexOf('banana')) {
	console.log('We have to buy bananas!');
} else {
	console.log(`We don't have to buy bananas!`);
}
  • A: We have to buy bananas!
  • B: We don't have to buy bananas
  • C: undefined
  • D: 1
Ответ

Ответ: B

Мы передали условие groceries.indexOf("banana") в оператор if. groceries.indexOf("banana") возвращает 0, что является ложным значением. Поскольку условие в операторе if ложно, выполняется код в блоке else, и в лог выводится We don't have to buy bananas!.


121. Что будет на выходе?
const config = {
	languages: [],
	set language(lang) {
		return this.languages.push(lang);
	}
};

console.log(config.language);
  • A: function language(lang) { this.languages.push(lang }
  • B: 0
  • C: []
  • D: undefined
Ответ

Ответ: D

Метод language является сеттером. Сеттеры не содержат действительного значения, их целью является изменение свойств. При вызове метода setter возвращается undefined.


122. Что будет на выходе?
const name = 'Lydia Hallie';

console.log(!typeof name === 'object');
console.log(!typeof name === 'string');
  • A: false true
  • B: true false
  • C: false false
  • D: true true
Ответ

Ответ: C

typeof name возвращает "строку". Строка "string" является истинным значением, поэтому !typeof name возвращает логическое значение false. false === "object" и false === "string" оба возвращают false.

(Если бы мы хотели проверить, был ли тип (не)равен определенному типу, мы должны были написать !== вместо !typeof)


123. Что будет на выходе?
const add = x => y => z => {
	console.log(x, y, z);
	return x + y + z;
};

add(4)(5)(6);
  • A: 4 5 6
  • B: 6 5 4
  • C: 4 function function
  • D: undefined undefined 6
Ответ

Ответ: A

Функция add возвращает стрелочную функцию, которая возвращает стрелочную функцию, которая возвращает стрелочную функцию (все еще тут?). Первая функция получает аргумент x со значением 4. Мы вызываем вторую функцию, которая получает аргумент y со значением 5. Затем мы вызываем третью функцию, которая получает аргумент z со значением 6. Когда мы пытаемся получить доступ к значениям x, y и z в функции последней стрелки, движок JS поднимается вверх по цепочке областей видимости, чтобы найти значения для x и y соответственно. Это возвращает 4 5 6.


124. Что будет на выходе?
async function* range(start, end) {
	for (let i = start; i <= end; i++) {
		yield Promise.resolve(i);
	}
}

(async () => {
	const gen = range(1, 3);
	for await (const item of gen) {
		console.log(item);
	}
})();
  • A: Promise {1} Promise {2} Promise {3}
  • B: Promise {<pending>} Promise {<pending>} Promise {<pending>}
  • C: 1 2 3
  • D: undefined undefined undefined
Ответ

Ответ: C

Функция генератора range возвращает асинхронный объект с обещаниями для каждого элемента в диапазоне, который мы передаем: Promise {1}, Promise {2}, Promise {3}. Мы устанавливаем переменную gen равной асинхронному объекту, после чего зацикливаем ее, используя цикл for await ... of. Мы устанавливаем переменную item равной возвращаемым значениям Promise: сначала Promise {1}, затем Promise {2}, затем Promise {3}. Так как мы ожидаем значение item, разрешается обещание, возвращаются разрешенные значения обещания: 1, 2, затем 3.


125. Что будет на выходе?
const myFunc = ({ x, y, z }) => {
	console.log(x, y, z);
};

myFunc(1, 2, 3);
  • A: 1 2 3
  • B: {1: 1} {2: 2} {3: 3}
  • C: { 1: undefined } undefined undefined
  • D: undefined undefined undefined
Ответ

Ответ: D

myFunc ожидает объект со свойствами x, y и z в качестве аргумента. Поскольку мы передаем только три отдельных числовых значения (1, 2, 3) вместо одного объекта со свойствами x, y и z ({x: 1, y: 2, z: 3}), то x, y и z имеют значение по умолчанию undefined.


126. Что будет на выходе?
function getFine(speed, amount) {
  const formattedSpeed = new Intl.NumberFormat({
    'en-US',
    { style: 'unit', unit: 'mile-per-hour' }
  }).format(speed)

  const formattedAmount = new Intl.NumberFormat({
    'en-US',
    { style: 'currency', currency: 'USD' }
  }).format(amount)

  return `The driver drove ${formattedSpeed} and has to pay ${formattedAmount}`
}

console.log(getFine(130, 300))
  • A: The driver drove 130 and has to pay 300
  • B: The driver drove 130 mph and has to pay $300.00
  • C: The driver drove undefined and has to pay undefined
  • D: The driver drove 130.00 and has to pay 300.00
Ответ

Ответ: B

С помощью метода Intl.NumberFormat мы можем форматировать числовые значения в любой локали. Мы форматируем числовое значение 130 для локали en-US как unit в mile-per-hour, что приводит к 130 mph. Числовое значение 300 для локали en-US в качестве currentcy в USD приводит к $300.00.


127. Что будет на выходе?
const spookyItems = ["👻", "🎃", "🕸"];
({ item: spookyItems[3] } = { item: "💀" });

console.log(spookyItems);
  • A: ["👻", "🎃", "🕸"]
  • B: ["👻", "🎃", "🕸", "💀"]
  • C: ["👻", "🎃", "🕸", { item: "💀" }]
  • D: ["👻", "🎃", "🕸", "[object Object]"]
Ответ

Ответ: B

Деструктурируя объекты, мы можем распаковать значения из правого объекта и присвоить распакованному значению значение того же по имени свойства в левом объекте. В этом случае мы присваиваем значение "💀" spookyItems[3]. Это означает, что мы модифицируем массив spookyItems, добавляем к нему «💀». При логировании spookyItems выводится ["👻", "🎃", "🕸", "💀"].


128. Что будет на выходе?
const name = "Lydia Hallie";
const age = 21;

console.log(Number.isNaN(name));
console.log(Number.isNaN(age));

console.log(isNaN(name));
console.log(isNaN(age));
  • A: true false true false
  • B: true false false false
  • C: false false true false
  • D: false true false true
Ответ

Ответ: C

С помощью метода Number.isNaN вы можете проверить, является ли передаваемое вами значение числовым значением и равно ли оно NaN. name не является числовым значением, поэтому Number.isNaN(name) возвращает false. age является числовым значением, но не равно NaN, поэтому Number.isNaN(age) возвращает false.

С помощью метода isNaN вы можете проверить, не является ли передаваемое вами значение числом. name не является числом, поэтому isNaN(name) возвращает true. age - это число, поэтому isNaN(age) возвращает false.


129. Что будет на выходе?
const randomValue = 21;

function getInfo() {
	console.log(typeof randomValue);
	const randomValue = 'Lydia Hallie';
}

getInfo();
  • A: "number"
  • B: "string"
  • C: undefined
  • D: ReferenceError
Ответ

Ответ: D

Переменные, объявленные с ключевым словом const, не имеют ссылки до их инициализации: это называется временная мертвая зона. В функции getInfo переменная randomValue находится в области видимости getInfo. В строке, где мы хотим записать значение typeof randomValue, переменная randomValue еще не инициализирована: выдается ReferenceError! Движок не пошел по цепочке областей видимости, так как мы объявили переменную randomValue в функции getInfo.


130. Что будет на выходе?
const myPromise = Promise.resolve('Woah some cool data');

(async () => {
	try {
		console.log(await myPromise);
	} catch {
		throw new Error(`Oops didn't work`);
	} finally {
		console.log('Oh finally!');
	}
})();
  • A: Woah some cool data
  • B: Oh finally!
  • C: Woah some cool data Oh finally!
  • D: Oops didn't work Oh finally!
Ответ

Ответ: C

В блоке try мы выводим в лог ожидаемое значение переменной myPromise: "Woah some cool data". Поскольку в блоке try не было выдано никаких ошибок, код в блоке catch не запускается. Код в блоке finally всегда выполняется, "Oh finally!" также выводится в лог.


131. Что будет на выходе?
const emojis = ['🥑', ['✨', '✨', ['🍕', '🍕']]];

console.log(emojis.flat(1));
  • A: ['🥑', ['✨', '✨', ['🍕', '🍕']]]
  • B: ['🥑', '✨', '✨', ['🍕', '🍕']]
  • C: ['🥑', ['✨', '✨', '🍕', '🍕']]
  • D: ['🥑', '✨', '✨', '🍕', '🍕']
Ответ

Ответ: B

С помощью метода flat мы можем создать новый плоский массив. Глубина уплощенного массива зависит от значения, которое мы передаем. В этом случае мы передали значение 1 (которое нам не нужно, это значение по умолчанию), что означает, что будут объединены только массивы на первой глубине. ['🥑'] и ['✨', '✨', ['🍕', '🍕']] в этом случае. Конкатенация этих двух массивов приводит к ['🥑', '✨', '✨', ['🍕', '🍕']].


132. Что будет на выходе?
class Counter {
  constructor() {
    this.count = 0;
  }

  increment() {
    this.count++;
  }
}

const counterOne = new Counter();
counterOne.increment();
counterOne.increment();

const counterTwo = counterOne;
counterTwo.increment();

console.log(counterOne.count);
  • A: 0
  • B: 1
  • C: 2
  • D: 3
Ответ

Ответ: D

counterOne экземпляр класса Counter. Counter класс содержит метод increment и свойство count в конструкторе. Сперва, при помощи counterOne.increment(), мы дважды вызываем метод increment. counterOne.count становится 2.

Затем, мы создаем новую переменную counterTwo, и присваиваем ей counterOne. Поскольку объекты передаются по ссылке, мы просто создаем новую ссылку на то же место в памяти, на которое указывает counterOne. Поскольку переменные ссылаются на то же место в памяти, любые изменения, внесенные в объект, на который ссылается counterTwo, также применяются к counterOne. Теперь counterTwo.count равно 2.

Мы вызываем counterTwo.increment(), что устанавливает значение count равное 3. Затем мы выводим в консоль значение переменной counterOne, которое равно 3.


133. Что будет на выходе?
const myPromise = Promise.resolve(Promise.resolve('Promise!'));

function funcOne() {
  myPromise.then(res => res).then(res => console.log(res));
  setTimeout(() => console.log('Timeout!', 0));
  console.log('Last line!');
}

async function funcTwo() {
  const res = await myPromise;
  console.log(await res);
  setTimeout(() => console.log('Timeout!', 0));
  console.log('Last line!');
}

funcOne();
funcTwo();
  • A: Promise! Last line! Promise! Last line! Last line! Promise!
  • B: Last line! Timeout! Promise! Last line! Timeout! Promise!
  • C: Promise! Last line! Last line! Promise! Timeout! Timeout!
  • D: Last line! Promise! Promise! Last line! Timeout! Timeout!
Ответ

Ответ: D

Сначала мы вызываем funcOne. В первой строке funcOne мы вызываем асинхронную функцию setTimeout, из которой обратный вызов отправляется в веб-API. (см. мою статью о цикле событий здесь.)

Затем мы вызываем обещание myPromise, которое является асинхронной операцией.

И обещание, и тайм-аут являются асинхронными операциями, функция продолжает работать, пока она занята выполнением обещания и обработкой обратного вызова setTimeout. Это означает, что Last line 1! регистрируется первой, так как это не асинхронная операция.

Поскольку стек вызовов еще не пуст, функция setTimeout и обещание в funcOne еще не могут быть добавлены в стек вызовов.

В funcTwo переменная res получает Promise, потому что Promise.resolve(Promise.resolve('Promise')) эквивалентно Promise.resolve('Promise'), так как разрешение обещания просто разрешает его стоимость. await в этой строке останавливает выполнение функции до тех пор, пока она не получит разрешение промиса, а затем продолжает работать синхронно до завершения, поэтому Promise 2!, а затем Last line 2! регистрируются, а setTimeout отправляется в Web API.

Тогда стек вызовов пуст. Промисы — это микрозадачи, поэтому они решаются первыми, когда стек вызовов пуст, поэтому Promise 1! регистрируется.

Теперь, поскольку funcTwo выталкивается из стека вызовов, стек вызовов пуст. Обратные вызовы, ожидающие в очереди (() => console.log("Timeout 1!") из funcOne, и () => console.log("Timeout 2!") из funcTwo) добавляются в стек вызовов один за другим. Первый обратный вызов регистрирует Timeout 1! и удаляется из стека. Затем второй обратный вызов регистрирует Timeout 2! и удаляется из стека.


134. Как мы можем вызвать функцию sum в sum.js из index.js?
// sum.js
export default function sum(x) {
  return x + x;
}

// index.js
import * as sum from './sum';
  • A: sum(4)
  • B: sum.sum(4)
  • C: sum.default(4)
  • D: Нельзя импортировать значения по умолчанию используя *, только именованные экспорты
Ответ

Ответ: C

Используя звездочку *, мы импортируем все экспортируемые значения из файла, включая именнованные экспорты и экспорты по умолчанию. Если бы у нас был следующий файл:

// 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);

В лог попадёт следующее:

{
  default: 'I love JavaScript',
  name: 'Lydia',
  age: 21
}

Для примера sum это означает, что импортированное значение sum будет таким:

{ default: function sum(x) { return x + x } }

Следовательно, мы можем вызвать эту функцию используя sum.default


135. Что будет на выходе?
const handler = {
  set: () => console.log('Added a new property!'),
  get: () => console.log('Accessed a property!'),
};

const person = new Proxy({}, handler);

person.name = 'Lydia';
person.name;
  • A: Added a new property!
  • B: Accessed a property!
  • C: Added a new property! Accessed a property!
  • D: В лог ничего не попадёт
Ответ

Ответ: C

C помощью Proxy мы можем добавить собственное поведению объекту, которое мы передаем вторым аргументом. В нашем случае мы передаем объект handler который содержит свойства: set и get. set вызывается каждый раз когда мы устанавливаем значения свойств, get же вызывается всякий раз когда мы получаем значения свойств.

Первый аргумент — пустой объект {}, который является значением person. Для него будет добавлено собственное поведение, описанное в объекте handler. При добавлении значения для объекта person будет вызвано свойство set. При запросе к значению person вызовется свойство get.

Сначала мы устанавливаем новое свойство name для объекта Proxy (person.name = "Lydia"). Вызывается set и в лог попадает "Added a new property!".

Затем мы обращаемся к значению Proxy-объекта. Вызывается свойство get объекта handler. "Accessed a property!" попадает в лог.


136. Какое из перечисленных действий может модифицировать объект person?
const person = { name: 'Lydia Hallie' };

Object.seal(person);
  • A: person.name = "Evan Bacon"
  • B: person.age = 21
  • C: delete person.name
  • D: Object.assign(person, { age: 21 })
Ответ

Ответ: A

С помощью Object.seal мы можем предотвращать как добавление новых свойств, так и удаление существующих.

Однако, изменение существующих свойств остаётся доступным.


137. Какое из перечисленных действий может модифицировать объект person?
const person = {
  name: 'Lydia Hallie',
  address: {
    street: '100 Main St',
  },
};

Object.freeze(person);
  • A: person.name = "Evan Bacon"
  • B: delete person.address
  • C: person.address.street = "101 Main St"
  • D: person.pet = { name: "Mara" }
Ответ

Ответ: C

С помощью метода Object.freeze мы можем заморозить объект. Свойства не могут быть добавлены, изменены или удалены.

Однако, это неглубоко замораживает объект. Замораживаются только непосредственные свойства объекта. Если свойством является другой объект(в нашем примере address), свойства этого объекта не замораживаются и могут быть изменены.


138. Что будет на выходе?
const add = x => x + x;

function myFunc(num = 2, value = add(num)) {
  console.log(num, value);
}

myFunc();
myFunc(3);
  • A: 2 4 and 3 6
  • B: 2 NaN and 3 NaN
  • C: 2 Error and 3 6
  • D: 2 4 and 3 Error
Ответ

Ответ: 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.


139. Что будет на выходе?
class Counter {
  #number = 10

  increment() {
    this.#number++
  }

  getNum() {
    return this.#number
  }
}

const counter = new Counter()
counter.increment()

console.log(counter.#number)
  • A: 10
  • B: 11
  • C: undefined
  • D: SyntaxError
Ответ

Ответ: D

В ES2020 мы можем добавлять приватные переменные в классы с помощью символа #. Мы не можем получить доступ к этим переменным вне класса. Когда мы пытаемся записать counter.#number, выдается SyntaxError: мы не можем получить доступ вне класса Counter!


140. В каком случае не будет ошибки?
const teams = [
  { name: 'Team 1', members: ['Paul', 'Lisa'] },
  { name: 'Team 2', members: ['Laura', 'Tim'] },
];

function* getMembers(members) {
  for (let i = 0; i < members.length; i++) {
    yield members[i];
  }
}

function* getTeams(teams) {
  for (let i = 0; i < teams.length; i++) {
    // ✨ SOMETHING IS MISSING HERE ✨
  }
}

const obj = getTeams(teams);
obj.next(); // { value: "Paul", done: false }
obj.next(); // { value: "Lisa", done: false }
  • A: yield getMembers(teams[i].members)
  • B: yield* getMembers(teams[i].members)
  • C: return getMembers(teams[i].members)
  • D: return yield getMembers(teams[i].members)
Ответ

Ответ: B

Чтобы выполнить итерацию по members в каждом элементе массива teams, нам нужно передать teams[i].members в функцию генератора getMembers. Функция генератора возвращает объект генератора. Чтобы перебрать каждый элемент в этом объекте-генераторе, нам нужно использовать yield*.

Если бы мы написали yield, return yield или return, вся функция генератора была бы возвращена при первом вызове метода next.


141. Что будет на выходе?
const person = {
  name: 'Lydia Hallie',
  hobbies: ['coding'],
};

function addHobby(hobby, hobbies = person.hobbies) {
  hobbies.push(hobby);
  return hobbies;
}

addHobby('running', []);
addHobby('dancing');
addHobby('baking', person.hobbies);

console.log(person.hobbies);
  • A: ["coding"]
  • B: ["coding", "dancing"]
  • C: ["coding", "dancing", "baking"]
  • D: ["coding", "running", "dancing", "baking"]
Ответ

Ответ: 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"]


142. Что будет на выходе?
class Bird {
  constructor() {
    console.log("I'm a bird. 🦢");
  }
}

class Flamingo extends Bird {
  constructor() {
    console.log("I'm pink. 🌸");
    super();
  }
}

const pet = new Flamingo();
  • A: I'm pink. 🌸
  • B: I'm pink. 🌸 I'm a bird. 🦢
  • C: I'm a bird. 🦢 I'm pink. 🌸
  • D: Nothing, we didn't call any method
Ответ

Ответ: B

Мы создаем переменную pet, которая является экземпляром класса Flamingo. Когда мы создаем этот экземпляр, вызывается constructor для Flamingo. Сначала регистрируется "I'm pink. 🌸", после чего мы вызываем super(). super() вызывает конструктор родительского класса Bird. Конструктор в Bird вызывается и регистрирует "I'm a bird. 🦢".


143. Какой/какие из вариантов приведет к ошибке?
const emojis = ['🎄', '🎅🏼', '🎁', '⭐'];

/* 1 */ emojis.push('🦌');
/* 2 */ emojis.splice(0, 2);
/* 3 */ emojis = [...emojis, '🥂'];
/* 4 */ emojis.length = 0;
  • A: 1
  • B: 1 и 2
  • C: 3 и 4
  • D: 3
Ответ

Ответ: D

Ключевое слово const просто означает, что мы не можем повторно объявить значение этой переменной, оно доступно только для чтения. Однако само значение не является неизменным. Свойства массива emojis можно изменить, например, добавив новые значения, объединив их или установив длину массива на 0.


144. Что нам нужно добавить к объекту person, чтобы получить ["Lydia Hallie", 21] в качестве вывода [...person]?
const person = {
  name: "Lydia Hallie",
  age: 21
}

[...person] // ["Lydia Hallie", 21]
  • A: Ничего, объекты итерируется по умолчанию
  • B: *[Symbol.iterator]() { for (let x in this) yield* this[x] }
  • C: *[Symbol.iterator]() { yield* Object.values(this) }
  • D: *[Symbol.iterator]() { for (let x in this) yield this }
Ответ

Ответ: C

По умолчанию объекты не являются итерируемыми. Итерируемым объект становится, если присутствует протокол итератора. Мы можем добавить это вручную, добавив символ итератора [Symbol.iterator], который должен возвращать объект-генератор, например, сделав его функцией-генератором *[Symbol.iterator]() {}. Эта функция-генератор должна возвращать Object.values объекта person, если мы хотим, чтобы он возвращал массив ["Lydia Hallie", 21]: yield* Object.values(this).


145. Что будет на выходе?
let count = 0;
const nums = [0, 1, 2, 3];

nums.forEach(num => {
	if (num) count += 1
})

console.log(count)
  • A: 1
  • B: 2
  • C: 3
  • D: 4
Ответ

Ответ: C

Условие if внутри цикла forEach проверяет, является ли значение num истинным или ложным. Поскольку первое число в массиве nums равно 0, то есть ложное значение, блок оператора if не будет выполнен. count увеличивается только для остальных 3 чисел в массиве nums: 1, 2 и 3. Поскольку count увеличивается на 1 3 раза, значение count равно 3.


146. Что будет на выходе?
function getFruit(fruits) {
	console.log(fruits?.[1]?.[1])
}

getFruit([['🍊', '🍌'], ['🍍']])
getFruit()
getFruit([['🍍'], ['🍊', '🍌']])
  • A: null, undefined, 🍌
  • B: [], null, 🍌
  • C: [], [], 🍌
  • D: undefined, undefined, 🍌
Ответ

Ответ: D

? позволяет нам дополнительно получить доступ к более глубоким вложенным свойствам внутри объектов. Мы пытаемся зарегистрировать элемент с индексом 1 в подмассиве с индексом 1 массива fruits. Если подмассив с индексом 1 в массиве fruits не существует, он просто вернет undefined. Если подмассив с индексом 1 в массиве fruits существует, но в этом подмассиве нет элемента с индексом 1, он также вернет значение undefined.

Во-первых, мы пытаемся зарегистрировать второй элемент в ['🍍'] подмассива [['🍊', '🍌'], ['🍍']]. Этот подмассив содержит только один элемент, что означает, что в индексе 1 нет элемента, и возвращает значение undefined.

Затем мы вызываем функцию getFruits без передачи значения в качестве аргумента, что означает, что fruits по умолчанию имеет значение undefined. Поскольку мы условно связываем элемент с индексом 1 массива fruits, он возвращает значение undefined, поскольку этот элемент с индексом 1 не существует.

Наконец, мы попытаемся зарегистрировать второй элемент в ['🍊', '🍌'] подмассива ['🍍'], ['🍊', '🍌']. Элемент с индексом 1 в этом подмассиве — 🍌, который регистрируется.


147. Что будет на выходе?
class Calc {
	constructor() {
		this.count = 0 
	}

	increase() {
		this.count++
	}
}

const calc = new Calc()
new Calc().increase()

console.log(calc.count)
  • A: 0
  • B: 1
  • C: undefined
  • D: ReferenceError
Ответ

Ответ: A

Мы устанавливаем переменную calc равной новому экземпляру класса Calc. Затем мы создаем экземпляр нового экземпляра Calc и вызываем метод увеличения для этого экземпляра. Поскольку свойство count находится в конструкторе класса Calc, свойство count не используется в прототипе Calc. Это означает, что значение count не было обновлено для экземпляра, на который указывает calc, count по-прежнему равен 0.


148. Что будет на выходе?
const user = {
	email: "[email protected]",
	password: "12345"
}

const updateUser = ({ email, password }) => {
	if (email) {
		Object.assign(user, { email })
	}

	if (password) {
		user.password = password
	}

	return user
}

const updatedUser = updateUser({ email: "[email protected]" })

console.log(updatedUser === user)
  • A: false
  • B: true
  • C: TypeError
  • D: ReferenceError
Ответ

Ответ: B

Функция updateUser обновляет значения свойств email и password у пользователя, если их значения переданы в функцию, после чего функция возвращает объект user. Возвращаемое значение функции updateUser — это объект user, что означает, что значение updatedUser является ссылкой на тот же объект user, на который указывает user. updatedUser === user равно true.


149. Что будет на выходе?
const fruit = ['🍌', '🍊', '🍎']

fruit.slice(0, 1)
fruit.splice(0, 1)
fruit.unshift('🍇')

console.log(fruit)
  • A: ['🍌', '🍊', '🍎']
  • B: ['🍊', '🍎']
  • C: ['🍇', '🍊', '🍎']
  • D: ['🍇', '🍌', '🍊', '🍎']
Ответ

Ответ: C

Во-первых, мы вызываем метод slice для массива фруктов. Метод slice не изменяет исходный массив, а возвращает значение, которое было вырезано из массива: банановый смайлик. Затем мы вызываем метод splice для массива фруктов. Метод splice изменяет исходный массив, что означает, что массив фруктов теперь состоит из ['🍊', '🍎']. Наконец, мы вызываем метод unshift для массива fruit, который изменяет исходный массив, добавляя предоставленное значение, в данном случае 🍇, в качестве первого элемента в массиве. Массив фруктов теперь состоит из ['🍇', '🍊', '🍎'].


150. Что будет на выходе?
const animals = {};
let dog = { emoji: '🐶' }
let cat = { emoji: '🐈' }

animals[dog] = { ...dog, name: "Mara" }
animals[cat] = { ...cat, name: "Sara" }

console.log(animals[dog])
  • A: { emoji: "🐶", name: "Mara" }
  • B: { emoji: "🐈", name: "Sara" }
  • C: undefined
  • D: ReferenceError
Ответ

Ответ: 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: " Сара"}.


151. Что будет на выходе?
const user = {
	email: "[email protected]",
	updateEmail: email => {
		this.email = email
	}
}

user.updateEmail("[email protected]")
console.log(user.email)
Ответ

Ответ: A

Функция updateEmail представляет собой стрелочную функцию и не привязана к объекту пользователя. Это означает, что ключевое слово this не относится к объекту user, а в данном случае относится к глобальной области видимости. Значение email в объекте user не обновляется. При регистрации значения user.email возвращается исходное значение [email protected].


152. Что будет на выходе?
const promise1 = Promise.resolve('First')
const promise2 = Promise.resolve('Second')
const promise3 = Promise.reject('Third')
const promise4 = Promise.resolve('Fourth')

const runPromises = async () => {
	const res1 = await Promise.all([promise1, promise2])
	const res2  = await Promise.all([promise3, promise4])
	return [res1, res2]
}

runPromises()
	.then(res => console.log(res))
	.catch(err => console.log(err))
  • A: [['First', 'Second'], ['Fourth']]
  • B: [['First', 'Second'], ['Third', 'Fourth']]
  • C: [['First', 'Second']]
  • D: 'Third'
Ответ

Ответ: D

Метод Promise.all выполняет переданные промисы параллельно. Если одно обещание не выполняется, метод Promise.all отколняется со значением отклоненного обещания. В этом случае promise3 отклонен со значением "Third". Мы перехватываем отклоненное значение в цепочке методов catch при вызове runPromises, чтобы перехватывать любые ошибки внутри функции runPromises. Только "Third" регистрируется, так как promise3 отклонено с этим значением.


153. Каким должно быть значение method для регистрации { name: "Lydia", age: 22 }?
const keys = ["name", "age"]
const values = ["Lydia", 22]

const method = /* ?? */
Object[method](keys.map((_, i) => {
	return [keys[i], values[i]]
})) // { name: "Lydia", age: 22 }
  • A: entries
  • B: values
  • C: fromEntries
  • D: forEach
Ответ

Ответ: C

Метод fromEntries превращает двумерный массив в объект. Первый элемент в каждом подмассиве будет ключом, а второй элемент в каждом подмассиве будет значением. В этом случае мы сопоставляем массив keys, который возвращает массив, первый элемент которого является элементом массива ключей текущего индекса, а второй элемент является элементом массива значений текущего индекса.

Это создает массив подмассивов, содержащих правильные ключи и значения, что приводит к { name: "Lydia", age: 22 }


154. Что будет на выходе?
const createMember = ({ email, address = {}}) => {
	const validEmail = /.+\@.+\..+/.test(email)
	if (!validEmail) throw new Error("Valid email pls")

	return {
		email,
		address: address ? address : null
	}
}

const member = createMember({ email: "[email protected]" })
console.log(member)
Ответ

Ответ: C

Значением по умолчанию для address является пустой объект {}. Когда мы устанавливаем переменную member равной объекту, возвращаемому функцией createMember, мы не передаем значение для адреса, что означает, что значение адреса является пустым объектом по умолчанию {}. Пустой объект является истинным значением, что означает, что условие address ? address : null условно возвращает true. Значением адреса является пустой объект {}.


155. Что будет на выходе?
let randomValue = { name: "Lydia" }
randomValue = 23

if (!typeof randomValue === "string") {
	console.log("It's not a string!")
} else {
	console.log("Yay it's a string!")
}
  • A: It's not a string!
  • B: Yay it's a string!
  • C: TypeError
  • D: undefined
Ответ

Ответ: B

Условие в операторе if проверяет, равно ли значение !typeof randomValue "строке". Оператор ! преобразует значение в логическое значение. Если значение истинно, возвращаемое значение будет "ложным", если значение ложным, возвращаемое значение будет "истинным". В этом случае возвращаемое значение typeof randomValue является истинным значением "number", что означает, что значение !typeof randomValue является логическим значением false.

!typeof randomValue === "string" всегда возвращает false, поскольку на самом деле мы проверяем false === "string". Поскольку условие вернуло false, запускается блок кода оператора else, и в журнал заносится сообщение Yay it's a string!.