200 теоретических вопросов по JavaScript

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.


Доброго времени суток, друзья!

Представляю вашему вниманию список из второй сотни вопросов по основам JavaScript из этого репозитория с краткими ответами и ссылками на «Современный учебник по JavaScript» Ильи Кантора (JSR) и MDN.

Данный список, а также 300+ практических вопросов доступны в моем приложении.

В приложении реализован механизм запоминания изученного вопроса, а также обеспечена работа в оффлайн-режиме.

Приношу извинения за возможные ошибки и опечатки. Приветствуется любая форма обратной связи.

Редакция от 14.09.

Первые 100 вопросов смотрите здесь.

101. Для чего используется stopPropagation()?


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

<div onclick="f2()">
    <div onclick="f1()"></div>
</div>

function f1(event) {
    event.stopPropagation()
    console.log('Внутренний контейнер')
}

function f2() {
    console.log('Внешний контейнер')
}

При клике по вложенному контейнеру в консоль выводится сообщение «Внутренний контейнер». Если убрать event.stopPropagation(), то при клике по вложенному контейнеру, в консоль будут выведены оба сообщения.

JSR
MDN

102. Что делает инструкция return false?


Данная инструкция используется в обработчиках событий для:

  • Отмены стандартного поведения браузера
  • Предотвращения распространения события по DOM
  • Остановки выполнения колбэка и возврата управления вызвавшей его функции

Обратите внимание: без указания возвращаемого значения оператор return возвращает undefined.

JSR
MDN

103. Что такое BOM?


BOM или (Browser Object Model — объектная модель браузера) позволяет JavaScript взаимодействовать с браузером. Данная модель включает в себя такие объекты, как navigator, location, history, screen, XMLHttpRequest и т.п. Другими словами, BOM — это дополнительные объекты, предоставляемые браузером, чтобы работать со всем, кроме документа.
Обратите внимание: BOM не стандартизирована, поэтому ее реализация может отличаться в разных браузерах.



JSR

104. Для чего используется setTimeout()?


Данный метод используется для отложенного выполнения задачи. Другими словами, он позволяет запустить выполнение функции или вычисление выражения через определенное время (в миллисекундах). В следующем примере мы выводим сообщение в консоль через 2 секунды:

setTimeout(() => console.log('Привет!'), 2000)

// во избежание утечек памяти, рекомендуется делать так
const timer = setTimeout(() => {
    console.log('Привет!')
    clearTimeout(timer)
}, 2000)

JSR
MDN

105. Для чего используется setInterval()?


Данный метод используется для периодического выполнения задачи. Другим словами, он позволяет запускать выполнение функции или вычисление выражения через определенный промежуток времени (в миллисекундах). В следующем примере мы выводим сообщение в консоль каждые 2 секунды:

setInterval(() => console.log('Привет!'), 2000)

// во избежание утечек памяти, не забывайте отключать таймер
// после достижения поставленной цели
let i = 0
const timer = setInterval(() => {
    console.log('Привет!')
    i++

    if (i == 2) {
        clearInterval(timer)
    }
}, 2000)

Во втором примере сообщение «Привет!» выведется в консоль два раза, после чего таймер будет остановлен

JSR
MDN

106. Почему JavaScript называют однопоточным (single threated)?


JavaScript является однопоточным или синхронным языком программирования. Это означает, что в один момент времени может выполняться только одна задача. Если задача является сложной, ее выполнение может занять продолжительное время и все это время основной поток выполнения кода будет заблокирован. Блокировка потока, в свою очередь, означает отсутствие интерактивности на странице. Браузер перестает реагировать на действия пользователя и другие события. Для решения данной проблемы применяются колбэки, промисы, async/await, воркеры и другие инструменты для работы с асинхронным кодом. В JavaScript в отличие, например, от Java, Go или C++ нет возможности создавать дополнительные потоки или процессы.

JSR
MDN

107. Что такое делегирование событий (event delegation)?


Делегирование событий — это техника, при которой событие регистрируется на родительском элементе для обработки событий, вызываемых дочерними элементами.
Часто применяется для обработки нажатия кнопок в группирующем контейнере или изменения полей для ввода текста в формах, например:

<form>
    <input type="text" class="first-input">
    <input type="text" class="second-input">
</form>

<div>
    <button class="first-button">click</button>
    <button class="second-button">click</button>
</div>

const form = document.querySelector('form')
const buttons = document.querySelector('div')

form.addEventListener('input', event => {
    console.log(event.target.className)
})

buttons.addEventListener('click', event => {
    console.log(event.target.className)
})

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

JSR

108. Что такое ECMAScript?


ECMAScript — это язык программирования, лежащий в основе JavaScript. Это своего рода шаблон или схема, по которой «строится» JavaScript. ECMAScript стандартизирован в спецификации ECMA-262 организацией по стандартам Ecma International.

JSR
MDN

109. Назовите особенности синтаксиса JSON


Синтаксис JSON имеет следующие особенности:

  • Данные представляют собой пары ключ/значение
  • Ключ и значение оборачиваются в двойные кавычки, кроме случаев, когда значение является числом («key»: «value»)
  • Данные разделяются запятыми
  • Объекты оборачиваются в фигурные скобки
  • Массивы — в квадратные

JSR
MDN

110. Что делает JSON.stringify()?


При отправке данных на сервер, они должны иметь специальный строковый формат. Для преобразования объекта в строку в формате JSON используется метод JSON.stringify():

const user = { name: 'Ванька', age: 30 }
const str = JSON.stringify(user)
console.log(str) // {"name":"Ванька","age":30}

JSR
MDN

111. Что делает JSON.parse()?


При получении данных от сервера, они имеют специальный строковый формат. Для преобразования этих данных в JavaScript объект используется метод JSON.parse():

const str = { "name":"Ванька","age":30 }
const user = JSON.parse(str)
console.log(user) // {name: "Ванька", age: 30}

JSR
MDN

112. Зачем нужен JSON?


При обмене данными между клиентом и сервером, эти данные могут быть только строками. Поскольку JSON — это текст, он прекрасно для этого подходит. Также он может использоваться как формат для данных любым языком программирования, наряду с другими форматами, такими как XML или Protobuf.

JSR
MDN

113. Что такое PWA (Progressive Web Application — прогрессивное веб-приложение)?


Если кратко, то PWA — это веб-сайты, которые ведут себя подобно нативным приложениям. Они могут быть установлены на телефон или компьютер, а также, как правило, работают в оффлайне. Для последнего используются сервис-воркеры и интерфейс кэширования. Преимуществом PWA перед мобильными приложениями является их размер и относительная легкость разработки. Также не нужно тратить ресурсы на создание двух приложений для одного сайта — веб и мобильного. При этом сохраняется хороший пользовательский опыт.

MDN

114. Для чего используется clearTimeout()?


Данный метод используется для остановки таймера, запущенного с помощью setTimeout(). Для этого идентификатор таймера записывается в переменную, которая затем передается clearTimeout() в качестве аргумента.

const timer = setTimeout(() => {
    console.log('Привет!')
    clearTimeout(timer)
}, 2000)

В приведенном примере через две секунды в консоль выводится сообщение «Привет!», после чего таймер останавливается. Это делается для того, чтобы сборщик мусора мог удалить выполненный таймер.

JSR
MDN

115. Для чего используется clearInterval()?


Данный метод используется для остановки таймера, запущенного с помощью setInterval(). Для этого идентификатор таймера записывается в переменную, которая затем передается clearInterval() в качестве аргумента.

let i = 1
const timer = setInterval(() => {
    console.log(i)
    i++

    if (i === 3) clearInterval(timer)
}, 1000)

В приведенном примере в консоль каждую секунду выводится значение переменной i, которое каждый раз увеличивается на 1 (1, 2). Когда значение i становится равным 3, таймер останавливается.

JSR
MDN

116. Как выполнить перенаправление?


Для этого можно использовать свойство location объекта window:

location.href = 'newPage.html'
// или
location.replace('newPage.html')
// или
location.assign('newPage.html')

MDN

117. Как проверить, существует ли подстрока в строке?


Существует, как минимум, три способа это сделать.
String.prototype.includes()

const mainStr = 'hello'
const subStr = 'hel'
mainStr.includes(subStr) // true

String.prototype.indexOf()

const mainStr = 'hello'
const subStr = 'hel'
mainStr.indexOf(subStr) !== -1 // true

RegExp

const mainStr = 'hello'
const regex = /hel/
regex.test(mainStr) // true

JSR
MDN — includes
MDN — indexOf
MDN — test

118. Как проверить корректность адреса электронной почты?


Это можно сделать средствами HTML, установив тип поля для ввода в значение email (<input type=«email»>). Однако, данный способ считается не очень надежным. Поэтому, обычно, email валидируется с помощью регулярного выражения. Это рекомендуется делать на стороне сервера, поскольку на клиенте может быть отключен JavaScript:

const validateEmail = email =>
    /S+@S+.S+/
        .test(email.toString()
        .toLowerCase())
const email = 'myemail@example.com'
validateEmail(email) // true

В приведенном примере используется одно из самых простых регулярных выражений для валидации адреса электронной почты. Более надежное выражение выглядит так (RFC 2822): [a-z0-9!#$%&'*+/=?^_\`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

119. Как получить текущий URL?


Для этого можно использовать свойство location объекта window или свойство URL объекта document:

console.log('Текущий URL', location.href)
console.log('Текущий URL', document.URL) // в Chrome в пустой вкладке получаем "Текущий URL chrome-search://local-ntp/local-ntp.html"

MDN — location
MDN — document.URL

120. Какие свойства имеет объект location?


Свойства объекта location могут использоваться для получения частей URL текущей страницы:

  • href — полный URL
  • origin — протокол, хост и порт (источник, используется в Политике общего происхождения (SOP) и Совместном использовании ресурсов (CORS))
  • protocol
  • host — хост и порт
  • hostname — хост
  • port
  • pathname — путь
  • search — строка запроса после ?
  • hash — строка запроса после # (якоря)
  • username — имя пользователя перед доменом
  • password — пароль перед доменом

MDN

121. Как получить строку запроса?


Для этого можно использовать конструктор URL:

const url = new URL('https://example.com?foo=1&bar=2')
console.log(url.search) // ?foo=1&bar=2
console.log(url.searchParams.get('foo')) // 1

MDN

122. Как проверить, существует ли свойство в объекте?


Для этого существует, как минимум, три способа.
Оператор in

const user = { name: 'Ванька' }
console.log('name' in user) // true
console.log(!('age' in user)) // true

Метод hasOwnProperty()

const user = { name: 'Ванька' }
console.log(user.hasOwnProperty('name')) // true
console.log(!user.hasOwnProperty('age')) // true

Сравнение с undefined

const user = { name: 'Ванька' }
console.log(user.name !== undefined) // true
console.log(user.age === undefined) // true

JSR
MDN — for...in
MDN — hasOwnProperty

123. Как перебрать перечисляемые свойства объекта?


Для этого можно использовать цикл for...in совместно с методом hasOwnProperty() для исключения унаследованных свойств.

const user = {
    name: 'Ванька',
    age: 30
}

for (key in user) {
    if (user.hasOwnProperty(key)) {
        console.log(\`${key}: ${user[key]}\`) // name: Ванька age: 30
    }
}

JSR
MDN

124. Как проверить, что объект является пустым?


Для этого существует, как минимум, три способа.
Метод Object.entries()

const obj = {}
console.log(Object.entries(obj).length === 0) // true
// для исключения из проверки объекта Date
const obj2 = new Date()
console.log(Object.entries(obj2).length === 0 && obj2.constructor === Object) // false

Метод Object.keys()

const obj = {}
console.log(Object.keys(obj).length === 0) // true
// для исключения из проверки объекта Date
const obj2 = new Date()
console.log(Object.keys(obj2).length === 0 && obj2.constructor === Object) // false

Цикл for...in и метод Object.hasOwnProperty()

const obj = {}
const obj2 = {key: 'value'}

const isEmpty = obj => {
    for (key in obj) {
        if (obj.hasOwnProperty(key)) return false
    }
    return true
}

console.log(isEmpty(obj)) // true
console.log(isEmpty(obj2)) // false

JSR — Объекты
JSR — Object.keys, values, entries
MDN — Object.entries
MDN — Object.keys
MDN — for...in
MDN — Object.hasOwnProperty

125. Что такое объект arguments?


arguments — это массивоподобный объект (псевдомассив), содержащий переданные функции аргументы:

function sum () {
    let total = 0
    for (let i = 0; i < arguments.length; i++) {
        total += arguments[i]
    }
    return total

    // или
    let total = 0
    for (const i of arguments) {
        total += i
    }
    return total

    // или
    return Array.from(arguments).reduce((acc, cur) => acc + cur)

}

sum(1, 2, 3) // 6

Обратите внимание, что стрелочные функции не имеют arguments. Вместо arguments рекомендуется использовать оператор rest… (прочие параметры), который работает как в обычных, так и в стрелочных функциях:

const sum = (...rest) => rest.reduce((acc, cur) => acc + cur)

sum(1, 2, 3) // 6

JSR
MDN

126. Как сделать первую букву строки заглавной?


Это можно сделать с помощью методов charAt(), toUpperCase() и slice():

String.prototype.capitilize = function () {
    return this.charAt(0).toUpperCase() + this.slice(1)
}

console.log('hello'.capitilize()) // Hello

JSR
MDN — charAt
MDN — toUpperCase
MDN — slice

127. Как получить текущую дату?


Это можно сделать с помощью объекта Date или конструктора Intl.DateTimeFormat:

console.log(new Date().toLocaleDateString()) // 02.09.2020

console.log(new Intl.DateTimeFormat(
    'ru-Ru',
    {
        weekday: 'long',
        day: 'numeric',
        month: 'long',
        year: 'numeric'
    }
).format(new Date())) // среда, 2 сентября 2020 г.

JSR — Date
JSR = Intl
MDN — Date
MDN — Intl.DateTimeFormat

128. Как сравнить два объекта Date?


Для этого следует сравнивать не сами объекты, а, например, значения, возвращаемые методом getTime():

const d1 = new Date()
const d2 = new Date(d1)

console.log(d1.getTime() === d2.getTime()) // true
console.log(d1 === d2) // false

JSR
MDN

129. Как проверить, что строка начинается с другой строки?


Для этого можно использовать встроенный метод startsWith():

console.log('Good morning'.startsWith('Good')) // true
console.log('Good morning'.startsWith('morning')) // false

По данным CanIUse данный метод поддерживает почти 94% браузеров

JSR
MDN

130. Как удалить проблемы в строке?


Для этого можно использовать встроенные методы trimStart() (начало строки), trimEnd() (конец строки) и trim() (начало и конец строки):

console.log('  hello world   '.trim()) // hello world

trim не работает для пробелов между словами. В этом случае можно воспользоваться методом replace() и регулярным выражением:

console.log('hello   world'.replace(/s+/, ' ')) // hello world
// можно уточнить количество пробелов
console.log('hello   world'.replace(/s{2,}/, ' ')) // hello world
console.log('key   value'.replace(/s{2,}/, ' -> ')) // key -> value

По данным CanIUse методы trimStart() и trimEnd() поддерживает 93% браузеров.

MDN

131. Как добавить новое свойство в объект?


Существует два способа это сделать. Предположим, что у нас есть такой объект:

const obj = {
    name: 'Ванька',
    age: 30
}

Мы можем добавить в него новое свойство, использую либо точечную, либо скобочную нотацию:

obj.job = 'разработчик'
obj['job'] = 'разработчик'

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

const obj = {}
obj[1] = 'один'
console.log(obj) // { 1: 'один' }
obj.2 = 'два' // SyntaxError: Unexpected number

JSR
MDN

132. Является ли выражение !-- специальным оператором?


Нет, не является. Это комбинация двух операторов: оператора! (логическое не) и оператора — (декремент). Если использовать указанное выражение с каким-либо значением, то сначала это значение будет уменьшено на единицу, затем преобразовано в логический тип и инвертировано:

const fun = val => !--val
const a = 1
const b = 2
console.log(fun(a)) // !0 -> not false -> true
console.log(fun(b)) // !1 -> not true -> false

JSR
MDN — Logical NOT
MDN — Decrement

133. Как присвоить переменной значение по умолчанию?


Для этого можно использовать оператор || (логическое или):

const a = b || 'default'

В данном случае переменной a будет присвоено значение default в случае, если значение переменной b будет ложным (false, undefined, null, NaN, 0, '').
Если речь идет о стандартных значениях параметров функции, то их можно присвоить следующим образом:

const greet = (name = 'незнакомец') => \`Привет, ${name}!\`
console.log(greet('Ванька')) // Привет, Ванька!
console.log(greet()) // Привет, незнакомец!

Более того, последующие параметры могут использовать значения предыдущих в качестве стандартных значений:

const sum = (a = 1, b = a + 2) => a + b
console.log(sum()) // 4

JSR
MDN

134. Как создать многострочную строку?


Раньше это делали примерно так (конкатенация и управляющие символы переноса строки):

const str =
    'Аз есмь' + ' ' +
    'очень длинная' + ' ' +
    'строка!'

// или
const str = 'Аз есмь a
 очень длинная
 строка!'
console.log(str)
/*
    Аз есмь
    очень длинная
    строка!
*/

Сейчас это делают так (шаблонный литерал):

const str =
    \`Аз есмь
    очень длинная
    строка!\`

JSR
MDN

135. Можем ли мы добавлять свойства функциям?


Поскольку функции — это тоже объекты, мы вполне можем добавлять им свойства. Значением свойства функции может быть другая функция:

function someFun () {}
someFun.somePropName = 'somePropValue'

console.log(someFun.somePropName) // somePropValue
// дефолтное свойство
console.log(someFun.name) // someFun

const sum = (x, y) => x + y
console.log(sum(1, 2)) // 3

sum.curry = x => y => x + y
console.log(sum.curry(1)(2)) // 3

JSR
MDN

136. Как узнать, сколько аргументов ожидает получить функция?


Для этого можно использовать свойство length:

const sum = (a, b, c) => +a + +b + +c
console.log(sum(1, '1', true)) // 3
console.log(sum(0, '', [])) // 0

console.log(sum.length) // 3

MDN

137. Что такое полифил (polyfill)?


Полифилы используются для обеспечения работы современного JavaScript-кода в старых браузерах. Это делается за счет реализации новых возможностей языка на старом синтаксисе. Сам процесс преобразования нового кода в старый называется транспиляцией. Самым популярным транспилятором JavaScript-кода является Babel.
Например, одной из последних возможностей JavaScript является метод Promise.allSettled(), который, в отличие от Promise.all(), не завершается при отклонении любого из переданных ему промисов.
Однако, на сегодняшний день его поддержка браузерами по данным CanIUse составляет 80%, поэтому нужен полифил:

const promise1 = Promise.resolve('promise1')
const promise2 = Promise.reject('promise2')
const promise3 = Promise.resolve('promise3')

// вот как выглядит встроенный Promise.allSettled()
Promise
    .allSettled([promise1, promise2, promise3])
    .then(console.log)
/*
    [
        {status: "fulfilled", value: "promise1"},
        {status: "rejected", reason: "promise2"},
        {status: "fulfilled", value: "promise3"},
    ]
*/

// а вот его полифил
// поддержка Promise.all() = 94%
const allSettled = promises => {
    const wrappedPromises = promises
        .map(p => Promise.resolve(p)
        .then(
            val => ({
                status: 'fulfilled',
                value: val
            }),
            err => ({
                status: 'rejected',
                reason: err
            })))
    return Promise.all(wrappedPromises)
}
allSettled([promise1,promise2,promise3])
    .then(console.log)

JSR
MDN

138. Для чего используются операторы continue и break?


Оператор break используется для выхода из цикла. После остановки итерации код выполняется дальше:

const obj = {
    1: 'Everything',
    2: 'is',
    3: 'impossible'
}

for (key in obj) {
    if (obj[key] === 'impossible') break

    console.log(obj[key]) // Everything is
}

console.log('possible') // possible

Оператор continue используется для пропуска итерации:

const obj = {
    1: 'Everything',
    2: 'is',
    3: 'impossible',
    4: 'possible'
}

for (key in obj) {
    if (obj[key] === 'impossible') continue

    console.log(obj[key]) // Everything is possible
}

MDN — break
MDN — continue

139. Что такое метка (label)?


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

loop1:
for (let i = 0; i < 3; i++) {
    loop2:
    for (let j = 0; j < 3; j++) {
        if (i === j) continue loop1

        console.log(\`i = ${i}, j = ${j}\`)
    }
}

/*
    i = 1, j = 0
    i = 2, j = 0
    i = 2, j = 1
*/

Использование меток считается плохой практикой.

MDN

140. В чем заключаются преимущества объявления переменных в начале кода?


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

  • Делает код чистым
  • Все переменные находятся в одном месте
  • Позволяет избежать случайного создания глобальных переменных
  • Предотвращает нежелательное переопределение переменных

JSR
MDN

141. В чем заключаются преимущества инициализации переменной при объявлении?


Рекомендуется инициализировать все переменные в момент объявления. Это дает следующие преимущества:

  • Делает код чистым
  • Переменные и их значения находятся в одном месте
  • Предотвращает присвоение неинициализированным переменным значения undefined

JSR
MDN

142. Назовите основные рекомендации по созданию объекта


Для создания объекта вместо конструктора объекта new Object() рекмондуется использовать скобочную нотацию {}. Также в зависимости от типа значения, рекомендуется использовать следующее:

  • строку, например, '' вместо new String()
  • число, например, 0 вместо new Number()
  • логическое значение, например, false вместо new Boolean()
  • [] вместо new Array()
  • // вместо new RegExp()
  • function (){} вместо new Function()

JSR
MDN

143. Как определить массив в формате JSON?


JSON-массив представляет собой массив JSON-объектов, например:

[
    { "name": "Ванька", "age": 30 },
    { "name": "Петька", "age": 20 }
]

JSR
MDN

144. Как реализовать функцию, возвращающую случайное целое число в заданном диапазоне?


Такую функцию можно реализовать с помощью методов Math.random() и Math.floor() объекта Math:

const getRandomInteger = (min, max) => Math.floor(min + Math.random() * (max + 1 - min))

JSR
MDN — Math.random()
MDN — Math.floor()

145. Что такое tree shaking (встряхивание дерева)?


Tree shaking — это удаление кода неиспользуемых модулей. Такие модули не включаются в окончательную сборку (бандл). Для того, чтобы сборщик модулей (бандлер) мог определить, какие модули используются, а какие нет, структура программы должна быть основана на ES6 модулях. Данная техника была популяризована бандлером Rollup.

MDN

146. Для чего используется tree shaking (встряхивание дерева)?


Tree shaking может существенно уменьшить размер сборки (бандла) за счет удаления из нее кода неиспользуемых модулей. Чем меньше размер сборки, тем выше производительность приложения. Tree shaking реализован в таких сборщиках модулей, как Rollup и Webpack.

MDN

147. Что такое регулярное выражение?


Регулярное выражение — это последовательность символов, формирующая поисковый шаблон. Этот шаблон может использоваться для поиска данных в тексте, например, подстроки в строке. Регулярные выражения широко используются многими языками программирования для операций поиска и замены текста. Общий шаблон регулярного выражения выглядит так:

/шаблон/модификатор

Пример:

const regex = /java/i
const str = 'JavaScript'
console.log(regex.test(str)) // true

Также для создания регулярного выражения можно использовать конструктор RegExp:

const regex = new RegExp('java', 'i')
const str = 'JavaScript'
console.log(regex.test(str)) // true

JSR
MDN

148. Какие методы используются в регулярных выражениях?


В регулярных выражениях используется два основных метода: exec() и test().
Метод exec() ищет совпадение с регулярным выражением в переданной ему в качестве аргумента строке. Поведение данного метода зависит от того, имеет ли регулярное выражение флаг g. Если нет, то возвращается первое совпадение. Если флаг g есть, то:

  • Вызов exec() возвращает первое совпадение и запоминает позицию после него в свойстве lastIndex.
  • Следующий такой вызов начинает поиск с позиции lastIndex, возвращает следующее совпадение и запоминает позицию после него в lastIndex.
  • Если совпадений больше нет, то exec() возвращает null, а для lastIndex устанавливается значение 0.

const str = 'Java и JavaScript - разные языки программирования'
const regex = /Java/g

let result
while (result = regex.exec(str)) {
    console.log(
        \`Найдено ${result[0]} на позиции ${result.index}\`
    )
}
/*
    Найдено Java на позиции 0
    Найдено Java на позиции 7
*/

Метод test() возвращает логическое значение в зависимости от того, найдено ли совпадение в строке:

const str = 'Я люблю JavaScript'

console.log(
    /Я люблю/.test(str) // true
)

JSR
MDN

149. Какие флаги используются в регулярных выражениях?


Флаг Описание
g глобальное сопоставление
i игнорирование регистра при сопоставлении
m сопоставление по нескольким строкам

const regex = /([а-яё]+)s([а-яё]+)/i
const str = 'Иван Иванов'
const newStr = str.replace(regex, '$2 $1')
console.log(newStr) // Иванов Иван

JSR
MDN

150. Какие специальные символы используются в регулярных выражениях?


Специальные символы, используемые в регулярных выражениях, можно разделить на несколько групп.
Основные символьные классы:
Символ Значение
\. любой символ, за некоторым исключением
\d цифра
\D не цифра
\w символ латиницы и нижнее подчеркивание
\W не символ латиницы и нижнее подчеркивание
\s пробельный символ
\S не пробельный символ
\ экранирование, например, \. — это точка

Наборы символов:
Символ Значение
[а-яёА-ЯЁ] любая буква русского алфавита
[^а-яёА-ЯЁ] любой символ, кроме букв русского алфавита

Границы:
Символ Значение
^ начало строки
$ конец строки
\b граница слова нулевой ширины
\B граница слова ненулевой ширины

Группировка:
Символ Значение
(x) сопоставляется с x, сопоставление запоминается
(?:x) сопоставляется с x, сопоставление не запоминается

Квантификаторы:
Символ Значение
* ноль и более символов
+ один и более символов
*? и +? аналогично * и +, но ищется минимальное совпадение
? ноль или один символ
x(?=y) сопоставляется с x, если за x следует y
x(?!y) сопоставляется с x, если за x не следует y
(?<=y)x сопоставляется с x, если x предшествует y
(?!y)x сопоставляется с x, если x не предшествует y
x|y x или y
x{n} n — точное количество x
x{n,} n — минимальное количество x
x{n,m} n — минимальное количество x, m — максимальное (от, до)

JSR
MDN

151. Как изменить стили HTML-элемента?


Это можно сделать либо с помощью свойства style, либо присвоив элементу соответствующий класс:

document
    .querySelector(selector)
    .style.property = value
document
    .querySelector('title')
    .fontSize = '2rem'

document.querySelector(selector)
    .className = 'class-name'
document.querySelector(selector)
    .classList.add('class-name')
document.querySelector('button')
    .classList.add('active')

JSR
MDN — style
MDN — className
MDN — classList

152. Что такое debugger (отладчик)?


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

const fun = () => {
    // магия
    debugger // в этом месте выполнение функции будет приостановлено
    // магия
}

JSR
MDN

153. Для чего используются контрольные точки debugger (отладчика)?


Контрольные точки используются для приостановки выполнения функции или другого кода в определенном месте с целью выяснения причин неправильной работы программы. После остановки выполнение функции может быть продолжено.

JSR
MDN

154. Можно ли использовать зарезервированные слова в качестве идентификаторов?


Нет, использовать зарезервированные слова в качестве названий переменных, меток, функций или объектов нельзя:

const class = 'Первый раз в первый класс' // SyntaxError: Unexpected token 'class'

155. Как определить ширину и высоту изображения?


Это можно сделать разными способами. Вот один из них:

const getImgSize = src => {
    const img = new Image()
    img.src = src
    img.addEventListener('load', () => console.log(\`${img.width} x ${img.height}\`)) // 276 x 110
    document.body.append(img)
}
getImgSize('http://www.google.com/ intl/en_ALL/images/logo.gif')

MDN

156. Как отправить синхронный HTTP-запрос?


Для этого можно использовать объект XMLHttpRequest, передав его методу open() третий опциональный аргумент со значением false:

const getUsers = url => {
    const xhr = new XMLHttpRequest()
    xhr.open('GET', url, false)
    xhr.send()
    console.table(xhr.response)

    const response = JSON.parse(xhr.response)
    const template = \`
        <table>
            ${response.reduce((html, user) => html += \`
                <tr>
                    <td>${user.name}</td>
                    <td>${user.username}</td>
                    <td>${user.email}</td>
                </tr>\`, '')}
        <table>
    \`
    document.body
        .insertAdjacentHTML('beforeend', template)
}

getUsers('https://jsonplaceholder. typicode.com/users')

JSR
MDN

157. Как сделать асинхронный HTTP-запрос?


Для этого можно использовать метод fetch():

const getUsers = async url => {
    const response = await fetch(url)
    const data = await response.json()
    console.table(data)

    const template = \`
        <table>
            ${data.reduce((html, user) => html += \`
                <tr>
                    <td>${user.name}</td>
                    <td>${user.username}</td>
                    <td>${user.email}</td>
                </tr>\`, '')}
        <table>
    \`
    document.body.insertAdjacentHTML('beforeend', template)
}

getUsers('https://jsonplaceholder. typicode.com/users')

JSR
MDN

158. Как получить дату в нужном формате?


Для этого можно использовать метод toLocaleString():

console.log(
    new Date().toLocaleString('ru-Ru', {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    })
) // воскресенье, 6 сентября 2020 г.

MDN

159. Как получить максимальные размеры страницы?


Для этого нужно найти максимальные значения свойств scrollWidth, offsetWidth, clientWidth и scrollHeight, offsetHeight, clientHeight объектов document.body и document.documentElement:

const pageWidth = Math.max(
    document.body.scrollWidth, document.documentElement.scrollWidth,
    document.body.offsetWidth, document.documentElement.offsetWidth,
    document.body.clientWidth, document.documentElement.clientWidth
)
const pageHeight = Math.max(
    document.body.scrollHeight, document.documentElement.scrollHeight,
    document.body.offsetHeight, document.documentElement.offsetHeight,
    document.body.clientHeight, document.documentElement.clientHeight
)
const pageSize = {
    width: pageWidth,
    heigth: pageHeight
}
console.log(pageSize)

const pageCenter = {
    centerX: pageWidth / 2,
    centerY: pageHeight / 2
}
console.log(pageCenter)

JSR

160. Что такое условный или тернарный оператор?


Тернарный оператор является сокращенным способом записи блока if...else:

let accesAllowed
const age = propmt('Сколько вам лет?')

// if...else
if (age > 18) {
    accesAllowed = true
} else {
    accessAllowed = false
}

// тернарный оператор
(age > 18)
    ? accesAllowed = true
    : accessAllowed = false

JSR
MDN

161. Можно ли использовать цепочку из тернарных операторов?


Да, в этом случае тернарный оператор является альтернативой блока if...else if...else:

let accessAllowed
const getAge = () => prompt('Сколько вам лет?')

// это всего лишь пример - не надо так делать
// if...else if...else
const checkAge = (age = getAge()) => {
    console.log(age)
    if (isNaN(age)) {
        Promise.resolve(alert('Возраст должен быть числом')).then(accessAllowed = false).then(checkAge)
    } else if (age === null || age === '') {
        Promise.resolve(alert('Введите ваш возраст')).then(accessAllowed = false).then(checkAge)
    } else if (age < 0) {
        Promise.resolve(alert('Возраст не может быть меньше 0')).then(accessAllowed = false).then(checkAge)
    } else if (age > 100) {
        Promise.resolve(alert('Возраст не может быть больше 100')).then(accessAllowed = false).then(checkAge)
    } else if (age < 18) {
        Promise.resolve(alert('Извините, вы слишком молоды')).then(accessAllowed = false)
    } else {
        Promise.resolve(alert('Добро пожаловать!')).then(accessAllowed = true)
    }
    console.log(accessAllowed)
}

// тернарный оператор
const checkAge = (age = getAge()) => {
    isNaN(age)
        ? Promise.resolve(alert('Возраст должен быть числом')).then(accessAllowed = false).then(checkAge)
        : (age === null || age === '')
          ? Promise.resolve(alert('Введите ваш возраст')).then(accessAllowed = false).then(checkAge)
          : (age < 0)
            ? Promise.resolve(alert('Возраст не может быть меньше 0')).then(accessAllowed = false).then(checkAge)
            : (age > 100)
            ? Promise.resolve(alert('Возраст не может быть больше 100')).then(accessAllowed = false).then(checkAge)
            : (age < 18)
                ? Promise.resolve(alert('Извините, вы слишком молоды')).then(accessAllowed = false)
                : Promise.resolve(alert('Добро пожаловать!')).then(accessAllowed = true)
    console.log(accessAllowed)
}

JSR
MDN

162. Как начать выполнение кода после полной загрузки страницы?


Это можно сделать несколькими способами.
Разместить тег script перед закрывающим тегом body или добавить ему атрибут defer:

<body>
    ...
    <script src="script.js"></script>
</body>

<!-- или -->
<head>
    ...
    <script src="script.js" defer></script>
</head>

Если ваш скрипт — это модуль, то вместо атрибута defer, нужно указать атрибут type со значением module:

<script src="script.js" type="module"></script>

Добавить тегу body атрибут onload:

<body onload="script()"></body>

Добавить код в качестве обработчика события load объекта window:

window.onload = () => console.log('Страница полностью загружена')

// или
window.addEventListener('load', () => console.log('Страница полностью загружена'))

Сделать тоже самое для document.body:

document.body.onload = () => console.log('Страница полностью загружена')

163. В чем разница между __proto__ и prototype?


Свойство __proto__ (внутреннее скрытое свойство [[Prototype]]) — это объект, от которого экземпляр наследует поля и методы. А prototype — это объект, который используется для создания __proto__ при создании экземпляра с помощью ключевого слова new:

class Person {
    constructor(firstName, secondName) {
        this.firstName = firstName
        this.secondName = secondName
    }
    getFullName() {
        return \`${this.firstName} ${this.secondName}\`
    }

}

const user = new Person('Иван', 'Иванов')
console.log(user.getFullName()) // Иван Иванов
console.log(user.__proto__.getFullName === Person.prototype.getFullName) // true
console.log(Person.prototype) // {constructor: ƒ, getFullName: ƒ}
console.log(user.prototype === undefined) // true

JSR
MDN

164. Приведите пример обязательного использования точки с запятой


Одним из случаев обязательного использования точки запятой является использование IIFE (Immediately Invoked Fuction Expression — немедленно вызываемого функционального выражения):
Например, следующий код:

try {
    const x = 'Быть'

    (() => {
        console.log(x)
    })()
} catch {
    console.log('Не быть')
}

Будет интерпретирован так:

try {
    const x = 'Быть'(() => {
        console.log(x)
    })()
} catch {
    console.log('Не быть')
}

Поэтому в блоке try мы получаем ошибку TypeError: «Быть» is not a function, управление передается блоку catch, и в консоль выводится «Не быть».
Для того, чтобы код работал, как ожидается, он должен выглядеть так:

try {
    // точку с запятой нужно поставить либо здесь
    const x = 'Быть';
    // либо здесь
    ;(() => {
        console.log(x)
    })()
} catch {
    console.log('Не быть')
}

Также не забывайте про случаи автоматического расставления точек с запятой.

165. Для чего используется метод freeze()?


Данный метод, как следует из его названия, служит для «замораживания» объекта. Замороженный объект является неизменяемым (иммутабельным). Это означает, что в такой объект нельзя добавлять новые свойства, удалять или изменять существующие. Также этот метод устанавливает configurable: false и writable: false для существующих свойств. Метод возвращает замороженный объект.

'use strict'
const obj = {
    mission: 'possible'
}

Object.freeze(obj)
obj.mission = 'impossible' // TypeError: Cannot assign to read only property 'mission' of object '#<Object>'

delete obj.mission // TypeError: Cannot delete property 'mission' of #<Object>

Обратите внимание, что в нестрогом режиме исключение не выбрасывается, код просто не выполняется.

JSR
MDN

166. Зачем нужен метод freeze()?


Парадигма объектно-ориентированного программирования гласит, что интерфейс, содержащий определенное количество элементов, должен быть иммутабельным, т.е. должна быть исключена возможность его расширения, модификации или использования элементов за пределами текущего контекста. Данный метод является алиасом ключевого слова final в некоторых других языках программирования.

JSR
MDN

167. Как сделать первую букву каждого слова в строке заглавной?


Одним из способов это сделать является следующий:

const capitilize = str => str.replace(
    /[а-яё]S+/gi,
    txt => txt[0].toUpperCase() + txt.slice(1).toLowerCase()
)

console.log(capitilize('аПтека, улИца, фонАрь')) // Аптека, Улица, Фонарь

168. Как узнать, что на странице отключен JavaScript?


Для этого можно использовать тег noscript. Код внутри этого тега будет выполнен только в случае, если на странице отключен JavaScript:

    console.log('JavaScript включен')

<noscript>
    <p>Включите JavaScript, или ничего не получится</p>
</noscript>

Для того, чтобы отключить JavaScript в Chrome, заходим в настройки -> раздел «Конфиденциальность и безопасность» -> Настройки сайтов -> раздел «Контент» -> JavaScript.

MDN

169. Какие операторы поддерживаются JavaScript?


Операторы служат для работы со значениями или операндами. JavaScript поддерживает следующие операторы:

  • Арифметические: + (сложение, приведение к числу, конкатенация), — (вычитание), * (умножение), / (деление), % (деление по модулю, с остатком), ++ (инкремент), — (декремент), ** (возведение в степень)
  • операторы сравнения: == (абстрактное, нестрогое равенство), != (абстрактное неравенство), === (строгое равенство, проверка на идентичность), !== (строгое неравенство), >, >=, <, <=
  • логические: && (и), || (или),! (не) (!!! (двойное отрицание) не является отдельным оператором)
  • операторы присваивания: =, +=, -=, *=, /=, %=
  • тернарный: ?...: (if...else)
  • оператор typeof: определяет тип операнда
  • побитовые: & (и), | (или), ^ (исключающее или), ~ (не), << (левый сдвиг), >> (правый сдвиг), >>> (правый сдвиг с заполнением нулями)
  • новые:?.. (опциональная цепочка), ?? (слияние с null)

// опциональная цепочка
const obj = {
    foo: {
        baz: {
            qux: 'bar'
        }
    }
}

// тогда
console.log(obj.foo.bar.baz.qux) // TypeError: Cannot read property 'baz' of undefined

if (
    obj.foo !== undefined &&
    obj.foo.bar !== undefined &&
    obj.foo.bar.baz !== undefined
) {
    console.log(obj.foo.bar.baz.qux) // ошибки не будет
}

// сейчас
console.log(obj?.foo?.bar?.baz?.qux) // undefined

// слияние с null
console.log(
    0 || 'default null', // 'default null'
    0 ?? 'default null', // 0
    '' || 'default string', // default string
    '' ?? 'default string', // ''
)

JSR — Операторы
JSR — Логические операторы
JSR — Операторы сравнения
JSR — Условные операторы
JSR — Побитовые операторы
MDN — Оператор опциональной последовательности
MDN — Оператор нулевого слияния

170. Для чего используется оператор rest… (прочие параметры)?


Оператор rest является альтернативой объекта arguments и возвращает массив из переданных функции аргументов:

const sum = (...rest) => rest.reduce((acc, cur) => acc + cur)

console.log(sum(1, 2, 3)) // 6

Обратите внимание, что оператор rest должен передаваться в качестве последнего аргумента:

const fun = (x, ...rest, y) => console.log(rest) // SyntaxError: Rest parameter must be last formal parameter

JSR
MDN

171. Для чего используется оператор spread… (оператор распространения)?


Оператор spread используется для расширения (распаковки, разворачивания) итерируемых сущностей (массивов, строк). Распаковка означает преобразование, например, массива из чисел в набор простых значений:

const sum = (x, y, z) => x + y + z

const nums = [1, 2, 3]

console.log(sum(...nums)) // 6

JSR
MDN

172. Как определить, заморожен ли объект?


Для того, чтобы определить, заморожен ли объект, т.е. является ли он неизменяемым (иммутабельным), используется метод isFrozen():

const obj = {
    prop: 'Добро пожаловать в мир JavaScript!'
}

Object.freeze(obj)

console.log(Object.isFrozen(obj)) // true

MDN

173. Как определить равенство значений, используя объект?


Для этого можно использовать метод is():

Object.is('двое из ларца', 'двое из ларца') // true
Object.is(0.1 + 0.2, 0.3) // false
Object.is(window, window) // true
Object.is(+0, -0) // false

const objA = {}
const objB = objA
Object.is(objA, objB) // true
Object.is({}, {}) // false

Значения являются равными, если:

  • оба являются undefined
  • оба являются null
  • оба являются true или false
  • оба являются строками одинаковой длины с одинаковыми символами
  • оба ссылаются на один объект
  • оба являются числами, +0, -0 или NaN

JSR
MDN

174. Как создать копию объекта?


Одним из самых надежных способов это сделать является использование метода assign():

const objA = {a: 1, b: 2}
const objB = Object.assign(objA)

console.log(objB) // {a: 1, b: 2}

console.log(objA === objB) // true

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

const objA = {a: 1, b: 2}
const objB = {b: 2, c: 3}

const objC = Object.assign(objA, objB)
console.log(objC) {a: 1, b: 2, c: 3}

Для копирования простых объектов можно использовать связку JSON.parse-JSON.stringify:

const objA = {a: 1, b: 2}

const objB = JSON.parse(JSON.stringify(objA))

console.log(objB) // {a: 1, b: 2}

JSR
MDN

175. Что такое прокси?


Объект Proxy «оборачивается» вокруг другого объекта и может перехватывать (и, при желании, самостоятельно обрабатывать) разные действия с ним, например чтение/запись свойств и другие.

const handler = {
    get: (obj, prop) => prop in obj
        ? obj[prop]
        : 0
}

// new Proxy(цель, обработчик)
const p = new Proxy({}, handler)

p.a = 1
p.b = true

console.log(p.a, p.b) // 1 true
console.log( 'c' in p, p.c) // false 0

176. Для чего используется метод seal()?


Данный метод «запечатывает» объект, запрещая добавлять/удалять свойства. Он также устанавливает configurable: false для всех существующих свойств. Однако, значения свойств такого объекта можно менять. Для проверки, является ли объект запечатанным, используется метод isSealed().

'use strict'
const obj = {
    prop: 'Добро пожаловать в мир JavaScript!'
}

Object.seal(obj)

obj.prop = 'Оставь надежду, всяк сюда входящий'
console.log(Object.isSealed(obj)) // true
delete obj.prop // TypeError: Cannot delete property 'prop' of #<Object>
console.log(obj.prop) // Оставь надежду, всяк сюда входящий

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

JSR
MDN

177. В чем разница между методами freeze() и seal()?


Метод Object.seal() в отличие от метода Object.freeze() позволяет изменять существующие свойства объекта.

'use strict'
const objA = {
    prop: 'Быть'
}
Object.freeze(objA)
objA.prop = 'Не быть' // TypeError: Cannot assign to read only property 'prop' of object '#<Object>'

const objB = {
    prop: 'Не быть'
}
Object.seal(objB)
objB.prop = 'Быть'
console.log(objB.prop) // Быть

178. Как получить перечисляемые пары ключ/значение объекта?


Метод Object.entries() возвращает массив из перечисляемых пар ключ/значение объекта в виде подмассивов в том же порядке, что и цикл for...in:

const obj = {
    x: 1,
    y: 2
}

console.log(Object.entries(obj)) // [["x", 1], ["y", 2]]

for (let [key, value] of Object.entries(obj)) {
    console.log(\`${key}: ${value}\`) // x: 1 y: 2
}

JSR
MDN

179. В чем главное отличие методов Object.keys(), Object.values() и Object.entries()?


Метод Object.keys() возвращает ключи объекта, метод Object.values() — значения его свойств, а Object.entries() массив из пар ключ/значение:

const user = {
    name: 'Ванька',
    age: 30
}

console.log(Object.keys(user)) // ["name", "age"]
console.log(Object.values(user)) // ["Ванька", 30]
console.log(Object.entries(user)) // [["name", "Ванька"], ["age", 30]]

JSR
MDN — Object.keys()
MDN — Object.values()
MDN — Object.entries()

180. Как создать объект с определенным прототипом, не используя функцию-конструктор и классы?


Для этого можно использовать метод Object.create():

const firstUser = {
    name: 'Ванька',
    sayHi() {
        console.log(\`Привет, меня зовут ${this.name}!\`)
    }
}

const secondUser = Object.create(firstUser)

secondUser.name = 'Петька'
secondUser.sayHi() // Привет, меня зовут Петька!

JSR
MDN

181. Для чего используется WeakSet?


WeakSet используется для хранения коллекции объектов со слабыми ссылками. Другими словами, он служит дополнительным хранилищем объектов, используемых другим кодом. Такие объекты автоматически удаляются сборщиком мусора, когда становятся недостижимыми (неиспользуемыми), т.е. когда от объекта остается только ключ в WeakSet.

const ws = new WeakSet()
let user = {}

ws.add(user)
console.log(ws.has(user)) // true

user = null
console.log(ws.has(user)) // false, структура была очищена автоматически

JSR
MDN

182. В чем разница между Set и WeakSet?


Их основным отличием является то, что объекты, хранящиеся в WeakSet, имеют слабые ссылки, т.е. автоматически удаляются, как только становятся недостижимыми. Другие отличия состоят в следующем:

  • В Set могут храниться любые значения, а в WeakSet — только объекты
  • WeakSet не имеет свойства size
  • WeakSet не имеет методов clear(), keys(), values(), forEach()
  • WeakSet не является итерируемой сущностью

JSR
MDN

183. Какие методы доступны в WeakSet?


WeakSet обладает следующими методами:

  • add(): добавляет объект в коллекцию
  • delete(): удаляет объект из коллекции
  • has(): определяет наличие объекта в коллекции
  • length(): возвращает длину коллекции

const ws = new WeakSet()
const objA = {}
const objB = {}

ws.add(objA)
ws.add(objB)
console.log(ws.has(objA)) // true
console.log(ws.lenghth()) // 2
ws.delete(objA)
console.log(ws.has(objA)) // false

JSR
MDN

184. Для чего используется WeakMap?


WeakMap используется для хранения пар ключ/значение, в которых ключи имеют слабые ссылки. Другими словами, он служит дополнительным хранилищем ключей, используемых другим кодом. Такие ключи автоматически удаляются сборщиком мусора, когда становятся недостижимыми (неиспользуемыми), т.е. когда от них остается только ключ в WeakMap.

const wm = new WeakMap()
let user = {}
wm.set(user, 'user')
console.log(wm.has(user)) // true
user = null
console.log(wm.has(user)) // false, структура была очищена автоматически

JSR
MDN

185. В чем разница между Map и WeakMap?


Их основным отличием является то, что ключи, хранящиеся в WeakMap, имеют слабые ссылки, т.е. автоматически удаляются как только становятся недостижимыми. Другие отличия состоят в следующем:

  • В Map в качестве ключей могут использоваться любые значения, а в WeakMap — только объекты
  • WeakMap не имеет свойства size
  • WeakMap не имеет методов clear(), keys(), values(), entries(), forEach()
  • WeakMap не является итерируемой сущностью

JSR
MDN

186. Какие методы доступны в WeakMap?


WeakMap обладает следующими методами:

  • set(): добавляет пару ключ/значение в объект
  • delete(): удаляет значение по ключу
  • has(): определяет наличие значения по ключу
  • get(): возвращает значение по ключу

const wm = new WeakMap()
const firstUser = {}
const secondUser = {}

wm.set(firstUser, 'Ванька')
wm.set(secondUser, 'Петька')
console.log(wm.has(firstUser)) // true
console.log(wm.get(firstUser)) // Ванька
wm.delete(secondUser)
console.log(wm.has(secondUser)) // false

JSR
MDN

187. Как закодировать URL?


Для этого можно использовать метод encodeURI(). Данный метод преобразует все специальные символы, кроме, /?: @ = + $ #

const url = 'https://ru.wikipedia.org/wiki/Лермонтов,_Михаил_Юрьевич'
const encoded = encodeURI(url)
console.log(encoded) // https://ru.wikipedia.org/wiki/%D0%9B%D0...

JSR
MDN

188. Как раскодировать URL?


Для этого можно использовать метод decodeURI():

const url = 'https://ru.wikipedia.org/wiki/%D0%9B%D0...'
const decoded = decodeURI(url)
console.log(decoded) // https://ru.wikipedia.org/wiki/Лермонтов,_Михаил_Юрьевич

JSR
MDN

189. Как вывести содержимое страницы на печать?


Для этого можно использовать глобальный метод print(). Данный метод открывает специальное диалоговое окно с настройками печати:

<button>Печать</button>

document.querySelector('button')
    .addEventListener('click', () => print())

MDN

190. Что такое анонимная функция?


Анонимная функция — это функция без названия. Такие функции часто присваиваются переменным, а также используются в качестве колбэков:

const sayHi = function () {
    console.log('Привет')
}
sayHi() // Привет
// или
const sayBye = () => console.log('Пока')
sayBye() // Пока

window.addEventListener('click', function () {
    console.log('Не буди лихо, пока оно тихо')
})
// или
window.addEventListener('contextmenu', e => {
    e.preventDefault()
    console.log('Контекстное меню - детям не игрушка')
})

JSR
MDN

191. Каков приоритет использования локальных и глобальных переменных?


Локальные переменные имеют приоритет над одноименными глобальными переменными:

let question = 'Не быть'

function toBe () {
    question = 'Быть'
    console.log(question)
}
toBe() // Быть

JSR
MDN

192. Что такое аксессоры?


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

class User {
    constructor (name, age) {
        this.name = name
        this.age = age
    }

    #access = false

    get access () {
        return this.#access
    }

    set access (bool) {
        this.#access = bool
    }
}

const user = new User('Ванька', 30)
console.log(user.#access) // SyntaxError: Private field '#access' must be declared in an enclosing class

console.log(user.access) // false
user.access = true
console.log(user.access) // true

Геттеры и сеттеры — это свойства, а методы — функции:

class User {
    constructor (name, age) {
        this.name = name
        this.age = age
    }

    #access = false

    getAccess () {
        return this.#access
    }

    setAccess(bool) {
        this.#access = bool
    }
}

const user = new User('Ванька', 30)
console.log(user.#access) // SyntaxError: Private field '#access' must be declared in an enclosing class

console.log(user.getAccess()) // false
user.setAccess(true)
console.log(user.getAccess()) // true

JSR

193. Как определить свойство в конструкторе объекта?


Для этого можно использовать метод Object.defineProperty(). Данный метод позволяет добавлять новые свойства к объекту и модифицировать существующие, а также изменять настройки доступа к объекту:

'use strict'
const obj = {}

Object.defineProperty(obj, 'prop', {
    value: 1,
    writable: false
})

console.log(obj.prop) // 1
obj.prop = 2 // TypeError: Cannot assign to read only property 'prop' of object '#<Object>'

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

JSR
MDN

194. В чем заключаются особенности геттеров и сеттеров?


Основными особенностями геттеров и сеттеров является следующее:

  • Они имеют более простой по сравнению с методами синтаксис
  • Используются для определения вычисляемых свойств — аксессоров
  • Позволяют обеспечить одинаковые отношения между свойствами и методами
  • Могут обеспечивать более высокое качество данных
  • Позволяют выполнять задачи за сценой, когда речь идет об инкапсуляции

JSR

195. Можно ли добавить к объекту геттеры и сеттеры с помощью метода Object.defineProperty()?


Вполне:

const obj = {counter: 0}

Object.defineProperty(obj, 'increment', {
    get() {return ++this.counter}
})
Object.defineProperty(obj, 'decrement', {
    get() {return --this.counter}
})

Object.defineProperty(obj, 'sum', {
    set(val) {return this.counter += val}
})
Object.defineProperty(obj, 'sub', {
    set(val) {return this.counter -= val}
})

obj.sum = 10
obj.sub = 5
console.log(obj) // {counter: 5}
console.log(obj.increment) // 6
console.log(obj.decrement) // 5

JSR
MDN

196. Для чего используется switch...case?


switch...case является альтернативой if...else и представляет собой более наглядный способ выполнения кода в зависимости от переданного условия:

const calc = (x, y, operator) => {
    let result

    try {
        switch (operator) {
            case '+':
                result = x + y
                break
            case '-':
                result = x - y
                break
            case '*':
                result = x * y
                break
            case '/':
                result = x / y
                break
            default:
                throw new Error('Некорректная операция')
        }

        if (isNaN(result)) {
            throw new Error('Операнды должны быть числами')
        }

        console.log(result)
        return result
    } catch (e) {
        console.error(e.message)
    }
}

calc(1, 2, '+') // 3
calc(3, 4, '*') // 12
calc('a', 1, '-') // Операнды должны быть числами
calc(5, 6, 'x') // Некорректная операция

JSR
MDN

197. Назовите правила использования switch...case


При использовании конструкции switch...case необходимо придерживаться следующих правил:

  • условие может быть числом или строкой
  • не допускается дублирование значений
  • инструкция default является опциональной. Если ни для одного блока case не найдено совпадения, выполняется блок default
  • break используется для остановки цикла
  • break также является опциональным, но без него выполнение цикла продолжится

JSR
MDN

198. Назовите примитивные типы данных.


Примитивными типами данных («примитивами») в JavaScript являются следующие значения:

  • number для любых чисел: целочисленных или чисел с плавающей точкой, целочисленные значения ограничены диапазоном ±253
  • bigint для целых чисел произвольной длины
  • string для строк. Строка может содержать один или больше символов, нет отдельного символьного типа
  • boolean для true/false
  • null для неизвестных значений – отдельный тип, имеющий одно значение null
  • undefined для неприсвоенных значений – отдельный тип, имеющий одно значение undefined
  • symbol для уникальных идентификаторов


MDN

Дополнительная литература


Habr — Из чего сделан JavaScript?
Habr — Зачем в JavaScript нужен строгий режим?
Насколько JavaScript сильный?
Medium — Advanced JavaScript ES6 — Temporal Dead Zone, Default Parameters And Let vs Var — Deep dive!
JavaScript: область видимости простыми словами
Делегирование событий в JavaScript
Medium — Понимаем замыкания в JavaScript. Раз и навсегда
Habr — Дэн Абрамов о замыканиях в JavaScript
Medium — Understanding Prototypes in JavaScript
Medium — Подробно о методах apply(), call() и bind(), необходимых каждому JavaScript разработчику
JavaScript: полное руководство по классам
Medium — JavaScript Classes: An In-Depth look (Part 1)
Medium — Разбираемся с путаницей между JavaScript методами slice(), splice() и split()
Копирование объектов в JavaScript
Начало работы с методами JavaScript-массивов .map(), .filter() и .reduce()
Как работает reduce() в JavaScript
Работаем с асинхронной итерацией в ECMAScript 2019, используя for-of
Новшества ES2020, которые мне очень нравятся
DigitalOcean — Знакомство с объектами map и set в JavaScript
Medium — Понимаем каррирование в JavaScript
Medium — What is Memoization in Javascript?
Redd — Debounce vs Throttle: Definitive Visual Guide
Путь к пониманию шаблонных литералов в JavaScript
Habr — 5 малоизвестных возможностей JSON.stringify()
Habr — Понимание (всех) «модульных» форматов и инструментов JavaScript
Habr — Использование JavaScript-модулей в продакшне: современное состояние дел. Часть 1
Habr — Визуализация работы сервис-воркеров
GoogleDevelopers — Service Workers: an Introduction
Habr — Хранилище для веба
WebDevBlog — Изучаем IndexedDB
GoogleDevelopers — Working with IndexedDB
Habr — Web Storage API: примеры использования
Habr — Прослушиватели событий и веб-воркеры
Medium — A Simple Introduction to Web Workers in JavaScript
Habr — Распространенные ошибки при работе с промисами в JavaScript, о которых должен знать каждый
Habr — Визуализация промисов и Async/Await
Habr — Политика общего происхождения и CORS: визуальное руководство
Источник: https://habr.com/ru/post/519004/


Интересные статьи

Интересные статьи

Часто от программистов PHP можно услышать: «О нет! Только не „Битрикс“!». Многие специалисты не хотят связываться фреймворком, считают его некрасивым и неудобным. Однако вакансий ...
Добрый день! Представляю вашему вниманию список вопросов к собеседованию Java Backend, которые я оформлял на протяжении около 2х лет. Вопросы разбиты по темам: core, collections, concurre...
В 2019 году люди знакомятся с брендом, выбирают и, что самое главное, ПОКУПАЮТ через интернет. Сегодня практически у любого бизнеса есть свой сайт — от личных блогов, зарабатывающих на рекламе, до инт...
Как и у всех разработчиков, у меня настал период затишья. Проект подходил к концу, задач практически не было, хотелось выше зарплату, ну и пошла получать свой заветный job offer. Так вышл...
В этой статье я постараюсь разобрать механизм реализации замыканий в JavaScript. Для этого я буду использовать браузер Chrome. Начнем с определения: Замыкания  - это функции, ссылающиеся на ...