Вопросы по JavaScript. Версия 1
Каким будет вывод?
Вопрос № 1
function sayHi() {
console.log(name)
console.log(age)
var name = "John"
let age = 30
}
sayHi()
- A:
John
иundefined
- B:
John
иError
- C:
Error
- D:
undefined
иError
Ответ
Правильный ответ: D
В функции sayHi
мы сначала определяем переменную name
с помощью ключевого слова var
. Это означает, что name
поднимается в начало функции. name
будет иметь значение undefined
до тех пор, пока выполнение кода не дойдет до строки, где ей присваивается значение John
. Мы еще не определили значение name
, когда пытаемся вывести ее значение в консоль, поэтому получаем undefined
. Переменные, объявленные с помощью ключевых слов let
и const
, также поднимаются в начало области видимости, но в отличие от переменных, объявленных с помощью 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
- D:
3 3 3
и3 3 3
Ответ
Правильный ответ: 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
console.log(+true)
console.log(!"John")
- A:
1
иfalse
- B:
0
иtrue
- C:
false
иNaN
- D:
false
иfalse
Ответ
Правильный ответ: A
Унарный плюс (+
) приводит операнд к числу. true
- это 1
, а false
- 0
. Строка John
- это истинное значение. Мы спрашиваем, является ли это значение ложным? Ответ: false
.
Вопрос № 5
let c = { greeting: "Hey!" }
let d
d = c
c.greeting = "Hello!"
console.log(d.greeting)
- A:
Hello!
- B:
Hey!
- C:
undefined
- D:
Error
Ответ
Правильный ответ: A
В JavaScript
все объекты являются "ссылочными" типами данных, т.е. значения объектов передаются по ссылкам. Сначала в переменной c
создается ссылка на объект. Затем мы указываем переменной d
ссылаться на тот же объект, на который ссылается c
. При изменении объекта меняются значения всех указывающих на него ссылок.
Вопрос № 6
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
.
Вопрос № 7
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor
return this.newColor
}
constructor({ newColor = "green" } = {}) {
this.newColor = newColor
}
}
const freddie = new Chameleon({ newColor: "pink" })
freddie.colorChange("orange")
- A:
orange
- B:
pink
- C:
green
- D:
Error
Ответ
Правильный ответ: D
Метод colorChange
является статическим. Такие методы не имеют доступа к экземплярам класса. Так как freddie
- это экземпляр, статический метод в нем не доступен. Поэтому выбрасывается исключение TypeError
.
Вопрос № 8
// обратите внимание: код выполняется в нестрогом режиме
let greeting
greetign = {} // опечатка!
console.log(greetign)
- A:
{}
- B:
Error
- C:
undefined
- D:
""
Ответ
Правильный ответ: A
С помощью выражения greetign = {}
мы создаем новый глобальный пустой объект, который выводится в консоль. Когда мы вместо greeting
написали greetign
, интерпретатор выполнил global.greetign = {}
в Node.js
(или window.greetign = {}
в браузере). В строгом режиме ("use strict"
) будет выброшено исключение ReferenceError: greetign is not defined
.
Вопрос № 9
function bark() {
console.log("Woof!")
}
bark.animal = "dog"
console.log(bark.animal)
- A:
dog
- B:
Error
- C:
undefined
- D:
""
Ответ
Правильный ответ: A
В JavaScript
такое возможно, т.к. функции в JS
- это тоже объекты. Точнее, функция — это специальный тип объекта, который можно вызывать (такой объект имеет внутренний слот callable
). Кроме того, функция — это объект со свойствами, вызывать которые нельзя, поскольку они не являются функциями.
Вопрос № 10
function Person(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
const person = new Person("John", "Smith")
Person.getFullName = function () {
return `${this.firstName} ${this.lastName}`
}
console.log(person.getFullName())
- A:
Error
- B:
""
- C:
John Smith
- D:
undefined undefined
Ответ
Правильный ответ: A
Нельзя добавлять свойства к конструктору как к обычному объекту. Если необходимо добавить свойство или метод всем экземплярам, то следует использовать прототипы. В данном случае выражение Person.prototype.getFullName = function () { return ${this.firstName} ${this.lastName} }
сделает метод getFullName
рабочим. В чем здесь преимущество? Предположим, что мы добавили этот метод к конструктору. Возможно, он нужен не каждому экземпляру класса Person
. Это приведет к лишнему расходованию памяти, т.к. все экземпляры будут иметь указанный метод. Напротив, если мы добавим данный метод к прототипу, у нас будет только одно место в памяти, к которому смогут обращаться все экземпляры. Такие методы называются совме стными или распределенными (shared).
Вопрос № 11
function Person(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
const john = new Person("John", "Smith")
const jane = Person("Jane", "Air")
console.log(john)
console.log(jane)
- A:
Person {firstName: "John", lastName: "Smith"}
иundefined
- B:
Person {firstName: "John", lastName: "Smith"}
иPerson {firstName: "Jane", lastName: "Air"}
- C:
Person {firstName: "John", lastName: "Smith"}
и{}
- D:
Person {firstName: "Smith", lastName: "Smith"}
иError
Ответ
Правильный ответ: A
Мы создаем объект jane
без помощи ключевого слова new
. Использование new
приводит к созданию нового объекта (экземпляра). Без new
создается глобальный объект. Мы указали, что this.firstName
равняется Jane
и this.lastName
равняется Air
. На самом деле, мы определили global.firstName = 'Jane'
и global.lastName = 'Air'
. Значением jane
является undefined
, поскольку мы ничего не возвращаем из функции Person
.
Вопрос № 12
function sum(a, b) {
return a + b
}
console.log(sum(1, "2"))
- A:
NaN
- B:
Error
- C:
"12"
- D:
3
Ответ
Правильный ответ: C
JavaScript
- это динамически типизированный язык: мы не определяем тип данных при объявлении переменных (для этого был придуман TypeScript
). Значения переменных могут быть автоматически преобразованы из одного типа в другой без нашего участия. Это называется "неявным приведением типов". Приведение - это преобразование данных из одного типа в другой. В рассматриваемом примере JavaScript
конвертировал число 1
в строку, чтобы операция имела смысл и вернула хоть какое-то значение. При сложении числа (1
) и строки ("2"
) число преобразуется в строку. Мы можем объединять строки так: "Hello" + "World"
. Это называется конкатенацией строк. Таким образом, 1 + "2"
возвращает "12"
.
Вопрос № 13
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
Постфиксный оператор ++
:
- возвращает значение (
0
); - увеличивает (инкрементирует) значение (после чего значением переменной
number
становится1
). Префиксный оператор++
: - инкрементирует значение (теперь
number === 2
); - возвращает значение (
2
). Результат:0 2 2
.
Вопрос № 14
function getPersonInfo(one, two, three) {
console.log(one)
console.log(two)
console.log(three)
}
const person = "John"
const age = 30
getPersonInfo`${person} is ${age} years old`
- A:
John 30 ["", " is ", " years old"]
- B:
["", " is ", " years old"] John 30
- C:
John ["", " is ", " years old"] 30
- D:
undefined
Ответ
Правильный ответ: B
При использовании тегированных шаблонных литералов (tagged template literals) первым значением, возвращаемым функцией, является массив строк. Прочими значениями являются значения, переданные функции в качестве аргументов.
Вопрос № 15
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:
"Хм... У тебя что, нет возраста?"
- D:
undefined
Ответ
Правильный ответ: C
В операциях сравнения примитивы сравниваются по значениям, а объекты - по ссылкам. JavaScript
проверяет, чтобы объекты указывали на одну и ту же область памяти. Сравниваемые объекты в рассматриваемом примере не такие: объект, переданный в качестве аргумента, указывает на другое место в памяти, нежели объекты, используемые в сравнениях. Поэтому выражения { age: 18 } === { age: 18 }
и { age: 18 } == { age: 18 }
возвращают false
.
Вопрос № 16
function getAge(...args) {
console.log(typeof args)
}
getAge(30)
- A:
number
- B:
array
- C:
object
- D:
NaN
Ответ
Правильный ответ: C
Оператор распространения или расширения (spread, ...
) возвращает массив с аргументами, переданными функции. Массив - это объект, поэтому выражение typeof args
возвращает object
.
Вопрос № 17
function getAge() {
"use strict"
age = 30
console.log(age)
}
getAge()
- A:
30
- B:
undefined
- C:
Error
- D:
NaN
Ответ
Правильный ответ: C
"use strict"
, среди прочего, позволяет предотвратить случайное объявл ение глобальных переменных. Мы не объявляли переменную age
, поэтому (в строгом режиме) выбрасывается исключение ReferenceError
. В нестрогом режиме ошибки не возникнет, а переменная age
станет свойством глобального объекта window
.
Вопрос № 18
const sum = eval("10*10+5")
console.log(sum)
- A:
105
- B:
"105"
- C:
Error
- D:
"10*10+5"
Ответ
Правильный ответ: A
Функция eval
выполняет код, переданный ей в виде строки. Если это выражение (как в данном случае), то оно вычисляется (оценивается). Выражение 10 * 10 + 5
возвращает число 105
. Использовать eval
не рекомендуется по причинам безопасности.
Вопрос № 19
var num = 8
var num = 10
console.log(num)
- A:
8
- B:
10
- C:
undefined
- D:
Error
Ответ
Правильный ответ: B
С помощью ключевого слова var
можно определять любое количество одноименных переменных. Переменная будет хранить последнее присвоенное ей значение. Однако, такой трюк нельзя проделать с let
и const
, т.к. переменные, объявленные с помощью этих ключевых слов, имеют блочную область видимости.
Вопрос № 20
const obj = { 1: "a", 2: "b", 3: "c" }
const set = new Set([1, 2, 3, 4, 5])
console.log(obj.hasOwnProperty("1"))
console.log(obj.hasOwnProperty(1))
console.log(set.has("1"))
console.log(set.has(1))
- A:
false true false true
- B:
false true true true
- C:
true true false true
- D:
true true true true
Ответ
Правильный ответ: C
Ключи объектов (кроме Symbol
) являются строками, даже если заданы не в виде строк (например, индексы в массиве). Поэтому выражение obj.hasOwnProperty('1')
также возвращает true
. Однако, это не работает с Set
. Значение 1
отсутствует в set
: set.has('1')
возвращает false
, а set.has(1)
- true
.
Вопрос № 21
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:
Error
Ответ
Правильный ответ: C
Если в объекте имеется два ключа с одинаковыми именами, то первый ключ перезаписывается. Его позиция сохраняется, а значением становится последнее из присвоенных.
Вопрос № 22
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
пропускает текущую итерацию (цикл), если условие удовлетворяется (является истинным).
Вопрос № 23
String.prototype.giveMePizza = () => {
return "Give me pizza!"
}
const name = "John"
console.log(name.giveMePizza())
- A:
"Give me pizza!"
- B:
Error
- C:
""
- D:
undefined
Ответ
Правильный ответ: A
String
- это встроенный конструктор, к которому можно добавлять новые свойства. Мы добавили метод giveMePizza
к его прототипу. Строки-примитивы автоматически конвертируются (преобразуются) в строки-объекты (благодаря объектной обертке). Поэтому все строки (объекты) имеют доступ к указанному методу.
Вопрос № 24
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:
Error
Ответ
Правильный ответ: B
Ключи объекта (кроме Symbol
) автоматически преобразуются в строки (даже индексы в массиве). Мы пытаемся добавить объект в качестве ключа со значением 123
к объекту a
. Однако, когда мы приводим объект к строке, он превращается в [object Object]
. Таким образом, мы говорим, что a["object Object"] = 123
. Затем мы повторяем процедуру. c
- это другой объект, который мы также неявно приводим к строке. Поэтому a["object Object"] = 456
. Наконец, когда мы выводим a[b]
в консоль, мы на самом деле обращаемся к a["object Object"]
. Поэтому в консоль выводится 456
.
Вопрос № 25
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
. После того, как setTimeout
отправляется в WebAPI
, функция bar
удаляется из стека вызовов (call stack). После этого вызывается функция foo
, и first
выводится в консоль. foo
удаляется из стека и вызывается функция baz
. third
выводится в консоль. WebAPI
отправляет функцию обратного вызова setTimeout
в очередь событий (task queue, второе слово читается как "кью"). Цикл событий (event loop) проверяет стек вызовов и очередь задач. Если стек оказывается пустым, то в него помещается первый элемент из очереди. Вызывается функция bar
и в консоль выводится second
.
Вопрос № 26
<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
). Всплытие происходит от самого глубоко вложенного элемента до самого внешнего.
Вопрос № 27
const person = { name: "John" }
function sayHi(age) {
console.log(`${this.name} is ${age}`)
}
sayHi.call(person, 30)
sayHi.bind(person, 30)
- A:
undefined is 30
иJohn is 30
- B:
function
иfunction
- C:
John is 30
иJohn is 30
- D:
John is 30
иfunction
Ответ
Правильный ответ: D
В обоих случаях мы передаем объект, на который будет указывать this
. Но метод call
выполняется сразу, а метод bind
возвращает копию функции с привязанным контекстом. Эту функцию следует вызывать отдельно или можно сделать так: sayHi.bind(person, 30)()
.
Вопрос № 28
function sayHi() {
return (() => 0)()
}
console.log(typeof sayHi())
- A:
object
- B:
number
- C:
function
- D:
undefined
Ответ
Правильный ответ: B
Функция sayHi
возвращает значение немедленно вызываемого функционального выражения (Immediately Invoked Function Expression, IIFE). Результатом является число 0
типа number
. Для информации: в JavaScript
имеется 8
встроенных типов данных: string, number, bigint, boolean, null, undefined, object и symbol
. function
не является отдельным типом, функции - это объекты.
Вопрос № 29
console.log(typeof typeof 1)
- A:
number
- B:
string
- C:
object
- D:
undefined
Ответ
Правильный ответ: B
Выражение typeof 1
возвращает number
. Выражение typeof number
возвращает string
.
Вопрос № 30
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:
Error
Ответ
Правильный ответ: C
Когда в массив добавляется значение, которое выходит за пределы длины массива, JavaScript
создает "пустые ячейки". На самом деле они имеют значение undefined
, но в консоль выводятся как [1, 2, 3, 7 x empty, 11]
(зависит от среды выполнения кода).
Вопрос № 31
(() => {
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
- 2
. После этого мы выводим в консоль значение x
, т.е. 1
. За пределами catch x
все еще имеет значение undefined
, а y
- 2
. Когда мы вызываем console.log(x)
за пределами catch
, возвращается undefined
, а console.log(y)
возвращает 2
.
Вопрос № 32
const result =
[[0, 1], [2, 3]].reduce(
(acc, cur) => {
return acc.concat(cur)
},
[1, 2]
)
console.log(result)
- 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]
. После конкатенации (объединения) acc
равняется [1, 2, 0, 1]
, а cur
- [2, 3]
. После их объединения, мы получаем [1, 2, 0, 1, 2, 3]
.
Вопрос № 33
console.log(!!null)
console.log(!!"")
console.log(!!1)
- A:
false true false
- B:
false false true
- C:
false true true
- D:
true true false
Ответ
Правильный ответ: B
null
- это false
. !null
возвращает true
. !true
возвращает false
.
""
- это false
. !""
возвращает true
. !true
возвращает false
.
1
- это true
. !1
возвращает false
. !false
возвращает true
.
Вопрос № 34
console.log([..."John"])
- A:
["J", "o", "h", "n"]
- B:
["John"]
- C:
[[], "John"]
- D:
[["J", "o", "h", "n"]]
Ответ
Правильный ответ: A
Строка является итерируемой (перебираемой) сущностью. Оператор распространения или расширения (spread, ...
) преобразует строку в массив, состоящий из символов этой строки.
Вопрос № 35
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
и10, 20
Ответ
Правильный ответ: C
Выполнение обычных функций не может быть остановлено после их запуска. Однако, генераторы можно останавливать в процессе выполнения, а затем продолжать с места остановки. Каждый раз, когда в функции-генераторе встречается ключевое слово yield
, функция возвращает значение, указанное после него. Обратите внимание, что в генераторе вместо return
используется yield
. Сначала мы инициализируем генератор с i
равным 10
. Мы вызываем генератор, используя метод next
. Когда мы в первый раз вызываем генератор, i
равняется 10
. Движок JavaScript
встречает первое ключевое слово yield
и возвращает значение i
. После этого выполнение функции приостанавливается и 10
выводится в консоль. Затем мы снова вызываем функцию посредством next()
. Она запускается с того места, где остановилась, с i
равным 10
. Движок встречает следующее ключевое слово yield
и возвращает i * 2
. i
равно 10
, поэтому возвращается 20
.
Вопрос № 36
const firstPromise = new Promise((res, rej) => {
setTimeout(res, 500, "one")
})
const secondPromise = new Promise((res, rej) => {
setTimeout(res, 100, "two")
})
Promise.race([firstPromise, secondPromise]).then(res => console.log(res))
- A:
one
- B:
two
- C:
two one
- D:
one two
Ответ
Правильный ответ: B
Когда мы передаем несколько промисов методу race
, он возвращает первый разрешенный (выполненный или отклоненный) промис. В функ цию setTimeout
мы передаем задержку в 500
мс для первого промиса и в 100
мс - для второго. Это означает, что secondPromise
разрешается первым со значением two
. Переменная res
имеет значение two
, которое и выводится в консоль.
Вопрос № 37
let person = { name: "John" }
const members = [person]
person = null
console.log(members)
- A:
null
- B:
[null]
- C:
[{}]
- D:
[{ name: "John" }]
Ответ
Правильный ответ: D
Сначала мы объявляем переменную person
со значением объекта, содержащего свойство name
. Затем мы объявляем переменную members
. Мы делаем первый элемент этого массива равным [person]
. Объекты взаимодействуют посредством ссылок при установке их равными друг другу. Когда мы назначаем ссылку из одной переменной в другую, создается копия этой ссылки (обратите внимание, что у этих переменных не одинаковые ссылки). Затем мы присваиваем переменной person
значение null
. Мы изменили только значение person
, а не первый элемент массива, поскольку этот элемент имеет другую (скопированную) ссылку на объект. Первый элемент в members
по-прежнему содержит ссылку на исходный объект. Когда мы выводим в консоль массив members
, первый элемент этого массива содержит значение объекта, который и выводится в консоль.
Вопрос № 38
const person = {
name: "John",
age: 30
}
for (const item in person) {
console.log(item)
}
- A:
{ name: "John" }
и{ age: 30 }
- B:
name
иage
- C:
John
и30
- D:
["name", "John"]
и["age", 30]
Ответ
Правильный ответ: B
С помощью цикла for..in
мы перебираем ключи объекта, в данном случае name
и age
. Ключи объекта (кроме Symbol
) являются строками. В каждом цикле мы устанавливаем значение item
равным текущему ключу, по которому он перебирается. Сначала item
равен name
, и выводится в консоль. Затем item
равен age
, что также выводится в консоль.
Вопрос № 39
console.log(3 + 4 + "5")
- A:
"345"
- B:
"75"
- C:
12
- D:
"12"
Ответ
Правильный ответ: B
Ассоциативность операторов - это порядок оценивания выражения движком JavaScript
, слева направо или справа налево. Это происходит только в том случае, если все операторы имеют одинаковый приоритет. У нас есть только один тип оператора: +
. Ассоциативность - слева направо. 3 + 4
оценивается первым. Это приводит к числу 7
. 7 + "5"
приводит к "75"
из-за неявного приведени я типов. JavaScript
преобразует число 7
в строку. Мы можем объединять (конкатенировать) две строки с помощью оператор +
. Выражение '7' + '5'
возвращает 75
.
Вопрос № 40
const num = parseInt("7*6", 10)
console.log(num)
- A:
42
- B:
"42"
- C:
7
- D:
NaN
Ответ
Правильный ответ: C
Функция parseInt
проверяет, являются ли символы в строке допустимыми с точки зрения используемой системы счисления (второй необязательный аргумент). Как только встречается недопустимый символ, синтаксический анализ строки прекращается и последующие символы игнорируются. *
является недопустимым числом. Поэтому parseInt
прекращает разбор строки и возвращает 7
.
Вопрос № 41
const result =
[1, 2, 3].map(num => {
if (typeof num === "number") return
return num * 2
})
console.log(result)
- A:
[]
- B:
[null, null, null]
- C:
[undefined, undefined, undefined]
- D:
[ 3 x empty ]
Ответ
Правильный ответ: C
Метод map
возвращает новый массив с обработанными с помощью функции обратного вызова элементами исходного массива. В данном случае элементы исходного массива являются числами, поэтому условие if typeof num === 'number'
удовлетворяется. После этого выполнение функции останавливается, в новый массив попадает значение переменной num
, равное undefined
.
Вопрос № 42
function greeting() {
throw "Всем привет!"
}
function sayHi() {
try {
const data = greeting()
console.log("Работает!", data)
} catch (error) {
console.log("Ошибка: ", error)
}
}
sayHi()
- A:
Работает! Всем привет!
- B:
Ошибка: undefined
- C:
Error
- D:
Ошибка: Всем привет!
Ответ
Правильный ответ: D
С помощью оператора throw
мы можем создавать собственные ошибки. Другими словами, с помощью этого оператора мы можем генерировать пользовательские исключения. Исключением может быть строка, число, логическое значение или объект. В данном случае, исключением является строка Всем привет!
. С помощью оператора catch
мы можем указать, что делать, если в блоке try
возникла ошибка. Исключение - Всем привет!
. error
равняется этой строке. Это приводит к Ошибка: Всем привет!
.
Вопрос № 43
function Car() {
this.make = "Lamborghini"
return { make: "Maserati" }
}
const myCar = new Car()
console.log(myCar.make)
- A:
Lamborghini
- B:
Maserati
- C:
Error
- D:
undefined
Ответ
Правильный ответ: B
Когда возвращается свойство, его значение равняется возвращаемому значению, а не значению, установленному в функции-конструкторе. Мы возвращаем строку Maserati
, поэтому значением myCar.make
является Maserati
.
Вопрос № 44
(() => {
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.js
). В браузере window.y
теперь равняется 10
. Затем мы объявляем переменную x
со значением y
. Переменные, объявленные с помощью ключевых слов let
и const
, имеют блочную область видимости, они доступны только в том блоке, в котором они объявлены. Таким блоком в данном случае является немедленно вызываемое функциональное выражение (Immediately Invoked Function Expression, IIFE). Когда мы используем оператор typeof
, операнд x
не определен: мы пытаемся получить доступ к x
вне блока его объявления. Это означает, что x
имеет значение undefined
. Переменные, которым не присвоено значение, по умолчанию имеют значение undefined
. Выражение console.log(typeof x)
возвращает undefined
. Однако, мы создали глобальную переменную y
, присвоив ей значение 10
. Это значение доступно в любом месте кода. y
определена и содержит значение типа number
. Поэтому выражение console.log(typeof y)
возвращает number
.
Вопрос № 45
class Dog {
constructor(name) {
this.name = name
}
}
Dog.prototype.bark = function() {
console.log(`Woof I am ${this.name}`)
}
const pet = new Dog("Rex")
pet.bark()
delete Dog.prototype.bark
pet.bark()
- A:
"Woof I am Rex"
и""
- B:
"Woof I am Rex"
и"Woof I am Rex"
- C:
"Woof I am Rex"
иundefined
- D:
"Woof I am Rex"
иError
Ответ
Правильный ответ: D
Оператор delete
позволяет удалять свойст ва объектов, включая свойства прототипов. Удаленное свойство прототипа становится недоступным в цепочке прототипов. Другими словами, функция bark
после delete Dog.prototype.bark
становится недоступной, однако мы все же пытаемся получить к ней доступ. Когда мы пытаемся вызвать нечто, не являющееся функцией, выбрасывается исключение TypeError
: в данном случае TypeError: pet.bark is not a function
, поскольку значением свойства bark
объекта pet
является undefined
.
Вопрос № 46
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
является коллекцией уникальных значений. Мы передаем в new Set()
массив [1, 1, 2, 3, 4]
с повторяющимся значением 1
. Поскольку в set
не может быть двух одинаковых значений, одно из них удаляется. Это приводит к { 1, 2, 3, 4 }
.
Вопрос № 47
// counter.js
let counter = 10
export default counter
// index.js
import myCounter from "./counter.js"
myCounter += 1
console.log(myCounter)
- A:
10
- B:
11
- C:
Error
- D:
NaN
Ответ
Правильный ответ: C
Импортируемый модуль доступен только для чтения: мы не можем его изменять. Это можно сделать только перед экспортом. Когда мы пытаемся увеличить значение переменной myCounter
, возникает ошибка myCounter доступен только для чтения и не может быть изменен
.
Вопрос № 48
const name = "John"
age = 30
console.log(delete name)
console.log(delete age)
- A:
false
иtrue
- B:
John
и30
- C:
true
иtrue
- D:
undefined
иundefined
Ответ
Правильный ответ: A
Оператор delete
возвращает логическое значение: true
при успешном удалении, иначе - false
. Однако, переменные, объявленные с помощью ключевых слов, не могут быть удалены с помощью delete
. Переменная name
была объявлена с помощью ключевого слова const
, поэтому возвращается false
. Когда мы устанавливаем переменную age
равной 30
, мы фактически добавляем свойство age
к глобальному объекту (window.age
в браузере, global.age
в Node.js
). Свойства объектов, включая глобальный, удалять можно, поэтому выражение delete age
возвращает true
.
Вопрос № 49
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
. Поэтому в консоль выводится 1
.
Вопрос № 50
const user = { name: "John", age: 30 }
const admin = { admin: true, ...user }
console.log(admin)
- A:
{ admin: true, user: { name: "John", age: 30 } }
- B:
{ admin: true, name: "John", age: 30 }
- C:
{ admin: true, user: [John, 30] }
- D:
{ admin: true }
Ответ
Правильный ответ: B
Оператор распространения или расширения (spread, ...
) позволяет объединять объекты - создавать копии пар ключ/значение одного объекта и добавлять их в другой объект. В данном случае мы создаем копию объекта user
и добавляем ее в объект admin
. Объект admin
содержит скопированные пары ключ/значение, что приводит к { admin: true, name: 'John', age: 30 }
.
Вопрос № 51
const person = { name: "John" }
Object.defineProperty(person, "age", { value: 30 })
console.log(person)
console.log(Object.keys(person))
- A:
{ name: "John", age: 30 }
и["name", "age"]
- B:
{ name: "John", age: 30 }
и["name"]
- C:
{ name: "John"}
и["name", "age"]
- D:
{ name: "John"}
и["age"]
Ответ
Правильный ответ: B
С помощью метода defineProperty
мы можем добавлять новые свойства к объекту или изменять существующие. Когда мы добавляем свойство к объекту с помощью defineProperty()
, они по умолчанию являются не перечисляемыми (enumerable: false
). Метод keys
возвращает все перечисляемые свойства объекта, в данном случае только name
. Свойства, добавленные с помощью defineProperty()
, по умолчанию также иммутабельны (неизменяемы, writable: false
). Это поведение можно переопределить, используя свойства writable
, configurable
и enumerable
. Таким образом, метод defineProperty
позволяет осуществлять тонкую настройку свойств, добавляемых к объекту.
Вопрос № 52
const settings = {
username: "johnsmith",
level: 19,
health: 88
}
const data = JSON.stringify(settings, ["level", "health"])
console.log(data)
- A:
{"level": 19, "health": 88}
- B:
{"username": "johnsmith"}
- C:
["level", "health"]
- D:
{"username": "johnsmith", "level": 19, "health": 88}
Ответ
Правильный ответ: A
Второй аргумент JSON.stringify()
- это заменитель (replacer). Заменитель может быть либо функцией, либо массивом, и позволяет контролировать, что и как должно быть преобразовано в значения. Если заменитель является массивом, только свойства, указанные в нем, будут добавлены в JSON-строку
. В данном случае в строку включаются только свойства level
и health
, свойство username
исключается. Значение переменной data
равняется { "level": 19, "health": 90 }
. Если заменитель является функцией, она вызывается для каждого свойства объекта. Значение, возвращаемое функцией, будет значением свойства при добавлении в строку. Если значением свойства является undefined
, такое свойство исключается из состава строки.
Вопрос № 53
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
и только после этого увеличивает его на 1
. num2
равняется 10
, так как мы передали num1
в функцию increasePassedNumber
. Аргумент number
равняется 10
. Снова оператор ++
сначала возвращает значение операнда, а затем увеличивает его на 1
. Поскольку аргумент number
равняется 10
, num2
также равняется 10
.
Вопрос № 54
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 }
. Аргумент по умолчанию реализуется в момент вызова функции. Каждый раз, когда мы вызываем функцию, создается новый объект. Мы вызываем функцию multiply
первые два раза, не передавая ей никаких аргументов, поэтому x
имеет значение { number: 10 }
. Затем мы умножаем значение x.number
на 2
, получаем 20
. В третий раз, когда мы вызываем multiply()
, мы передаем объект value
в качестве. Оп ератор *=
является сокращением для x.number = x.number * 2
: мы меняем значение x.number
, теперь оно равняется 20
. В четвертый раз мы снова передаем multiply()
объект value
. x.number
равняется 20
, поэтому выражение x.number *= 2
возвращает 40
.
Вопрос № 55
[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
мы применяем функцию обратного вызова к каждому элементу массива, что, в конечном счете, приводит к единственному значению. В приведенном примере мы не возвращаем никаких значений из функции, а просто регистрируем значение аккумулятора и текущее значение. Значение аккумулятора равняется ранее возвращенному значению колбека. Если методу reduce
не передается необязательный аргумент initialValue
(начальное значение), аккумулятор равняется первому элементу при первом вызове. При первом вызове аккумулятор (x
) равняется 1
, а текущее значение (y
) - 2
. Мы не выходим из функции, а регистрируем значение аккумулятора и текущее значение: 1
и 2
, соответственно. Если из функции не возвращается значения, она возвращает undefined
. При следующем вызове аккумулятор равняется undefined
, а текущее значение - 3
. undefined
и 3
выводятся в консоль. При четвертом вызове мы снова не возвращаем значение из функции. Аккумулятор равняется undefined
, а текущее значение - 4
: undefined
и 4
выводятся в консоль.
Вопрос № 56
// index.js
console.log('Выполнение index.js')
import { sum } from './sum.js'
console.log(sum(1, 2))
// sum.js
console.log('Выполнение sum.js')
export const sum = (a, b) => a + b
- A:
Выполнение index.js Выполнение sum.js 3
- B:
Выполнен ие sum.js Выполнение index.js 3
- C:
Выполнение sum.js 3 Выполнение index.js
- D:
Выполнение index.js undefined Выполнение sum.js
Ответ
Правильный ответ: B
При импорте модулей с помощью ключевого слова import
, они являются предварительно разобранными (распарсенными). Это означает, что модули запускаются первыми, а код в файле, который импортирует модуль, выполняется позже. В этом разница между require()
в CommonJS
и import()
в ES6
. С помощью метода require
мы можем загружать зависимости динамически во время выполнения кода. При использовании require()
вместо import()
в консоль будет выведено Выполнение index.js Выполнение sum.js 3
.
Вопрос № 57
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.
Вопрос № 58
const name = "John Smith"
console.log(name.padStart(12))
console.log(name.padStart(2))
- A:
"John Smith"
и"John Smith"
- B:
" John Smith"
и" John Smith" ("[12x whitespace]John Smith" "[2x whitespace]John Smith")
- C:
" John Smith"
и"John Smith" ("[2x whitespace]John Smith", "John Smith")
- D:
"John Smith"
и"Jo"
Ответ
Правильный ответ: C
С помощью метода padStart
мы добавляем отступы в начало строки. Значение, передаваемое этому методу, представляет собой общую длину строки вместе с отступом. Строка John Smith
имеет длину, равную 10
. name.padStart(12)
вставляет 2
пробела в начало строки, потому что 10 + 2
есть 12
. Если аргумент, переданный методу padStart
, меньше длины строки, заполнение не выполняется.
Вопрос № 59
console.log("📱" + "💻")
- A:
"📱💻"
- B:
257548
- C:
undefined
- D:
Error
Ответ
Правильный ответ: A
С помощью оператора +
мы можем объединять строки. Это называется конкатенацией. В данном случае, мы объединяем строку 📱
со строкой 💻
, что приводит к 📱💻
.
Вопрос № 60
function* startGame() {
const answer = yield "Ты любишь JavaScript?"
if (answer !== "Да") {
return "Как интересно... В таком случае, что ты здесь делаешь?"
}
return "JavaScript тоже тебя любит ❤️"
}
const game = startGame()
console.log(/* 1 */) // Ты любишь JavaScript?
console.log(/* 2 */) // JavaScript тоже тебя любит ❤️
- A:
game.next("Да").value
иgame.next().value
- B:
game.next.value("Да")
иgame.next.value()
- C:
game.next().value
иgame.next("Да").value
- D:
game.next.value()
иgame.next.value("Да")
Ответ
Правильный ответ: C
Когда движок JavaScript
встречает ключевое слово yield
, выполнение функции-генератора приостанавливается. Во-первых, мы должны позволить функции вернуть строку Ты любишь JavaScript?
, что можно сделать, вызвав game.next().value
. Код функции выполняется последовательно до тех пор, пока не встретится ключевое слово yield
. В первой строке имеется yield
: выполнение останавливается с первым результатом. Это означает, что переменная answer
на данный момент еще не определена. Когда мы вызываем game.next("Да").value
, предыдущий yield
заменяется значением аргумента, переданного методу next
, в данном случае Да
. Значение переменной answer
равняется Да
. Условие if (answer !== "Да")
возвращает false
, и JavaScript тоже тебя любит ❤️
выводится в консоль.
Вопрос № 61
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
Вопрос № 62
async function getData() {
return await Promise.resolve("Я сделал это!")
}
const data = getData()
console.log(data)
- A:
"Я сделал это!"
- B:
Promise {\<resolved\>: "Я сделал это!"}
- C:
Promise {\<pending\>}
- D:
undefined
Ответ
Правильный ответ: C
Асинхронная функция всегда возвращает промис. await
ожидает разрешения промиса: промис разрешается, когда мы вызываем getData()
, чтобы присвоить его переменной data
. Если бы мы хотели получить доступ к разрешенному значению Я сделал это!
, мы могли бы использовать метод then
для data
: data.then(res => console.log(res))
. Тогда бы мы получили Я сделал это!
.
Вопрос № 63
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
.
Вопрос № 64
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:
Error
Ответ
Правильный ответ: B
Object.freeze()
делает невозможным добавление, удаление или изменение свойств объекта (если только значение свойства не является другим объектом). Когда мы создаем переменную shape
и устанавливаем ее равной замороженному объекту box
, shape
ссылается на этот объект. Заморожен ли объект, можно определить посредством Object.isFrozen()
. В да ном случае Object.isFrozen(shape)
вернет true
, поскольку переменная shape
ссылается на замороженный объект. Поскольку shape
заморожен, а значение свойства x
не является объектом, мы не можем его изменять. x
по-прежнему равняется 10
, и { x: 10, y: 20 }
выводится в консоль.
Вопрос № 65
const { name: myName } = { name: "John" }
console.log(name)
- A:
John
- B:
myName
- C:
undefined
- D:
Error
Ответ
Правильный ответ: D
Когда мы распаковываем свойство name
из правого объекта, мы присваиваем значение John
переменной myName
. С помощью выражения { name: myName }
мы сообщаем JavaScript
, что хотим создать новую переменную с именем myName
и со значением свойства name
из правой части выражения. Поскольку мы пытаемся вывести в консоль name
, переменную, которая не определена, выбрасывается исключение ReferenceError
.
Вопрос № 66
const add = () => {
const cache = {}
return num => {
if (num in cache) {
return `Из кеша! ${cache[num]}`
} else {
const result = num + 10
cache[num] = result
return `Вычислено! ${result}`
}
}
}
const addFunction = add()
console.log(addFunction(10))
console.log(addFunction(10))
console.log(addFunction(5 * 2))
- A:
Вычислено! 20 Вычислено! 20 Вычислено! 20
- B:
Вычислено! 20 Из кеша! 20 Вычислено! 20
- C:
Вычислено! 20 Из кеша! 20 Из кеша! 20
- D:
Вычислено! 20 Из кеша! 20 Error
Ответ
Правильный ответ: C
Функция add
является функцией запоминания (мемоизации). С помощью запоминания мы можем кешировать результаты вызова функции, чтобы ускорить ее по вторное выполнение. В данном случае мы создаем объект cache
для хранения возвращаемых функцией значений. Если мы повторно вызовем функцию addFunction
с тем же аргументом, она сначала проверит, имеется ли соответствующее значение в кеше. Если такое значение имеется, оно возвращается, что экономит время на выполнение функции. Иначе, если значение в кеше отсутствует, оно вычисляется и сохраняется. Мы вызываем addFunction()
3 раза с одним и тем же аргументом: при первом вызове для num
, равном 10
, значение, возвращаемое функцией, в кеше отсутствует. Условие if (num in cache)
возвращает false
, и выполняется блок else
: Вычислено! 20
выводится в консоль, а результат добавляется в объект cache
. cache
теперь выглядит как { 10: 20 }
. При повторном вызове значение для аргумента 10
возвращается из кеша. Условие if (num in cache)
возвращает true
, и Из кеша! 20
выводится в консоль. В третий раз мы передаем в функцию выражение 5 * 2
, что оценивается (вычисляется) как 10
. Объект cache
содержит искомое значение. Условие if (num in cache)
возвращает true
, и Из кеша! 20
выводится в консоль.
Вопрос № 67
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
равняется итерируемому элементу, "☕" "💻" "🍷" "🍫"
выводится в консоль.
Вопрос № 68
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
Элементами массива могут быть любые типы данных. Числа, строки, объекты, другие массивы, null
, логические значения, undefined
, а также даты, функции и выражения. Элемент будет равен возвращаемому значению. Выражение 1 + 2
возвращает 3
, 1 * 2
- 2
, а 1 / 2
- 0.5
.
Вопрос № 69
function sayHi(name) {
return `Hello, ${name}`
}
console.log(sayHi())
- A:
Hello
, - B:
Hello, undefined
- C:
Hello, null
- D:
Error
Ответ
Правильный ответ: B
По умолчанию аргументы функции имеют значение undefined
, если значение не было передано при вызове функции или присвоено по умолчанию. В данном случае мы не передаем значения для аргумента name
. name
равняется undefined
. В ES6
мы можем перезаписывать undefined
значениями по умолчанию. Например: function sayHi(name = "John") { ... }
. В данном случае, если мы не передали значение или передали undefined
, аргумент name
будет иметь значение John
.
Вопрос № 70
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
указывает на этот объект. Когда мы выводим в консоль this.status
, выводится свойство status
объекта data
или 😉
. С помощью метода call
мы можем изменить объект, на который ссылается this
(изменить контекст this
). В функциях ключевое слово this
относится к объекту, которому принадлежит функция, либо к объекту, создаваемому с помощью функции-конструктора. Мы объявили функцию setTimeout
для объекта global
, поэтому в функции setTimeout
ключевое слово this
указывает на объект global
. В глобальном объекте есть переменная status
со значением 😎
, которое и выводится в консоль.
Вопрос № 71
const person = {
name: "John",
age: 30
}
let city = person.city
city = "New York"
console.log(person)
- A:
{ name: "John", age: 30 }
- B:
{ name: "John", age: 30, city: "New York" }
- C:
{ name: "John", age: 30, city: undefined }
- D:
"New York"
Ответ
Правильный ответ: A
Мы устанавливаем переменную city
равной значению свойства city
объекта person
. У этого объекта нет свойства city
, поэтому переменная city
имеет значение undefined
. Обратите внимание, что мы не ссылаемся на person
. Мы просто устанавливаем переменную city
равной текущему значению свойства city
объекта person
. Затем мы устанавливаем переменную city
равной строке New York
. Это не изменяет объект person
.
Вопрос № 72
function checkAge(age) {
if (age < 18) {
const message = "Ты слишком молод."
} else {
const message = "Ты достаточно взрослый!"
}
return message
}
console.log(checkAge(30))
- A:
"Ты слишком молод."
- B:
"Ты достаточно взрослый!"
- C:
Error
- D:
undefined
Ответ
Правильный ответ: C
Переменные, объявленные с помощью ключевых слов const
и let
, имеют блочную область видимости. Блок - это любой код между фигурными скобками ({}
) - в данном случае в фигурных скобках операторов if-else
. Мы не можем получить доступ к переменной за пределами блока, в котором она объявлена - выбрасывается исключение ReferenceError
.
Вопрос № 73
function getName(name) {
const hasName = /* ? */
}
- A:
!!name
- B:
name
- C:
new Boolean(name)
- D:
name.length
Ответ
Правильный ответ: A
С помощью выражения !!name
мы определяем, является ли значение аргумента name
истинным. Если name
равняется true
, то !name
возвращает false
. А !false
(это то, чем на самом деле является !!name
) возвращает true
. Устанавливая hasName
равным name
, мы устанавливаем hasName
равным любому значению, которое передается функции getName
, а не логическому значению true
. new Boolean(true)
возвращает объектную обертку, а не само логическое значение. name.length
возвращает длину переданного аргумента.
Вопрос № 74
console.log("Я хочу пиццу!"[0])
- A:
""
- B:
"Я"
- C:
Error
- D:
undefined
Ответ
Правильный ответ: B
Чтобы получить символ по определенному индексу из строки, мы можем использовать скобочную нотацию. Первый символ в строке имеет индекс 0
, второй - индекс 1
и т.д. В данном случае мы хотим получить элемент с индексом 0
, символ Я
, который и выводится в консоль. Альтернативой получения символа по индексу является метод charAt
.
Вопрос № 75
function sum(num1, num2 = num1) {
console.log(num1 + num2)
}
sum(10)
- A:
NaN
- B:
20
- C:
Error
- D:
undefined
Ответ
Правильный ответ: B
Мы можем установить значение параметра по умолчанию равным другому параметру функции, если такой параметр был определен до параметра по умолчанию. Мы передаем значение 10
функции sum
. Если sum()
получает только один аргумент, значит, значение для num2
не передано, ей присваивается значение по умолчанию, т.е. 10
. Выражение num1 + num2
возвращает 20
. Если по пытаться установить значение параметра по умолчанию равным параметру, который определяется позже, то возникнет ошибка.
Вопрос № 76
// module.js
export default () => "Hello World!"
export const name = "John"
// index.js
import * as data from "./module"
console.log(data)
- A:
{ default: function default(), name: "John" }
- B:
{ default: function default() }
- C:
{ default: "Hello World!", name: "John" }
- D: глобальный объект module.js
Ответ
Правильный ответ: A
С помощью import * as name
мы импортируем все экспорты из файла module.js
в файл index.js
, создается новый объект data
. В файле module.js
имеется два экспорта: экспорт по умолчанию и именованный экспорт. Экспорт по умолчанию - это функция, которая возвращает строку Hello World!
, а именованный экспорт - это переменная name
, которая имеет значение John
. Объект data
имеет свойство default
для экспорта по умолчанию, другие свойства - именованные экспорты и соответствующие значения.
Вопрос № 77
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 member
возвращает object
.
Вопрос № 78
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
.
Вопрос № 79
function giveMePizza() {
return "А вот и пицца!"
}
const giveMeChocolate = () => "Вот шоколад... теперь дуй в тренажерку."
console.log(giveMePizza.prototype)
console.log(giveMeChocolate.prototype)
- A:
{ constructor: ...} { constructor: ...}
- B:
{} { constructor: ...}
- C:
{ constructor: ...} {}
- D:
{ constructor: ...} undefined
Ответ
Правильный ответ: D
Обычные функции, такие как giveMePizza
, имеют свойство prototype
, которое является объектом (прототипом объекта) со свойством constructor
. Однако стрелочные функции, такие как giveMeChocolate
, не имеют прототипа. Поэтому при попытке получить доступ к giveMeChocolate.prototype
возвращается undefined
.
Вопрос № 80
const person = {
name: "John",
age: 30
}
for (const [x, y] of Object.entries(person)) {
console.log(x, y)
}
- A:
name John
иage 30
- B:
["name", "John"]
и["age", 30]
- C:
["name", "age"]
иundefined
- D:
Error
Ответ
Правильный ответ: A
Object.entries(person)
возвращает массив вложенных массивов, содержащий ключи и значения: [ [ 'name', 'John' ], [ 'age', 30 ] ]
.
С помощью цикла for-of
мы перебираем элементы массива - в данном случае подмассивы. Мы можем деструктурировать подмассивы в цикле, используя const [x, y]
. x
равняется первому элементу в подмассиве, y
- второму. Первым подмассивом является [ "name", "John" ]
, где x
равняется name
, а y
- John
. Вторым подмассивом является [ "age", 30 ]
, где x
равняется age
, а y
- 30
.
Вопрос № 81
function getItems(fruitList, ...args, favoriteFruit) {
return [...fruitList, ...args, favoriteFruit]
}
console.log(getItems(["banana", "apple"], "pear", "orange"))
- A:
["banana", "apple", "pear", "orange"]
- B:
[ ["banana", "apple"], "pear", "orange" ]
- C:
["banana", "apple", ["pear"], "orange"]
- D:
Error
Ответ
Правильный ответ: D
...args
- это прочие параметры (оператор rest). Значение прочих параметров - это массив, содержащий неиспользованные аргументы и в этой связи передаваемый последним. В приведенном примере rest
является вторым аргументом. Это приводит к синтаксической ошибке.
function getItems(fruitList, favoriteFruit, ...args) {
return [...fruitList, ...args, favoriteFruit]
}
getItems(["banana", "apple"], "pear", "orange")
Данный код работает, как ожидается, и возвращает массив [ 'banana', 'apple', 'orange', 'pear' ]
.
Вопрос № 82
function nums(a, b) {
if
(a > b)
console.log('a больше')
else
console.log('b больше')
return
a + b
}
console.log(nums(4, 2))
console.log(nums(1, 2))
- A:
a больше, 6
иb больше, 3
- B:
a больше, undefined
иb больше, undefined
- C:
undefined
иundefined
- D:
Error
Ответ
Правильный ответ: B
В JavaScript
мы не обязаны явно указывать точку с запятой (;
), однако, интерпретатор автоматически добавляет их после операторов. Оператором могут быть переменные или ключевые слова, такие как throw
, return
, break
и др. В приведенном примере имеется оператор return
и выражение a + b
на новой строке. Поскольку это новая строка, движок не знает, что это значение, которое мы хотим вернуть. Он автоматически добавляет точку с запятой после return
. Это выглядит так: return; a + b
.
Это означает, что строка a + b
никогда не достигается, функция возвращает управление после ключевого слова return
. Если значение не возвращается явно, как в приведенном примере, функция возвращает undefined
. Обратите внимание, что после операторов if-else
точки с запятой автоматически не вставляются.
Вопрос № 83
class Person {
constructor() {
this.name = "John"
}
}
Person = class AnotherPerson {
constructor() {
this.name = "Jane"
}
}
const member = new Person()
console.log(member.name)
- A:
John
- B:
Jane
- C:
Error
- D:
undefined
Ответ
Правильный ответ: B
Мы можем установить классы равными другим классам/функциям-конструкторам. В данном случае мы устанавливаем класс Person
равным классу AnotherPerson
. Свойство name
этого конструктора имеет значение Jane
, поэтому свойство name
для нового экземпляра класса Person
member
- это также Jane
.
Вопрос № 84
const info = {
[Symbol("a")]: "b"
}
console.log(info)
console.log(Object.keys(info))
- A:
{ Symbol('a'): 'b' }
и["{Symbol('a')"]
- B:
{}
и[]
- C:
{ a: 'b' }
и['a']
- D:
{ Symbol('a'): 'b' }
и[]
Ответ
Правильный ответ: D
Symbol
не является перечисляемым (enumerable: false
). Метод keys
возвращает все перечисляемые ключи объекта. Symbol
не просматривается таким способом, поэтому возвращается пустой массив. При выводе в консоль объекта будут видны все его свойства, даже не перечисляемые. Это одно из качеств символа: помимо представления совершенно уникального значения (которое предотвращает случайное пересечение имен в объектах, например, при работе с 2 библиотеками, которые хотят добавить свойства с одинаковыми именами к одному и тому же объекту). Мы также можем "скрыть" свойства объектов таким способом (хотя и не полностью: мы можем получить доступ к символам с помощью Object.getOwnPropertySymbols()
).
Вопрос № 85
const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name; age: user.age }
const list = [1, 2, 3, 4]
const user = { name: "John", age: 30 }
console.log(getList(list))
console.log(getUser(user))
- A:
[1, [2, 3, 4]]
иundefined
- B:
[1, [2, 3, 4]]
и{ name: "John", age: 30 }
- C:
[1, 2, 3, 4]
и{ name: "John", age: 30 }
- D:
null
и{ name: "John", age: 30 }
Ответ
Правильный ответ: A
Функция getList
принимает массив в качестве аргумента. В getList()
мы деструктурируем этот массив. Это выглядит так: [x, ...y] = [1, 2, 3, 4]
.
С помощью rest-оператора ...y
мы помещаем прочие аргументы (все аргументы, кроме первого) в массив. Такими аргументами являются 2, 3 и 4
. Значением переменной y
является массив, содержащий прочие параметры. В данном случае значение x
равно 1
, поэтому, в консоль попадает [x, y]
, т.е. [1, [2, 3, 4]]
.
Функция getUser
в качестве аргумента принимает нечто, похожее на объект (обратите внимание, что свойства "объекта" разделяются ;
, а не ,
). В случае стрелочных функций мы можем обойтись без фигурных скобок, если возвращаем только одно значение. Однако, если мы хотим вернуть объект из стрелочной функции, то должны указать его в круглых скобках, в противном случае, при разборе кода, когда движок встретит ,
будет выброшено исключение SyntaxError
. Такая функция вернула бы объект: const getUser = user => ({ name: user.name, age: user.age })
.
Поскольку "свойства" разделены ;
и отсутствует оператор return
, функция возвращает undefined
.
Вопрос № 86
const name = "John"
console.log(name())
- A:
SyntaxError
- B:
ReferenceError
- C:
TypeError
- D:
undefined
Ответ
Правильный ответ: C
Переменная name
содержит строку, которая не является функцией, поэтому не может быть вызвана. TypeError
возникает, когда значение не соответствует ожидаемому типу. Движок JavaScript
ожидает, что значением переменной name
является функция, так как мы пытаемся ее вызвать. Однако, значением name
является строка, поэтому выбрасывается исключение TypeError: name is not a function
(name
не является функцией). SyntaxError
генерируются, когда мы написали нечто недопустимое с точки зрения JavaScript
, например, когда ключевое слово return
написано как retrun
. ReferenceError
генерируются, когда JavaScript
не может найти ссылку на значение, к которому мы обращаемся.
Вопрос № 87
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 || true)
: пустой массив ([]
) является истинным значением. Это первое истинное значение, которое и возвращается. Переменная three
имеет значение []
.
Вопрос № 88
const myPromise = () => Promise.resolve('I have resolved!')
function firstFunction() {
myPromise().then(res => console.log(res))
console.log('first')
}
async function secondFunction() {
console.log(await myPromise())
console.log('second')
}
firstFunction()
secondFunction()
- A:
I have resolved! first
иI have resolved! second
- B:
first I have resolved!
иsecond I have resolved!
- C:
I have resolved! second
иfirst I have resolved!
- D:
first I have resolved!
иI have resolved! second
Ответ
Правильный ответ: D
С промисами дело обстоит следующим образом: "Я хочу отложить выполнение этой функции, поскольку это может занять некоторое время" (promise переводится как "обещание"). Только когда промис выполнен или отклонен (разрешен), и когда стек вызовов (call stack) пуст, я хочу получить возвращаемое им значение. Мы можем получить значение с помощью ключевого слова then
или await
в асинхронной функции. Эти ключевые слова работают по-разному. В firstFunction()
мы (вроде бы) приостановили выполнение функции myPromise
, и продолжили выполнение другого кода, в данном случае console.log('first')
. Затем функция разрешается строкой I have resolved!
, которая выводится в консоль после освобождения стека вызовов. С помощью ключевого слова await
в secondFunction()
мы пр иостанавливаем выполнение асинхронной функции до тех пор, пока промис не будет разрешен. Это означает, что мы ожидаем разрешения myPromise()
со значением I have resolved!
, и только после того, как это произошло, мы переходим к следующей строке. Поэтому строка second
выводится в консоль последней.
Вопрос № 89
const set = new Set()
set.add(1)
set.add("John")
set.add({ name: "John" })
for (let item of set) {
console.log(item + 2)
}
- A:
3 NaN NaN
- B:
3 7 NaN
- C:
3 John2 [object Object]2
- D:
"12" John2 [object Object]2
Ответ
Правильный ответ: C
Оператор +
используется не только для сложения чисел, но и для объединения (конкатенации) строк. Всякий раз, когда движок JavaScript
видит, что одно или несколько значений не являются числом, он приводит число к строке. Первым значением является 1
- число. Выражение 1 + 2
возвращает 3
. Вторым значением является John
. John
является строкой, а 2
- числом: 2
приводится к строке. John
и 2
объединяются, что приводит к John2
. { name: "John" }
является объектом. Ни число, ни объект не являются строкой, поэтому они приводятся к строке. Когда объект приводится к строке он превращается в [object Object]
. [object Object]
, объединенный с 2
, становится [object Object]2
.
Вопрос № 90
console.log(Promise.resolve(5))
- A:
5
- B:
Promise {<pending>: 5}
- C:
Promise {<resolved>: 5}
- D:
Error
Ответ
Правильный ответ: C
Мы можем передавать в Promise.resolve()
любой тип данных. Данный метод возвращает промис с разрешенным значением. Если мы передадим ему обычную функцию, промис разрешится с обычным значением. Если мы передадим промис, промис разрешится с разрешенным значением переданного промиса. В данном случае мы передаем Promise.resolve()
число 5
. Поэтому возвращается разрешенный промис со значением 5
.
Вопрос № 91
function compareMembers(person1, person2 = person) {
if (person1 !== person2) {
console.log("Не одинаковые!")
} else {
console.log("Одинаковые!")
}
}
const person = { name: "Игорь" }
compareMembers(person)
- A:
"Не одинаковые!"
- B:
"Одинаковые!"
- C:
Error
- D:
undefined
Ответ
Правильный ответ: B
Объекты в JavaScript
передаются по ссылке. Когда мы проверяем объекты на строгое равенство (идентичность) с помощью оператора ===
, мы сравниваем их ссылки. Мы устанавливаем значение по умолчанию для параметра person2
, равное объекту person
, и передаем объект person
в качестве значения для параметра person1
. Это означает, что оба параметра содержат ссылку на одно и то же место в памяти, п оэтому они равны. Выполняется код в блоке else
, и в консоль выводится Одинаковые!
.
Вопрос № 92
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:
Error
Ответ
Правильный ответ: D
В JavaScript
у нас есть два способа получить доступ к свойствам объекта: скобочная нотация и точечная нотация. В данном случае, мы используем точечную нотацию (colorConfig.colors
) вместо скобочной (colorConfig["colors"]
). При точечной нотации движок пытается найти свойство объекта с указанным именем. В приведенном примере JavaScript
пытается найти свойство colors
в объекте colorConfig
. Такого свойства не существует, поэтому возвращается undefined
. Затем мы пытаемся получить доступ к значению первого элемента массива, используя [1]
. Мы не можем сделать этого для undefined
, поэтому выбрасывается исключение TypeError: Cannot read property '1' of undefined
. JavaScript
интерпретирует (распаковывает) операторы. Когда мы используем скобочную нотацию, JavaScript
видит открывающуюся скобку ([
) и продолжает разбирать код, пока не встретит закрывающуюся скобку (]
). Только после этого выра жение оценивается. Если бы мы использовали colorConfig[colors[1]]
, то вернулось бы значение свойства red
объекта colorConfig
.
Вопрос № 93
console.log('❤️' === '❤️')
- A:
true
- B:
false
- C:
undefined
- D:
Error
Ответ
Правильный ответ: A
Смайлики - это юникоды. Юникод для сердца - U+2764 U+FE0F
. Юникоды одинаковы для одних и тех же смайликов. Таким образом, мы сравниваем две одинаковые строки, поэтому возвращается true
.
Вопрос № 94
const food = ['🍕', '🍫', '🍳', '🍔']
const info = { favoriteFood: food[0] }
info.favoriteFood = '🍝'
console.log(food)
- A:
['🍕', '🍫', '🍳', '🍔']
- B:
['🍝', '🍫', '🍳', '🍔']
- C:
['🍝', '🍕', '🍫', '🍳', '🍔']
- D:
undefined
Ответ
Правильный ответ: A
Мы устанавливаем значение свойства favoriteFood
объекта info
равным строке 🍕
. Строка является примитивным типом данных. В JavaScript
примитивные типы данных (все, что не является объектом) передаются по значению. Затем мы меняем значение свойства favoriteFood
. Массив food
не изменился, поскольку значение favoriteFood
было скопировано из значения первого элемента в массиве и не имеет ссылки на то же место в памяти, что и food[0]
. Поэтому в консоль выводится исходный массив ['🍕', '🍫', '🍳', '🍔']
.
Вопрос № 95
let name = 'John'
function getName() {
console.log(name)
let name = 'Jane'
}
getName()
- A:
John
- B:
Jane
- C:
undefined
- D:
Error
Ответ
Правильный ответ: D
Каждая функция имеет собственный контекст выполнения (или область видимости). Функция getName
сначала ищет переменную name
в собственном контексте (области видимости). getName()
содержит переменную name
: мы объявляем переменную name
с помощью ключевого слова let
и присваиваем ей значение Jane
. Переменные, объявленные с помощью ключевых слов let
и const
не поднимаются в начало области видимости (в данном случае функции), в отличие от переменных, объявленных с помощью ключевого слова var
. Они недоступны до инициализации (присваивания им значения). Это называется "временной мертвой зоной". Когда мы пытаемся получить доступ к таким переменным, JavaScript
выбрасывает исключение ReferenceError
. Если бы мы не объявили переменную name
в функции getName
, движок продолжал бы поиск переменной по цепочке областей видимости. Внешняя область видимости содержит переменную name
со значением John
. В этом случае в консоль было бы выведено John
.
Вопрос № 96
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
иa
- B:
a
иundefined
- C:
['a', 'b', 'c']
иa
- D:
a
и['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*
. Это означает, что первое значение равняется первому значению итератора. Итератор - это массив ['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
Вопрос № 97
console.log(`${(x => x)('Я люблю')} писать код`)
- A:
Я люблю писать код
- B:
undefined писать код
- C:
${(x => x)('Я люблю') писать код
- D:
Error
Ответ
Правильный ответ: A
Выражения внутри шаблонных литералов оцениваются первыми. Это означает, что строка будет содержать значение выражения - в данном случае значение немедленно вызываемого функционального выражения (IIFE) (x => x)('Я люблю')
. Мы передаем значение Я люблю
в качестве аргумента стрелочной функции x => x
. Аргумент x
имеет значение Я люблю
, которое и возвращается. Это приводит к Я люблю писать код
.
Вопрос № 98
const person = {
name: "John",
age: 29
}
const changeAge = (x = { ...person }) => x.age += 1
const changeAgeAndName = (x = { ...person }) => {
x.age += 1
x.name = "Jane"
}
changeAge(person)
changeAgeAndName()
console.log(person)
- A:
{ name: "Jane", age: 30 }
- B:
{ name: "Jane", age: 31 }
- C:
{ name: "John", age: 30 }
- D:
{ name: "John", age: 31 }
Ответ
Правильный ответ: C
Функции changeAge
и changeAgeAndName
имеют параметры по умолчанию, а именно: вновь созданный объект { ...person }
. Этот объект имеет копии всех ключей/значений объекта person
. Сначала мы вызываем changeAge()
и передаем ей объект person
в качестве аргумента. Эта функция увеличивает значение свойства age
на 1
. person
теперь равняется { name: 'John', age: 30 }
. Затем мы вызываем changeAgeAndName()
без аргументов. Поэтому значение аргумента x
равняется новому объекту { ...person }
. Поскольку это новый объект, он не влияет на свойства исходного объекта person
. Таким образом, person
по-прежнему равняется { name: 'John', age: 30 }
.
Вопрос № 99
function sumValues(x, y, z) {
return x + y + z // 6
}
- 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
. Для того, чтобы эта функция вернула 6
, ей в качестве аргумента необходимо передать ...[1, 2, 3]
.
Вопрос № 100
let num = 1
const list = ['a', 'b', 'c', 'd']
console.log(list[(num += 1)])
- A:
b
- B:
c
- C:
Error
- D:
undefined
Ответ
Правильный ответ: B
С помощью оператора +=
мы увеличиваем значение переменной num
на 1
. Начальным значением num
является 1
, выражение 1 + 1
оценивается как 2
. Элементом массива со вторым индексом является c
, что и выводится в консоль.
Вопрос № 101
const person = {
firstName: 'John',
lastName: 'Smith',
pet: {
name: 'Rex',
},
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
const member = {}
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:
Rex undefined John Smith undefined
- C:
Rex null John Smith null
- D:
Error
Ответ
Правильный ответ: B
Благодаря оператору опциональной последовательности (?.
) нам больше не нужно предварительно определять наличие глубоко вложенных свойств. Если мы попытаемся получить доступ к свойству значения undefined
или null
, выражение вернет undefined
. person.pet?.name
: объект person
имеет свойство pet
, pet
имеет свойство name
- возвращается Rex
. person.pet?.family?.name
: объект person
имеет свойство pet
, pet
не имеет свойства family
- возвращается undefined
. person.getFullName?.()
: объект person
имеет метод getFullName
- возвращается John Smith
. member.getLastName?.()
: объект member
не имеет метода getLastName
, возвращается undefined
.
Вопрос № 102
const groceries = ['банан', 'яблоко', 'апельсин']
if (groceries.indexOf('банан')) {
console.log('Нам нужно купить бананы!')
} else {
console.log('Нам не нужно покупать бананы!')
}
- A:
"Нам нужно купить бананы!"
- B:
"Нам не нужно покупать бананы!"
- C:
undefined
- D:
1
Ответ
Правильный ответ: B
Условие groceries.indexOf('banana')
возвращает значение 0
, которое является ложным. Поскольку условие не удовлетворяется, выполняется код в блоке else
, в консоль выводится Нам не нужно покупать бананы!