- PVSM.RU - https://www.pvsm.ru -
Доброго времени суток, друзья!
Представляю вашему вниманию список из первых 100 вопросов по основам JavaScript из этого репозитория [1] с краткими ответами и ссылками на «Современный учебник по JavaScript» Ильи Кантора (JSR) и MDN. Также в конце имеются ссылки на статьи для пытливых умов.
Данный список, а также 300+ практических вопросов доступны в моем приложении, которое можно посмотреть и установить здесь (PWA Store) [2] и здесь (Netlify) [3]. В приложении реализован механизм запоминания изученного вопроса, а также обеспечена работа в офлайн-режиме.
Приношу извинения за возможные ошибки и опечатки. При их обнаружении, не стесняйтесь писать в личку, буду весьма признателен.
Дополнительная литература [104]
Существует множество способов это сделать. Вот некоторые из них:
Простейший способ создать объект — использовать контруктор объекта. Однако, данный способ использовать не рекомендуется.
const object = new Object()
При использовании данного метода ему в качестве аргумента передается объект, который станет прототипом нового объекта.
const object = Object.create(null)
Синтаксис объектного литерала эквивалентен методу Object.create().
const object = {}
Создаем функцию-конструктор и применяем оператор «new» для создания экземпляра этой функции — объекта.
function Person (name) {
const object = { }
object.name = name
object.age = 30
return object
}
const object = new Person('John')
Данный способ идентичен предыдущему, за исключением того, что для добавления новых свойств и методов используется прототип функции.
function Person ( ) { }
Person.prototype.name = 'John'
const object = new Person()
Это похоже на создание экземпляра с помощью Object.create() с прототипом функции и привязку данной функции к экземпляру с параметрами в качестве аргументов.
function f {}
new f(x, y, z)
Или:
// создаем новый экземпляр, используя прототип функции
const newInstance = Object.create(f.prototype)
// привязываем функцию
const result = f.call(newInstance, x, y, z)
// если result не нулевой объект, используем ее, иначе, используем newInstance
console.log(result && typeof result === 'object' ? result : newInstance)
Для создания объектов могут использоваться классы.
class Person {
constructor(name) {
this.name = name
}
}
const object = new Person('John')
Сингтон — это объект, допускающий создание только одного экземпляра. Повторные вызовы конструктора данного объекта будут возвращать один и тот же экземпляр. Это позволяет избежать случайного создания нескольких экземпляров одного объекта.
const object = new function () {
this.name = 'John'
}
Прототипы используется для создания новых объектов на основе существующих. Такая техника называется прототипным наследованием. Прототип экземпляра объекта доступен через Object.getPrototypeOf(object) или свойство __proto__ (внутреннее скрытое свойство [[Prototype]]), а прототип функции-конструктора доступен через Object.prototype.
Разницу между данными методами можно объяснить с помощью следующих примеров.
Метод call() вызывает функцию с указанным значением this и аргументами через запятую.
const employee1 = { firstName: 'Иван', lastName: 'Иванов' }
const employee2 = { firstName: 'Петр', lastName: 'Петров' }
function invite (greet1, greet2) {
onsole.log(`${greet1}, ${this.firstName} ${this.lastName}. ${greet2}`)
}
invite.call(employee1, 'Привет', 'Как дела?') // Привет, Иван Иванов. Как дела?
invite.call(employee2, 'Привет', 'Как дела?') // Привет, Петр Петров. Как дела?
Метод apply() вызывает функцию с указанным значением this и аргументами в виде массива.
const employee1 = { firstName: 'Иван', lastName: 'Иванов' }
const employee2 = { firstName: 'Петр', lastName: 'Петров' }
function invite (greet1, greet2) {
console.log(`${greet1}, ${this.firstName} ${this.lastName}. ${greet2}`)
}
invite.apply(employee1, ['Привет', 'Как дела?']) // Привет, Иван Иванов. Как дела?
invite.apply(employee2, ['Привет', 'Как дела?']) // Привет, Петр Петров. Как дела?
Метод bind() возвращает новую функцию с указанным значением this и позволяет передать ей массив или любое количество аргументов через запятую.
const employee1 = { firstName: 'Иван', lastName: 'Иванов' }
const employee2 = { firstName: 'Петр', lastName: 'Петров' }
function invite (greet1, greet2) {
console.log(`${greet1}, ${this.firstName} ${this.lastName}. ${greet2}`)
}
const inviteEmployee1 = invite.bind(employee1)
const inviteEmployee2 = invite.bind(employee2)
inviteEmployee1('Привет', 'Как дела?') // Привет, Иван Иванов. Как дела?
inviteEmployee2('Привет', 'Как дела?') // Привет, Петр Петров. Как дела?
Таким образом, методы call() и apply() вызывают функцию после ее привязки к объекту. Разница между ними состоит в способе передачи аргументов. Эту разницу легко запомнить при помощи первых букв методов: call — это запятая (comma, c), apply — массив (array, a). Метод bind() возвращает новую функцию, привязанную к указаному объекту.
JSR — Call/Apply [109]
JSR — Bind [110]
MDN — Call [111]
MDN — Apply [112]
MDN — Bind [113]
JSON — это текстовый формат данных, основанный на синтаксисе объектов JavaScript, изобретенный Дугласом Крокфордом. Он используется для передачи данных по сети и, обычно, имеет расширение .json и MIME-тип application/json.
Разбор (парсинг): преобразует строку в формате JSON в объект.
JSON.parse(text)
Стрингификация: преобразует объект в строку в формате JSON для передачи по сети.
JSON.stringify(object)
Метод slice() возвращает выбранные элементы массива в виде нового массива. Он возвращает элементы, начиная с индекса, указанного в первом аргументе, и заканчивая, но не включая, индексом, указанном во втором необязательном аргументе. Если второй аргумент отсутствует, то будут извлечены все элементы, начиная с индекса, указанного в первом аргументе.
const arrayIntegers = [1, 2, 3, 4, 5]
const arrayIntegers1 = arrayIntegers.slice(0, 2) // [1, 2]
const arrayIntegers2 = arrayIntegers.slice(2, 3) // [3]
const arrayIntegers3 = arrayIntegers.slice(4) // [5]
Обратите внимание, что данный метод не изменяет исходный массив, а лишь возвращает его подмножество в виде нового массива.
Метод splice() используется для добавления или удаления элементов в или из массива. Первый аргумент определяет начальную позицию для добавления или удаления элементов, второй опциональный аргумент — количество удаляемых элементов. Каждый последующий аргумент добавляется в массив:
let arrayOriginal1 = [1, 2, 3, 4, 5]
let arrayOriginal2 = [1, 2, 3, 4, 5]
let arrayOriginal3 = [1, 2, 3, 4, 5]
let array1 = arrayOriginal1.splice(0, 2) // возвращается [1, 2]; исходный массив = [3, 4, 5]
let array2 = arrayOriginal2.slice(3) // возвращается [4, 5]; исходный массив = [1, 2, 3]
let array3 = arrayOriginal3.slice(3, 1, 'a', 'b', 'c') // возвращается [4]; исходный массив = [1, 2, 3, 'a', 'b', 'c']
Обратите внимание, что метод splice() модифицирует исходный массив и возвращает массив извлеченных элементов.
Главные отличия состоят в следующем:
Slice | Splice |
---|---|
Не изменяет исходный массив | Изменяет исходный массив |
Возвращает подмассив исходного массива | Возвращает удаленные элементы в виде массива |
Служит для извлечения элементов из массива | Служит для добавления/удаления элементов в/из массива |
JSR [116]
MDN — Slice [117]
MDN — Splice [118]
Объекты похожи на карты в том, что оба позволяют устанавливать ключи для значений, извлекать значения, удалять ключи и определять наличие значения по ключу. По этой причине объекты раньше использовались как карты. Однако между ними существуют некоторые отличия, которые делают использование карт более предпочтительным в определенных случаях.
JavaScript предоставляет два способа для сравнения значений: строгое (===, !==) и абстрактное (==, !==). При строгом сравнении значения сравниваются как есть, а при нестрогом при необходимости осуществляется неявное преобразование (приведение) типов значений. Строгие операторы используют следующие правила для сравнения различных типов значений:
Логические значение являются строго равными, когда оба являются истинными или ложными, т.е. true или false
Два объекта являются строго равными, если ссылаются на один и тот же объект (место в памяти)
null === undefined возвращает false, но null == undefined возвращает true
Несколько примеров:
0 == false // true
0 === false // false
1 == "1" // true
1 === "1" // false
null == undefined // true
null === undefined // false
'0' == false // true
'0' === false // false
[] == [] // или
[] === [] // false, ссылаются на разные места в памяти
{} == {} // или
{} === {} // false, ссылаются на разные места в памяти
Стрелочные функции — это сокращенный способ записи функциональных выражений. Они не имеют собственных this, arguments, super и new.target. Эти функции служат хорошей альтернативой функциям, не имеющим методов, но не могут использоваться как конструкторы.
В JavaScript функции являются объектами первого класса. Это означает, что функции могут использоваться как обычные переменные.
Например, функция может передаваться в качестве аргумента другой функции, возвращаться как значение из другой функции и присваиваться переменной. В следующем примере функция присваивается обработчику:
const handler = () => console.log('Это функция обработки клика')
document.addEventListener('click', handler)
Функция первого порядка — это функция, которая не принимает другую функцию в качестве аргумента и не возвращает функцию как значение:
const firstOrder = () => console.log('Я - функция первого порядка')
Функция высшего порядка — это функция, которая принимает другую функцию в качестве аргумента или возвращает другую функцию как значение:
const firstOrderFunc = () => console.log('Я - функция первого порядка')
const higherOrder = returnFirstOrderFunc => returnFirstOrderFunc()
higherOrder(firstOrderFunc)
Унарная функция (функция-монада) — это функция, принимающая только один аргумент:
const unaryFunction = a => console.log(a + 10) // прибавляем 10 к переданному аргументу и выводим результат в консоль
Каррирование — это процесс преобразования функции с несколькими параметрами в несколько функций с одним параметром. Данный процесс назван в четь математика Хаскелла Карри. Каррирование превращает одну n-арную функцию в несколько унарных функций (уменьшает арность функции):
const multiArgF = (a, b, c) => a + b + c
const curryUnaryF = a => b => c => a + b + c
curryUnaryF(1) // возвращает функцию: b => c => 1 + b + c
curryUnaryF(1)(2) // возвращает функцию: c => 3 + c
curryUnaryF(1)(2)(3) // возвращает число 6
Каррирование применяется в целях обеспечения возможности повторного использования кода и создания композиции из функций.
JSR [128]
Чистая функция — это функция, возвращаемое значение которой зависит только от передаваемых аргументов, без побочных эффектов. Проще говоря, если вы вызывается функцию n раз с n аргументами, и функция всегда возвращает одно и тоже значение, значит, она является чистой:
// не чистая
let numberArray = []
const impureAddNumber = number => numberArray.push(number)
// чистая
const pureAddNumber = number => argNumberArray => argNumberArray.concat([number])
// отображаем результаты
console.log(impureAddNumber(6)) // 1
console.log(numberArray) // [6]
console.log(pureAddNumber(7)(numberArray)) // [6, 7]
console.log(numberArray) // [6]
В приведенном примере impureAddNumber не является чистой функцией, поскольку метод push() возвращает новую длину массива, которая не зависит от передаваемого аргумента. Вторая функция является чистой, поскольку метод concat() объединяет два массива без побочных эффектов и возвращает новый массив. Чистые функции важны для юнит-тестирования и не нуждаются во внедрении зависимостей. Отсутствие побочных эффектов повышает надежность приложения за счет более слабых связей между его элементами. Одним из воплощений данного принципа является концепция неизменности (иммутабельности), представленная в ES6, и заключающаяся в предпочтении const перед let.
Ключевое слово «let» служит для объявления локальной переменной, имеющей блочную область видимости. Область видимости такой переменной органичена блоком, оператором или выражением, в котором она используется. Переменные, объявленные с помощью ключевого слова «var», имеют глобальную область видимости или область видимости функции, в которой они определены:
let counter = 30
if (counter === 30) {
let counter = 31
console.log(counter) // 31
}
console.log(counter) // 30 (переменная counter, объявленная в блоке, здесь не существует)
Основные отличия состоят в следующем:
var | let |
---|---|
Доступно с момента появления JavaScript | Представлено в ES6 |
Имеет глобальную или функциональную область видимости | Имеет блочную область видимости |
Переменные поднимаются в начало области видимости | Переменные также поднимаются, но не инициализируются (поднимается только объявление, но не присвоение значения) |
Несколько примеров:
function userDetails(username) {
if (username) {
console.log(salary)
console.log(age)
let age = 30
var salary = 10000
}
console.log(salary) // 10000 (область видимости функции)
console.log(age) // ошибка: age не определена (блочная область видимости)
}
JSR [129]
MDN — let [130]
MDN — var [131]
Let (пусть) — это математический оператор, который использовался ранними языками программирования, такими как Scheme и Basic. В настоящее время let используется большим количеством языков программирования, так что данное слово является наиболее близкой альтернативой сокращению «var» (variable — переменная).
JSR [129]
MDN [130]
Если вы попытаетесь переопределить переменную, объявленную с помощью ключевого слова «let» в блоке switch, то получите ошибку:
let counter = 1
switch(x) {
case 0:
let name
break
case 1:
let name // синтаксическая ошибка (SyntaxError)
break
}
Для решения данной задачи необходимо создать новый блок внутри case — новую лексическую область видимости:
let counter = 1
switch(x) {
case 0: {
let name
break
}
case 1: {
let name
break
}
}
При попытке доступа к переменным, объявленным с помощью ключевого слова «let» или «const» (но не «var»), до их определения (т.е. до присваивания им значения внутри текущей области видимости) будет выброшено исключение ReferenceError (ошибка ссылки). Другими словами, временной мертвой зоной называется время между созданием контекста (области видимости) переменной и ее определением:
function someMethod () {
console.log(counter1) // undefined
console.log(counter2) // ReferenceError
var counter1 = 1
const counter2 = 2
}
MDN [130]
IIFE — это функция, которая вызывается сразу после определения. Синтаксис такой функции может выглядеть так (один из вариантов, наиболее распространенный):
(function () {
// код
})()
// или, если речь идет о стрелочной функции
(() => {
// код
})()
Главная причина использования IIFE заключается в обеспечении приватности переменных, поскольку доступ к переменным, объявленным внутри IIFE, нельзя получить из внешнего окружения:
(function () {
var message = 'IIFE'
console.log(message)
})()
console.log(message) // ошибка: message не определена
Среди прочего, можно назвать следующее:
Мемоизация — это способ повышения производительности функции за счет сохранения в кэше ранее полученных результатов выполнения этой функции. При каждом вызове функции переданный ей аргумент становится индексом кэша. Если данные имеются в кэше, они возвращаются без повторного выполнения функции. В противном случае, функция выполняется, а результат записывается в кэш:
const memoizAddition = () => {
let cache = {}
return value => {
if (value in cache) {
console.log('Получение данных из кэша')
return cache[value] // в данном случае, cache.value не может быть использовано в качестве названия свойства, поскольку названия свойств в JS не могут начинаться с числа. Поэтому используется скобочная нотация
} else {
console.log('Результат вычисляется')
let result = value + 20
cache[value] = result
return result
}
}
}
// возвращаем функцию из memoizAddition
const addition = memoizAddition()
console.log(addition(20)) // Результат вычисляется 40
console.log(addition(20)) // Получения данных из кэша 40
Поднятие — это процесс перемещения переменных и функциональных выражений в начало их области видимости перед выполнением кода. Запомните: поднимаются только сами переменные и выражения, а не их инициализация (т.е. поднимается объявление переменной, а не присваивание ей значения):
console.log(message) // undefined
var message = 'Хойстинг'
Для компилятора данный код выглядит так:
var message
console.log(message)
message = 'Хойстинг'
Классы, представленные в ES6, являются синтаксическим сахаром (оберткой, абстракцией или надстройкой) для прототипного наследования (для прототипа функции-конструктора). Пример функции-конструктора:
function Bike(model, color) {
this.model = model
this.color = color
}
Bike.prototype.getDetails = function () {
return 'Эта ' + this.model + ' велосипеда имеет ' + this.color + ' цвет.'
}
Тот же пример с использованием класса:
class Bike {
constructor (color, model) {
this.color = color
this.model = model
}
getDetails () {
return `Эта ${this.model} велосипеда имеет ${this.color} цвет.`
}
}
Замыкание — это комбинация функции и ее лексического окружения. Проще говоря, замыкание — это когда внутренняя функция имеет доступ к переменным, объявленным во внешней функции. Замыкание имеет цепочку из трех областей видимости:
function Welcome (name) {
var greetingInfo = function (message) {
console.log(message + ' ' + name)
}
return greetingInfo
}
var myFunction = Welcome('Иван')
myFunction('Добро пожаловать, ') // Добро пожаловать, Иван
myFunction('Привет, ') // Привет, Иван
Модули — это небольшие части независимого переиспользуемого кода, лежащие в основе многих шаблонов проектирования. Большинство модулей экспортируется в качестве объектов, функций или конструкторов.
JSR [136]
MDN [137]
Среди прочего, можно назвать следующее:
Область видимости определяет доступность переменных, функций и объектов в разных местах кода во время его выполнения. Другими словами, область видимости — это видимость переменных и других ресурсов в текущем контексте выполнения кода.
MDN [144]
Сервис-воркер — это скрипт, который выполняется независимо от веб-страницы, на которой он был запущен, и действий пользователя. Фактически сервис-воркер выполняет роль прокси-сервера между приложением и браузером. Основными возможностями сервис-воркеров является следующее: обеспечение работы приложения в режиме офлайн, периодическая фоновая синхронизация, пуш-уведомления, перехват и обработка сетевых запросов и программное управление кэшем.
MDN [145]
Сервис-воркеры не имеют прямого доступа к DOM. Однако, они могут взаимодействовать со страницей через интерфейс postMessage, а страница — может изменять DOM.
MDN — ServiceWorker [145]
MDN — postMessage [146]
Одной из проблем сервис-воркеров является то, что их выполнение прекращается, когда они не используются, и повторно запускается при необходимости. Это не позволяет добавлять обработчики событий fetch и message глобально. Для повторного использования информации необходимо обеспечить взаимодействие сервис-воркеров с индексированной базой данных (IndexedDB) или локальным хранилищем (local storage).
MDN [145]
IndexedDB — это низкоуровневый прикладной интерфейс для хранения большого объема структурированных данных, включая файлы и blobs, на стороне клиента. Данный интерфейс использует индексы для высокопроизводительного поиска данных.
JSR [147]
MDN [148]
Веб-хранилище — это интерфейс, позволяющий хранить данные в виде пар ключ/значение локально, т.е. в браузере пользователя, более удобным способом, чем при использовании куки. Веб-хранилище предоставляет два механизма хранения данных:
postMessage — это способ коммуникации разных источников объекта window (например, страницы и генерируемого ею поп-апа (всплывающего окна) или страницы и встроенного в нее iframe). Обычно, скрипты одной страницы не имеют доступа к другой странице, если данная страница следует политике общего происхождения или, как еще говорят, одного источника (источники должны иметь одинаковый протокол, хост и порт).
Куки — это небольшой фрагмент данных, который сохраняется на компьютере пользователя для последующего использования браузером. Куки сохраняются в виде пар ключ/значение:
document.cookie = 'username=John'
Куки используются для сохранения информации о пользователе (не рекомендуется использовать для хранения конфиденциальной информации). Обычно, данный процесс состоит из двух этапов:
По умолчанию, куки удаляются при закрытии браузера, однако это можно изменить, установив время жизни (expires) (в формате UTC):
document.cookie = 'username=John; expires=Sat, 5 Sep 2020 12:00:00 UTC'
По умолчанию, куки принадлежат текущей странице, однако это также можно изменить, установив путь (path):
document.cookie = 'username=John; path=/services'
Удалить куки можно, установив прошедшее время в качестве времени жизни. В этом случае не нужно определять значение куки:
document.cookie = 'username=; expires=Fri, 05 Jun 2020 00:00:00 UTC; path=/;'
Обратите внимание, что в данном случае необходимо определить путь для удаления правильного куки. Некоторые браузеры не позволяют удалить куки без указания этого параметра.
JSR [151]
MDN [152]
Основные отличия состоят в следующем:
Критерий | Куки | Локальное хранилище | Сессионное хранилище |
---|---|---|---|
Доступность | Как на сервере, так и на клиенте | Только на клиенте | Только на клиенте |
Время жизни | Устанавливается с помощью expires | До удаления пользователем | До закрытия вкладки браузера |
Поддержка шифрования | Поддерживается | Не поддерживается | Не поддерживается |
Максимальный размер данных | 4 Кб | Около 5 Мб (зависит от браузера) | Около 5 Мб (зависит от браузера) |
JSR — Куки [151]
MDN — Cookie [152]
JSR — LocalStorage, SessionStotage [149]
MDN — Web Storage [150]
Локальное хранилище — это тоже самое, что и сессионное хранилище, за исключением того, что в первом данные сохраняются даже при закрытии и перезагрузке браузера, а во втором данные удаляются по окончании сессии страницы.
JSR [149]
MDN [150]
Объект window предоставляет объекты WindowLocalStorage и WindowSessionStorage, которые имеют свойства localStorage и sessionStorage, соответственно. Эти свойства создают экземпляр объекта Storage, с помощью которого можно записывать, извлекать и удалять данные для определенного домена и типа хранилища (сессионное или локальное):
// сохраняем данные
localStorage.setItem('data', document.querySelector('.data').value)
// получаем данные
localStorage.getItem('data')
Сессионное хранилище предоставляет методы для чтения, записи и удаления данных:
// записываем данные
sessionStorage.setItem('key', 'value')
// получаем данные
const data = sessionStorage.getItem('key')
// удаляем определенные данные
sessionStorage.removeItem('key')
// удаляем все данные
sessionStorage.clear()
При изменении хранилища в контексте другого документа возникает событие storage:
window.onstorage = function () {}
Пример обработки данного события:
window.onstorage = ev => {
console.log(`${ev.key} был изменен.n Старое значение: ${ev.oldValue}.n Новое значение: ${ev.newValue}.`)
}
Данное событие, в частности, позволяет реализовать своего рода чат.
JSR [149]
MDN [150]
Веб-хранилище является более безопасным и может хранить больший объем данных, чем куки, что не влияет на производительность. Кроме того, данные не отправляются на сервер (в случае с куки данные включаются в заголовки запроса и ответа при каждом обращении клиента к серверу). Поэтому такой способ хранения данных является более предпочтительным, чем куки.
JSR [149]
MDN [150]
Перед использованием веб-хранилища рекомендуется проверить поддержку данного интерфейса браузерами:
if (typeof(Storage) !== 'undefined') {
// код
} else {
// веб-хранилище не поддерживается
}
// или
if ('Storage' in window) {
console.log('ok')
} else {
console.warn('!ok')
}
По данным CanIUse [153] поддержка веб хранилища на сегодняшний день составляет 98%.
Перед использованием сервис-воркеров рекомендуется проверить поддержку данного интерфейса браузерами:
if (typeof(Worker) !== undefined) {
// код
} else {
// сервис-воркеры не поддерживаются
}
// или
if ('Worker' in window) {
console.log('ok')
} else {
console.warn('!ok')
}
По данным CanIUse [154] поддержка сервис-воркеров на сегодняшний день составляет 94,5%.
MDN [145]
Для использования веб-воркера необходимости сделать следующее.
Создать файл для воркера, например, counter.js:
let i = 0
function timedCount() {
i = i + 1
postMessage(i)
setTimeout('timedCount()', 500)
}
timedOut()
Метод postMessage() используется для отправки сообщения странице.
Создаем объект воркера:
const w = new Worker('counter.js')
После этого обрабатываем получение сообщений от воркера:
w.onmessage = ev => document.querySelector('.message').textContent = ev.data
Воркер будет продолжать обрабатывать событие message даже после того, как внешний скрипт выполнит свою работу, поэтому нужно принудительно его остановить:
w.terminate()
Если присвоить воркеру значение undefined, код можно будет использовать повторно:
w = undefined
MDN [155]
Поскольку веб-воркеры создаются в отдельном файле, они не имеют доступа к следующим объектам:
MDN [155]
Промис — это объект, который либо выполняется с некоторым значением, либо отклоняется с ошибкой. Разрешение промиса происходит либо после истечения определенного времени, либо после возникновения определенного события. Промис может иметь одно из трех состояний: находится в режиме ожидания (pending), выполнен (fulfilled), отклонен (rejected).
Синтаксис промиса:
const promise = new Promise((resolve, reject) => {
// код
})
// или, когда мы уверены, что промис выполнится успешно
const promise = Promise.resolve(value)
promise.then(value => {
// код
})
Пример использования промиса:
const promise = new Promise(resolve => {
const timer = setTimeout(() => {
resolve('Привет от промиса!')
clearTimeout(timer)
}, 5000);
}, reject => {
reject('Что-то пошло не так!')
})
promise
.then(value => console.log(value))
.catch(error => console.error(error))
.finally(() => console.log('Мы закончили')) // в консоль будет выведено "Привет от промиса!" через 5 секунд и "Мы закончили"
Алгоритм выполнения промиса:
Промисы используются для работы с асинхронным кодом. Они представляют собой альтернативу функциям обратного вызова, позволяя избежать так называемого «ада колбеков», делают код более чистым и читаемым.
JSR [156]
MDN [157]
У промисов существует три состояния:
Колбек — это функция, которая передается другой функции в качестве аргумента. Данная функция (внутренняя) вызывается внутри родительской (внешней) для выполнения определенной операции. Рассмотрим простой пример:
function callback(name) {
alert(`Привет, ${name}!`)
}
function outer(cb) {
const name = prompt('Пожалуйста, введите свое имя')
cb(name)
}
outer(callback)
В приведенном примере функция outer запрашивает имя пользователя и записывает его в переменную name. Затем данная функция передает name функции callback, которая выводит приветствие с именем пользователя.
Колбеки нужны, поскольку JavaScript — язык, управляемый событиями. Это означает, что вместо ожидания ответа на запрос или обработки определенного события, JS продолжает реагировать на другие события. Рассмотрим пример, в котором одна функция обращается к интерфейсу, а другая — выводит сообщение в консоль:
function first () {
// имитируем обращение к API
setTimeout(() => console.log('Вызвана первая функция.'), 1000)
}
function second () {
console.log('Вызвана вторая функция.')
}
first()
second()
// сначала будет выведено "Вызвана вторая функция.", затем "Вызвана первая функция."
Как видите, JS не ожидает завершения первой функции, а продолжает выполнение кода. Поэтому колбеки используются для имитации асинхронности, предотвращая блокировку основного потока выполнения программы.
Ад колбеков — это антипаттерн, когда множество функций обратного вызова вложены друг в друга для реализации асинхронной логики. Такая структура кода сложна для восприятия и поддержки. Это выглядит примерно так:
function first () {
return function second () {
return function third () {
return function fourth () {
// и т.д.
}
}
}
}
Такой подход к написанию кода считается плохой практикой, кроме случаев каррирования (включая debounce и throttle) или частичного применения функций.
JSR [158]
MDN [159]
События, отправленные сервером — это технология пуш-уведомлений, позволяющая браузерам получать от сервера обновленные данные через HTTP-соединение без отправки запроса. Это один из способов коммуникации клиента и сервера, когда сообщения отправляются только сервером. Данная технология используется для обновления Facebook/Twitter, цен в магазинах, новостных лент и т.д.
JSR [160]
MDN [161]
Для этого используется объект «EventSource»:
if('EventSource' in window) {
const source = new EventSource('sse_generator.js')
source.onmessage = event => document.querySelector('output').innerHTML += event.data + ''
}
Это делается так:
if (typeof EventSource !== 'undefined') {
// код
} else {
// SSE не поддерживается
}
// или
('EventSource' in window)
? console.log('ok')
: console.warn('!ok')
По данным CanIUse [163] на сегодняшний день SSE поддерживается 95% браузеров.
JSR [160]
MDN [161]
Вот список этих событий:
Событие | Описание |
---|---|
open | Возникает при открытии соединения с сервером |
message | Возникает при получении сообщения от сервера |
error | Возникает при выбрасывании исключения |
Основными правилами работы с промисами является следующее:
Вы можете вкладывать колбеки друг в друга с целью последовательного выполнения определенных операций:
loadScript('/script1.js', script => {
console.log(`Скрипт ${script} загружен.`)
loadScript('/script2.js', script => {
console.log(`Скрипт ${script} загружен.`)
loadScript('/script3.js', script => {
console.log(`Скрипт ${script} загружен.`)
})
})
})
Последовательное выполнение нескольких асинхронных задач с помощью промисов называется цепочкой промисов. Рассмотрим пример:
new Promise((resolve, reject) => {
const id = setTimeout(() => {
resolve(1)
clearTimeout(id)
}, 1000)
}).then(result => {
console.log(result) // 1
return result * 2
}).then(result2 => {
console.log(result2) // 2
return result2 * 3
}).then(result3 => {
console.log(result3) // 6
}).catch(error => console.error(error))
Алгоритм выполнения:
Promise.all() — это промис, принимающий массив других промисов в качестве аргумента и возвращающий результаты выполненных промисов или ошибку при отклонении одного из них. Синтаксис:
Promise.all([Promise1, Promise2, Promise3])
.then(results => console.log(results))
.catch(error => console.error(error))
Помните, что порядок получения результатов зависит от порядка промисов в массиве.
MDN [164]
JSR [165]
Метод Promise.race() возвращает результат первого выполненного или отклоненного промиса из переданных ему в виде массива промисов:
const promise1 = new Promise((resolve, reject) => setTimeout(resolve, 500, 'один'))
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'два'))
Promise.race([promise1, promise2]).then(value => console.log(value)) // "два"
Для включения строго режима используется инструкция 'use strict' (или «use strict») в начале всего кода или отдельной функции. Строгий режим был представлен в ES6. В данном режиме запрещены некоторые действия и выбрасывается больше исключений.
MDN [167]
JSR [168]
Строгий режим позволяет писать более безопасный код, предотвращая возникновение многих ошибок. Например, он запрещает случайное создание глобальных переменных (без ключевого слова, variable = value), присваивание значения свойству, доступному только для чтения, свойству, которое можно получить только с помощью геттера, несуществующему свойству и несуществующей переменной или объекту. В нестрогом режиме во всех этих случаях исключение не выбрасывается.
MDN [167]
JSR [168]
Строгий режим включается с помощью инструкции 'use strict' (или «use strict») в начале кода или функции. Обычно, данная инструкция указывается в самом начале скрипта, т.е. в глобальном пространстве имен:
'use strict'
x = 3.14 // Uncaught ReferenceError: x не определена
Если 'use strict' указывается в функции, то действие строгого режима распространяется только на эту функцию:
x = 3.14 // все в порядке
f() // Uncaught ReferenceError: y не определена
function f () {
'use strict'
y = 3.14
}
Двойное отрицание (!!) преобразует значение в логическое. Если значение является ложным, то возвращается false, иначе — true:
const x = 1
console.log(x) // 1
console.log(!!x) // true
const y = ''
console.log(y) // ''
console.log(!!str) // false
Помните: "!!" — это не отдельный оператор, а два оператора "!".
MDN [169]
JSR [170]
Данный оператор служит для удаления свойств объектов и значений этих свойств:
const user = {
name: 'Иван',
age: 20
}
delete user.age
console.log(user) // { name: "Иван" }
delete user // false
// в строгом режиме будет выброшено исключение Uncaught SyntaxError: использование оператора Delete в строгом режиме недопустимо
Помните, что поскольку массив — это тоже объект, применение delete к элементу массива, удалит его значение и запишет в него undefined, т.е. индекс элемента массива сохранится и длина массива не изменится
JSR [171]
MDN [172]
Данный оператор используется для определения типа переменной или выражения:
typeof 1 // number
typeof [] // object
typeof 'Иван Иванов' // string
typeof (1 + 2) // number
typeof null // object (?)
typeof NaN // number (?)
undefined — это неопределенное (не отсутствующее) стандартное значение (значение по умолчанию) переменной, которой не было присвоено значения, а также необъявленной переменной. Это один из примитивных типов данных:
let name
console.log(typeof name) // undefined
console.log(typeof age) // undefined
Данное значение может присваиваться переменным явно:
user = undefined
null — значение, представляющее собой отсутствие значения, установленное явно. Это один из примитивных типов данных. С помощью null можно удалить значение переменной:
const user = null
console.log(typeof user) // object
Основные отличия состоят в следующем:
Null | Undefined |
---|---|
Присваивается в качестве индикатора отсутствия значения | Является значением по умолчанию для переменных, которым не было присвоено значения, или необъявленных переменных |
Тип — object | Тип — undefined |
Примитивный тип, означающий нуль, отсутствие значения или ссылки | Примитивный тип, означающий, что переменной не было присвоено значения |
Указывает на отсутствие значения переменной | Указывает на отсутствие переменной или неопределенность ее значения |
JSR — undefined [175]
MDN — undefined [176]
JSR — null [177]
MDN — null [178]
Функция eval() вычисляет переданную ей строку. Строка может быть выражением, переменной, одним или несколькими операторами:
console.log(eval('1 + 2')) // 3
// пример с каррированием
const calc = a => b => c =>
(c === '+' || c === '-' || c === '*' || c === '/')
? eval(`a ${c} b`)
: 'Некорректная операция!'
calc(10)(5)('+') // 15
Использовать не рекомендуется по причинам безопасности.
JSR [179]
MDN [180]
Основные отличия состоят в следующем:
Window | Document |
---|---|
Является корневым узлом (верхним элементом) любой страницы | Является прямым потомков объекта window. Также известен как Document Object Model (DOM) |
Доступен по умолчанию (поэтому вместо window.property можно использовать property, например, вместо window.localStorage, можно использовать localStorage) | Доступен через window.document или просто document |
Имеет методы alert(), prompt() и т.д., а также свойства document, location и др. | Имеет методы getElementById(), getElementsByClassName(), querySelector() и т.д. |
JSR — Глобальный объект [181]
MDN — window [182]
JSR — DOM [183]
MDN — DOM [184]
Информацию об истории перемещений между страницами в браузере содержит свойство history объекта window. Для перехода к предыдущей или следующей странице следует использовать методы back(), next() или go():
const goBack = () => {
history.back()
// или
history.go(-1)
}
const goForward = () => history.forward()
MDN [185]
В JavaScript есть 8 основных типов:
Функция isNaN() преобразует значение в число и проверяет, является ли оно NaN.
isNaN('hello') // true
isNaN(100) // false
Более надежной версией данной функции является метод Number.isNaN(), представленный в ES6.
JSR [188]
MDN [189]
Основные отличия заключаются в следующем:
Необъявленные | Неопределенные |
---|---|
Не существуют в программе | Были объявлены без присвоения значения |
Попытка доступа заканчивается ошибкой | При попытке получить доступ возвращается undefined |
Поднимается (всплывает) в начало текущей области видимости | Также поднимается, но без присвоенного значения, т.е. со значением undefined (поднимается только объявление, но не инициализация) |
В браузере глобальные функции и переменные, объявленные с помощью ключевого слова «var», или без использованию ключевого слова (в нестрогом режиме), становятся свойствами глобального объекта window (не работает в модулях). Такие переменные доступны из любого места программы. Использовать глобальные переменные не рекомендуется. При необходимости создания глобальной переменной лучше сделать это явно:
window.currentUser = {
name: 'Иван'
}
// или
globalThis.currentUser = {
name: 'Иван'
}
console.log(currentUser.name) // Иван
JSR [181]
Создание глобальных переменных приводит к загрязнению глобального пространства имен, что может вызвать конфликт между названиями переменных. Это также усложняет отладку и тестирование кода.
JSR [181]
Глобальное свойство NaN является значением, представляющим собой не число (Not-a-Number). Точнее, NaN указывает на то, что значение является неправильным, но все-таки числом. Поэтому typeof NaN возвращает number.
parseInt('bla') // NaN
Math.sqrt(-1) // NaN
MDN [191]
Глобальная функция isFinite() преобразует аргумент в число и возвращает true, если оно является обычным (конечным) числом, т.е. не NaN, Infinity (положительная бесконечность), -Infinity (отрицательная бесконечность). В противном случае, возвращается false.
isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(100) // true
Также существует метод Number.isFinite(), который в отличие от isFinite() не преобразует аргумент в число перед проверкой.
MDN [192]
JSR [188]
Поток событий (распространение событий) — это порядок, в котором событие возникает на странице. Когда вы кликаете по элементу, вложенному в другие элементы, перед тем как событие достигнет целевого элемента, оно последовательно пройдет через все его родительские элементы, начиная от глобального объекта window. Существует три стадии распространения события:
JSR [193]
Всплытие — это стадия распространения события, когда событие сначала регистрируется на целевом элементе, а затем по цепочке из предков данного элемента поднимается до самого верхнего (внешнего) элемента — глобального объекта window.
JSR [193]
Погружение — это стадия возникновения события, когда оно сначала регистрируется на самом верхнем (внешнем) элементе (глобальном объекте window), а затем спускается вниз по цепочке из предков до целевого элемента.
JSR [193]
Это можно сделать разными способами:
function submitForm() {
document.forms[0].submit()
}
form.onsubmit = function(event) {
event.preventDefault()
// код
}
form.addEventListener('submit', event => {
event.preventDefault()
// код
})
Любая кнопка в форме по умолчанию имеет тип submit, т.е. служит для отправки формы.
MDN [194]
JSR [195]
Данную информацию содержит глобальный объект navigator. Некоторую часть этой информации можно получить через его свойство platform:
console.log(navigator.platform)
MDN [196]
Событие «DOMContentLoaded» возникает, когда первоначальный HTML документ полностью загружен и разобран без ожидания полной загрузки таблиц стилей, изображений или фреймов. Событие «load» возникает после полной загрузки страницы, включая все дополнительные ресурсы.
MDN — DOMContentLoaded [197]
MDN — load [198]
JSR [199]
Нативные объекты (native objects) являются частью языка и определяются в спецификации ECMAScript. Такими объектами являются, например, Number, String, Function, Object, Math, RegExp, Date и т.д. Хостовые объекты (host objects) предоставляются браузером или другой средой выполнения, например, Node.js. Такими объектами являются, например, window, document (DOM), XMLHttpRequest, Web API (стек вызовов — call stack, очередь задач — task queue) и др. Пользовательскими объектами (user objects) являются любые объекты, создаваемые в коде, например, объект, содержащий информацию о пользователе:
const user = {
name: 'Иван',
age: 20
}
Такими средствами являются:
JSR [200]
MDN — debugger [201]
MDN — Console [202]
Преимущества:
Недостатки
JSR — Промисы [156]
MDN — Promise [157]
JSR — Колбеки [158]
MDN — Callback [159]
Когда браузер загружает страницу, он разбирает HTML и генерирует из него DOM-объекты. Для узлов-элементов большинство стандартных HTML-атрибутов автоматически становятся свойствами DOM-объектов. Т.е. атрибут элемента указывается в разметке, а его свойство в DOM. Например, для тега «body» с атрибутом id=«page» у DOM-объекта будет свойство body.id=«page».
<input type="text" value="Доброе утро!">
// данный элемент имеет два атрибута: type и value
const input = document.querySelector('input')
// получаем атрибут
console.log(input.getAttribute('value'))
// получаем свойство
console.log(input.value)
// меняем значение атрибута
input.setAttribute('value', 'Добрый вечер!')
// меняем значение свойства
input.value = 'Добрый вечер!'
JSR [203]
Политика общего происхождения (одинакового источника) блокирует доступ к данным из другого источника. Источником является сочетание домена, хоста и порта. По умолчанию, совместное использование ресурсов (cross-origin resource sharing, CORS) запрещено, т.е. данные предоставляются только в ответ на запрос из того же источника, в котором они находятся. Это поведение можно изменить с помощью специальных HTTP-заголовков.
JSR [204]
MDN — SOP [205]
MDN — CORS [206]
Оператор void вычисляет переданное выражение и возвращает undefined. Обычно, когда мы кликаем по ссылке, браузер загружает новую сраницу или перезагружает текущую. С помощью выражения «void(0)» можно этого избежать:
<a href="javascript:void(0)" onclick="alert('Привет!')">Нажми на меня!
</a>
Перезагрузку страницы также можно предотвратить с помощью заглушки:
<a href="#">Битая ссылка</a>
// в этом случае символ "#" добавляется к URL в адресной строке
MDN [207]
Сам по себе JavaScript — это интерпретируемый язык программирования. Движок (runtime, engine) разбирает код, интерпретирует каждую строку и выполняет ее. Однако, в современных браузерах используется технология под названием «компиляция на лету» (just-in-time, JIT compilation), когда код компилируется перед выполнением. Это увеличивает время подготовки к выполнению кода, но существенно ускоряет само выполнение.
JSR [208]
MDN [209]
Да, JavaScript чувствителен к регистру. Поэтому ключевые слова, названия переменных, функций и объектов должны быть идентичными при их использовании. Например, const somename и const someName — это разные переменные, typeof(1) — number, а typeOf 1 — ReferenceError: typeOf не определена.
JSR [208]
MDN [209]
Нет, это два совершенно разных языка программирования. Однако, они оба относятся к объектно-ориентированным языкам и, как и множество других языков, используют похожий синтаксис (if, else, for, switch, break, continue и т.д.). Java в JavaScript — это маркетинговый ход.
JSR [208]
MDN [209]
Событие — это реакция браузера на определенное действие. Таким действием может быть действие пользователя, например, нажатие кнопки или ввод текста, загрузка страницы, получение ответа на запрос и т.д. (т.е. действия, приводящие к возникновению событий, не обязательно зависят от пользователя). События регистрируются с целью их дальнейшей обработки.
button.onclick = () => alert('Привет!')
input.addEventListener('change', function() {
p.textContent = this.value
})
window.onload = () => console.log('Страница полностью загружена.')
Habr — Из чего сделан JavaScript? [212]
Habr — Как работает JS: о внутреннем устройстве V8 и оптимизации кода [213]
Medium — Разбираемся с путаницей между JavaScript методами slice(), splice() и split() [214]
Medium — Prototypes in JavaScript [215]
Medium — Understanding Prototypes in JavaScript [216]
Medium — Подробно о методах apply(), call() и bind(), необходимых каждому JavaScript разработчику [217]
DigitalOcean — Знакомство с объектами map и set в JavaScript [218]
Medium — Why Should We Stop Using Objects As Maps in JavaScript? [219]
Habr — 5 рекомендаций по написанию качественных стрелочных функций [220]
Habr — Каррирование функций в JavaScript [221]
Medium — Понимаем каррирование в JavaScript [222]
Medium — Curry and Function Composition [223]
Habr — Зачем в JavaScript нужен строгий режим? [224]
Medium — Advanced JavaScript ES6 — Temporal Dead Zone, Default Parameters And Let vs Var — Deep dive! [225]
Medium — Понимаем немедленно вызываемые функции IIFE и немного больше [226]
Habr — Почему пора перестать использовать JavaScript IIFE [227]
Habr — Мемоизация в JS и ускорение функций [228]
Medium — What is Memoization in Javascript? [229]
Medium — Разбираемся с “поднятием” (hoisting) в JavaScript [230]
DigitalOcean — Понимание понятия классов в JavaScript [231]
Habr — Как работает JS: классы и наследование, транспиляция в Babel и TypeScript [232]
Habr — Классы и фабричные функции в JavaScript. Что выбрать? [233]
Medium — JavaScript Classes: An In-Depth look (Part 1) [234]
Medium — Понимаем замыкания в JavaScript. Раз и навсегда [235]
Habr — Замыкания в JavaScript для начинающих [236]
Habr — Дэн Абрамов о замыканиях в JavaScript [237]
Habr — Понимание (всех) «модульных» форматов и инструментов JavaScript [238]
FreeCodeCamp — JavaScript Modules: A Beginner’s Guide [239]
Habr — Использование JavaScript-модулей в продакшне: современное состояние дел. Часть 1 [240]
Medium — Introduction to ES6 modules [241]
Habr — Области видимости в JavaScript [242]
DP — JavaScript Scope Explained in Simple Words [243]
Habr — Визуализация работы сервис-воркеров [244]
Habr — Как работает JS: сервис-воркеры [245]
Habr — Service Workers. Инструкция по применению [246]
GoogleDevelopers — Service Workers: an Introduction [247]
Habr — 5 малоизвестных возможностей JSON.stringify() [248]
Habr — Хранилище для веба [249]
Habr — Как работает JS: системы хранения данных [250]
WebDevBlog — Изучаем IndexedDB [251]
GoogleDevelopers — Working with IndexedDB [252]
Medium — A quick but complete guide to IndexedDB and storing data in browsers [253]
Habr — Web Storage API: примеры использования [254]
Medium — Как работать с localStorage в JavaScript [255]
Habr — Как работает JS: веб-воркеры и пять сценариев их использования [256]
Habr — Прослушиватели событий и веб-воркеры [257]
Medium — A Simple Introduction to Web Workers in JavaScript [258]
Habr — Использование промисов в JavaScript [259]
Habr — Элегантное асинхронное программирование с помощью промисов [260]
Habr — Визуализация промисов и Async/Await [261]
Habr — Распространенные ошибки при работе с промисами в JavaScript, о которых должен знать каждый [262]
Medium — Understanding Throttling and Debouncing [263]
Redd — Debounce vs Throttle: Definitive Visual Guide [264]
Medium — A Look at Server-Sent Events [265]
Habr — SSEGWSW: Server-Sent Events Gateway by Service Workers [266]
GoogleDeveloper — Get Started with Debugging JavaScript in Chrome DevTools [267]
Microsoft — Отладка приложения JavaScript или TypeScript в Visual Studio [268]
Habr — Политика общего происхождения и CORS: визуальное руководство [269]
Автор: Igor Agapov
Источник [270]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/356543
Ссылки в тексте:
[1] этого репозитория: https://github.com/sudheerj/javascript-interview-questions
[2] здесь (PWA Store): https://progressiveapp.store/pwa/JSQ
[3] здесь (Netlify): https://jsq.netlify.app/
[4] Как создать объект?: #0
[5] Что такое прототипы?: #1
[6] В чем разница между Call, Apply и Bind?: #2
[7] Что такое JSON и какие у него есть методы?: #3
[8] Что делает метод Array.slice()?: #4
[9] Что делаем метод Array.splice()?: #5
[10] В чем разница между slice() и splice()?: #6
[11] Как сравниваются объекты (objects) и карты (maps)?: #7
[12] В чем разница между операторами "==" и "==="?: #8
[13] Что такое лямбда- или стрелочные функции?: #9
[14] Почему функции называют объектами первого класса?: #10
[15] Что такое функция первого порядка?: #11
[16] Что такое функция высшего порядка?: #12
[17] Что такое унарная функция?: #13
[18] Что такое каррирование (currying)?: #14
[19] Что такое чистая функция?: #15
[20] Для чего используется ключевое слово «let»?: #16
[21] В чем разница между let и var?: #17
[22] Почему в качестве ключевого слова было выбрано слово «let»?: #18
[23] Как переопределить переменную в блоке switch?: #19
[24] Что такое временная мертвая зона?: #20
[25] Что такое немедленно вызываемое функциональное выражение (IIFE, Immediately Invoked Function Expression)?: #21
[26] В чем заключаются преимущества использования модулей?: #22
[27] Что такое запоминание или мемоизация?: #23
[28] Что такое поднятие переменных (hoisting)?: #24
[29] Что такое класс?: #25
[30] Что такое замыкание?: #26
[31] Что такое модуль?: #27
[32] Зачем нужны модули?: #28
[33] Что такое область видимости?: #29
[34] Что такое сервис-воркер (service worker)?: #30
[35] Как взаимодействовать с объектной моделью документа (Document Object Model, DOM) с помощью сервис-воркеров?: #31
[36] Как повторно использовать информацию при перезапуске сервис-воркера?: #32
[37] Что такое индексированная база данных (IndexedDB)?: #33
[38] Что такое веб-хранилище (Web Storage)?: #34
[39] Что такое postMessage?: #35
[40] Что такое куки (cookie)?: #36
[41] Зачем нужны куки?: #37
[42] Какими возможностями обладают куки?: #38
[43] Как удалить куки?: #39
[44] В чем разница между куки, локальным и сессионным хранилищами?: #40
[45] В чем главное отличие между локальным и сессионным хранилищами?: #41
[46] Как получить доступ к веб-хранилищу?: #42
[47] Какие методы предоставляет сессионное хранилище?: #43
[48] Какое событие возникает при работе с веб-хранилищем?: #44
[49] Для чего используется веб-хранилище?: #45
[50] Как определить поддержку веб-хранилища браузером?: #46
[51] Как определить поддержку сервис-воркеров браузером?: #47
[52] Приведите пример веб-воркера: #48
[53] Назовите ограничения веб-воркеров по работе с DOM: #49
[54] Что такое промис (обещание, promise)?: #50
[55] Зачем нужны промисы?: #51
[56] Назовите три возможных состояния промиса: #52
[57] Что такое функция обратного вызова (колбек)?: #53
[58] Зачем нужны колбеки?: #54
[59] Что такое ад колбеков?: #55
[60] Что такое события, отправленные сервером (server-sent events, SSE)?: #56
[61] Как получать сообщения (уведомления или события), отправленные сервером?: #57
[62] Как проверить поддержку SSE браузером?: #58
[63] Какие события возникают при работе с SSE?: #59
[64] Назовите основные правила работы с промисами: #60
[65] Что такое колбек в колбеке?: #61
[66] Что такое цепочка из промисов?: #62
[67] Что такое Promise.all()?: #63
[68] Что такое Promise.race()?: #64
[69] Что такое строгий режим?: #65
[70] Зачем нужен строгий режим?: #66
[71] Как включить строгий режим?: #67
[72] Для чего используется двойное отрицание?: #68
[73] Для чего используется оператор «delete»?: #69
[74] Для чего используется оператор «typeof»?: #70
[75] Что такое undefined?: #71
[76] Что такое null?: #72
[77] В чем разница между null и undefined?: #73
[78] Что такое eval?: #74
[79] В чем разница между window и document?: #75
[80] Как получить доступ к истории браузера?: #76
[81] Какие типы данных существуют в JavaScript?: #77
[82] Что делает isNaN()?: #78
[83] В чем разница между необъявленными и неопределенными переменными?: #79
[84] Что такое глобальные переменные?: #80
[85] Какие проблемы влечет за собой создание глобальных переменных?: #81
[86] Что такое NaN?: #82
[87] Что делает isFinite()?: #83
[88] Что такое поток событий (event flow)?: #84
[89] Что такое всплытие события?: #85
[90] Что такое погружение или захват события?: #86
[91] Как отправить форму на обработку?: #87
[92] Как получить информацию об операционной системе?: #88
[93] В чем разница между событиями «DOMContentLoaded» и «load»?: #89
[94] В чем разница между нативными, хостовыми (принадлежащими среде выполнения кода) и пользовательскими объектами?: #90
[95] Какие средства используются для откладки кода?: #91
[96] В чем заключаются преимущества и недостатки промисов по сравнению с колбеками?: #92
[97] В чем разница между атрибутом и свойством элемента?: #93
[98] Что такое политика общего происхождения (same-origin policy)?: #94
[99] Что делает void 0?: #95
[100] JavaScript — это компилируемый или интерпретируемый язык программирования?: #96
[101] Чувствителен ли JavaScript к регистру?: #97
[102] Связаны ли Java и JavaScript?: #98
[103] Что такое событие (event)?: #99
[104] Дополнительная литература: #100
[105] JSR: https://learn.javascript.ru/object
[106] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object
[107] JSR: https://learn.javascript.ru/prototype-inheritance
[108] MDN: https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object_prototypes
[109] JSR — Call/Apply: https://learn.javascript.ru/call-apply-decorators
[110] JSR — Bind: https://learn.javascript.ru/bind
[111] MDN — Call: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/call
[112] MDN — Apply: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
[113] MDN — Bind: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
[114] JSR: https://learn.javascript.ru/json
[115] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/JSON
[116] JSR: https://learn.javascript.ru/array-methods
[117] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
[118] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
[119] JSR: https://learn.javascript.ru/map-set
[120] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Map
[121] JSR: https://learn.javascript.ru/comparison
[122] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/%D0%9E%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B_%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F
[123] JSR: https://learn.javascript.ru/arrow-functions-basics
[124] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions
[125] JSR: https://learn.javascript.ru/function-basics
[126] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/First-class_Function
[127] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F
[128] JSR: https://learn.javascript.ru/currying-partials
[129] JSR: https://learn.javascript.ru/variables
[130] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/let
[131] MDN — var: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/var
[132] JSR: https://learn.javascript.ru/switch
[133] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/switch
[134] JSR: https://learn.javascript.ru/closure#bloki-koda-i-tsikly-iife
[135] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/IIFE
[136] JSR: https://learn.javascript.ru/modules-intro
[137] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Modules
[138] JSR: https://learn.javascript.ru/var
[139] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/%D0%9F%D0%BE%D0%B4%D0%BD%D1%8F%D1%82%D0%B8%D0%B5
[140] JSR: https://learn.javascript.ru/class
[141] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes
[142] JSR: https://learn.javascript.ru/closure
[143] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Closures
[144] MDN: https://developer.mozilla.org/ru/docs/Glossary/Scope
[145] MDN: https://developer.mozilla.org/ru/docs/Web/API/ServiceWorker
[146] MDN — postMessage: https://developer.mozilla.org/ru/docs/Web/API/Client/postMessage
[147] JSR: https://learn.javascript.ru/indexeddb
[148] MDN: https://developer.mozilla.org/ru/docs/Web/API/IndexedDB_API
[149] JSR: https://learn.javascript.ru/localstorage
[150] MDN: https://developer.mozilla.org/ru/docs/Web/API/Web_Storage_API
[151] JSR: https://learn.javascript.ru/cookie
[152] MDN: https://developer.mozilla.org/ru/docs/Web/API/Document/cookie
[153] CanIUse: https://caniuse.com/#feat=namevalue-storage
[154] CanIUse: https://caniuse.com/#feat=serviceworkers
[155] MDN: https://developer.mozilla.org/ru/docs/Web/API/Web_Workers_API
[156] JSR: https://learn.javascript.ru/promise-basics
[157] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise
[158] JSR: https://learn.javascript.ru/callbacks
[159] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F_%D0%BE%D0%B1%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%B2%D1%8B%D0%B7%D0%BE%D0%B2%D0%B0
[160] JSR: https://learn.javascript.ru/server-sent-events
[161] MDN: https://developer.mozilla.org/ru/docs/Web/API/Server-sent_events
[162] MDN: https://developer.mozilla.org/ru/docs/Web/API/EventSource
[163] CanIUse: https://caniuse.com/#feat=eventsource
[164] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
[165] JSR: https://learn.javascript.ru/promise-api
[166] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
[167] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Strict_mode
[168] JSR: https://learn.javascript.ru/strict-mode
[169] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Logical_NOT
[170] JSR: https://learn.javascript.ru/logical-ops
[171] JSR: https://learn.javascript.ru/object#literaly-i-svoystva
[172] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/delete
[173] JSR: https://learn.javascript.ru/types#type-typeof
[174] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/typeof
[175] JSR: https://learn.javascript.ru/types#znachenie-undefined
[176] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/undefined
[177] JSR: https://learn.javascript.ru/types#znachenie-null
[178] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/null
[179] JSR: https://learn.javascript.ru/eval
[180] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/eval
[181] JSR — Глобальный объект: https://learn.javascript.ru/global-object
[182] MDN — window: https://developer.mozilla.org/ru/docs/Web/API/Window
[183] JSR — DOM: https://learn.javascript.ru/dom-nodes
[184] MDN — DOM: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/DOM
[185] MDN: https://developer.mozilla.org/ru/docs/Web/API/History
[186] JSR: https://learn.javascript.ru/types
[187] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Data_structures
[188] JSR: https://learn.javascript.ru/number
[189] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/isNaN
[190] MDN: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/Variable
[191] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/NaN
[192] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/isFinite
[193] JSR: https://learn.javascript.ru/bubbling-and-capturing
[194] MDN: https://developer.mozilla.org/ru/docs/Web/API/HTMLFormElement/submit
[195] JSR: https://learn.javascript.ru/forms-submit
[196] MDN: https://developer.mozilla.org/ru/docs/Web/API/Navigator
[197] MDN — DOMContentLoaded: https://developer.mozilla.org/ru/docs/Web/API/Document/DOMContentLoaded_event
[198] MDN — load: https://developer.mozilla.org/ru/docs/Web/Events/load
[199] JSR: https://learn.javascript.ru/onload-ondomcontentloaded
[200] JSR: https://learn.javascript.ru/debugging-chrome
[201] MDN — debugger: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/debugger
[202] MDN — Console: https://developer.mozilla.org/ru/docs/Web/API/Console
[203] JSR: https://learn.javascript.ru/dom-attributes-and-properties
[204] JSR: https://learn.javascript.ru/cross-window-communication
[205] MDN — SOP: https://developer.mozilla.org/ru/docs/Web/Security/Same-origin_policy
[206] MDN — CORS: https://developer.mozilla.org/ru/docs/Web/HTTP/CORS
[207] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/void
[208] JSR: https://learn.javascript.ru/intro
[209] MDN: https://developer.mozilla.org/ru/docs/Web/JavaScript
[210] MDN: https://developer.mozilla.org/ru/docs/Web/API/Event
[211] JSR: https://learn.javascript.ru/introduction-browser-events#event-object
[212] Habr — Из чего сделан JavaScript?: https://habr.com/ru/company/ruvds/blog/482472/
[213] Habr — Как работает JS: о внутреннем устройстве V8 и оптимизации кода: https://habr.com/ru/company/ruvds/blog/337460/
[214] Medium — Разбираемся с путаницей между JavaScript методами slice(), splice() и split(): https://medium.com/@stasonmars/%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%D1%81%D1%8F-%D1%81-%D0%BF%D1%83%D1%82%D0%B0%D0%BD%D0%B8%D1%86%D0%B5%D0%B9-%D0%BC%D0%B5%D0%B6%D0%B4%D1%83-javascript-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%B0%D0%BC%D0%B8-slice-splice-%D0%B8-split-6e72363baf1d
[215] Medium — Prototypes in JavaScript: https://medium.com/better-programming/prototypes-in-javascript-5bba2990e04b
[216] Medium — Understanding Prototypes in JavaScript: https://medium.com/madhash/understanding-prototypes-in-javascript-e466244da086
[217] Medium — Подробно о методах apply(), call() и bind(), необходимых каждому JavaScript разработчику: https://medium.com/@stasonmars/%D0%BF%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%BE-%D0%BE-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%B0%D1%85-apply-call-%D0%B8-bind-%D0%BD%D0%B5%D0%BE%D0%B1%D1%85%D0%BE%D0%B4%D0%B8%D0%BC%D1%8B%D1%85-%D0%BA%D0%B0%D0%B6%D0%B4%D0%BE%D0%BC%D1%83-javascript-%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D1%83-ddd5f9b06290
[218] DigitalOcean — Знакомство с объектами map и set в JavaScript: https://www.digitalocean.com/community/tutorials/understanding-map-and-set-objects-in-javascript-ru
[219] Medium — Why Should We Stop Using Objects As Maps in JavaScript?: https://medium.com/better-programming/why-should-we-stop-using-objects-as-maps-in-javascript-19c0275da72f
[220] Habr — 5 рекомендаций по написанию качественных стрелочных функций: https://habr.com/ru/company/ruvds/blog/486690/
[221] Habr — Каррирование функций в JavaScript: https://habr.com/ru/company/ruvds/blog/427295/
[222] Medium — Понимаем каррирование в JavaScript: https://medium.com/@stasonmars/%D0%BF%D0%BE%D0%BD%D0%B8%D0%BC%D0%B0%D0%B5%D0%BC-%D0%BA%D0%B0%D1%80%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B2-javascript-5ec4a1d88827
[223] Medium — Curry and Function Composition: https://medium.com/javascript-scene/curry-and-function-composition-2c208d774983
[224] Habr — Зачем в JavaScript нужен строгий режим?: https://habr.com/ru/company/ruvds/blog/477284/
[225] Medium — Advanced JavaScript ES6 — Temporal Dead Zone, Default Parameters And Let vs Var — Deep dive!: https://medium.com/nmc-techblog/advanced-javascript-es6-temporal-dead-zone-default-parameters-and-let-vs-var-deep-dive-ca588fcde21b
[226] Medium — Понимаем немедленно вызываемые функции IIFE и немного больше: https://medium.com/@stasonmars/%D0%BF%D0%BE%D0%BD%D0%B8%D0%BC%D0%B0%D0%B5%D0%BC-%D0%BD%D0%B5%D0%BC%D0%B5%D0%B4%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE-%D0%B2%D1%8B%D0%B7%D1%8B%D0%B2%D0%B0%D0%B5%D0%BC%D1%8B%D0%B5-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8-iife-%D0%B8-%D0%BD%D0%B5%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5-ff8e9ba409eb
[227] Habr — Почему пора перестать использовать JavaScript IIFE: https://habr.com/ru/company/ruvds/blog/494868/
[228] Habr — Мемоизация в JS и ускорение функций: https://habr.com/ru/company/ruvds/blog/332384/
[229] Medium — What is Memoization in Javascript?: https://medium.com/@mike_wong/what-is-memoization-in-javascript-5c6cdef49ad2
[230] Medium — Разбираемся с “поднятием” (hoisting) в JavaScript: https://medium.com/@stasonmars/%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%D1%81%D1%8F-%D1%81-%D0%BF%D0%BE%D0%B4%D0%BD%D1%8F%D1%82%D0%B8%D0%B5%D0%BC-hoisting-%D0%B2-javascript-7d2d27bc51f1
[231] DigitalOcean — Понимание понятия классов в JavaScript: https://www.digitalocean.com/community/tutorials/understanding-classes-in-javascript-ru
[232] Habr — Как работает JS: классы и наследование, транспиляция в Babel и TypeScript: https://habr.com/ru/company/ruvds/blog/415377/
[233] Habr — Классы и фабричные функции в JavaScript. Что выбрать?: https://habr.com/ru/company/ruvds/blog/352198/
[234] Medium — JavaScript Classes: An In-Depth look (Part 1): https://medium.com/javascript-in-plain-english/javascript-classes-an-in-depth-look-part-1-47d8f4e77cbd
[235] Medium — Понимаем замыкания в JavaScript. Раз и навсегда: https://medium.com/@stasonmars/%D0%BF%D0%BE%D0%BD%D0%B8%D0%BC%D0%B0%D0%B5%D0%BC-%D0%B7%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D1%8F-%D0%B2-javascript-%D1%80%D0%B0%D0%B7-%D0%B8-%D0%BD%D0%B0%D0%B2%D1%81%D0%B5%D0%B3%D0%B4%D0%B0-c211805b6898
[236] Habr — Замыкания в JavaScript для начинающих: https://habr.com/ru/company/ruvds/blog/424967/
[237] Habr — Дэн Абрамов о замыканиях в JavaScript: https://habr.com/ru/company/ruvds/blog/513764/
[238] Habr — Понимание (всех) «модульных» форматов и инструментов JavaScript: https://habr.com/ru/post/501198/
[239] FreeCodeCamp — JavaScript Modules: A Beginner’s Guide: https://www.freecodecamp.org/news/javascript-modules-a-beginner-s-guide-783f7d7a5fcc/
[240] Habr — Использование JavaScript-модулей в продакшне: современное состояние дел. Часть 1: https://habr.com/ru/company/ruvds/blog/466537/
[241] Medium — Introduction to ES6 modules: https://medium.com/backticks-tildes/introduction-to-es6-modules-49956f580da
[242] Habr — Области видимости в JavaScript: https://habr.com/ru/company/ruvds/blog/337038/
[243] DP — JavaScript Scope Explained in Simple Words: https://dmitripavlutin.com/javascript-scope/
[244] Habr — Визуализация работы сервис-воркеров: https://habr.com/ru/post/491840/
[245] Habr — Как работает JS: сервис-воркеры: https://habr.com/ru/company/ruvds/blog/349858/
[246] Habr — Service Workers. Инструкция по применению: https://habr.com/ru/company/2gis/blog/345552/
[247] GoogleDevelopers — Service Workers: an Introduction: https://developers.google.com/web/fundamentals/primers/service-workers
[248] Habr — 5 малоизвестных возможностей JSON.stringify(): https://habr.com/ru/post/491252/
[249] Habr — Хранилище для веба: https://habr.com/ru/post/500834/
[250] Habr — Как работает JS: системы хранения данных: https://habr.com/ru/company/ruvds/blog/415505/
[251] WebDevBlog — Изучаем IndexedDB: https://webdevblog.ru/izuchaem-indexeddb/
[252] GoogleDevelopers — Working with IndexedDB: https://developers.google.com/web/ilt/pwa/working-with-indexeddb
[253] Medium — A quick but complete guide to IndexedDB and storing data in browsers: https://medium.com/free-code-camp/a-quick-but-complete-guide-to-indexeddb-25f030425501
[254] Habr — Web Storage API: примеры использования: https://habr.com/ru/post/496348/
[255] Medium — Как работать с localStorage в JavaScript: https://medium.com/@stasonmars/%D0%BA%D0%B0%D0%BA-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D1%82%D1%8C-%D1%81-localstorage-%D0%B2-javascript-5aad737535d4
[256] Habr — Как работает JS: веб-воркеры и пять сценариев их использования: https://habr.com/ru/company/ruvds/blog/348424/
[257] Habr — Прослушиватели событий и веб-воркеры: https://habr.com/ru/company/ruvds/blog/479268/
[258] Medium — A Simple Introduction to Web Workers in JavaScript: https://medium.com/young-coder/a-simple-introduction-to-web-workers-in-javascript-b3504f9d9d1c
[259] Habr — Использование промисов в JavaScript: https://habr.com/ru/company/ruvds/blog/418085/
[260] Habr — Элегантное асинхронное программирование с помощью промисов: https://habr.com/ru/post/488762/
[261] Habr — Визуализация промисов и Async/Await: https://habr.com/ru/post/501702/
[262] Habr — Распространенные ошибки при работе с промисами в JavaScript, о которых должен знать каждый: https://habr.com/ru/post/484466/
[263] Medium — Understanding Throttling and Debouncing: https://blog.bitsrc.io/understanding-throttling-and-debouncing-973131c1ba07
[264] Redd — Debounce vs Throttle: Definitive Visual Guide: https://redd.one/blog/debounce-vs-throttle
[265] Medium — A Look at Server-Sent Events: https://medium.com/conectric-networks/a-look-at-server-sent-events-54a77f8d6ff7
[266] Habr — SSEGWSW: Server-Sent Events Gateway by Service Workers: https://habr.com/ru/company/tinkoff/blog/471718/
[267] GoogleDeveloper — Get Started with Debugging JavaScript in Chrome DevTools: https://developers.google.com/web/tools/chrome-devtools/javascript
[268] Microsoft — Отладка приложения JavaScript или TypeScript в Visual Studio: https://docs.microsoft.com/ru-ru/visualstudio/javascript/debug-nodejs?view=vs-2019
[269] Habr — Политика общего происхождения и CORS: визуальное руководство: https://habr.com/ru/post/514684/
[270] Источник: https://habr.com/ru/post/517002/?utm_source=habrahabr&utm_medium=rss&utm_campaign=517002
Нажмите здесь для печати.