Skip to content

AndrewMosh/javascript_interview_cheatsheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 

Repository files navigation

Содержание

No. Вопросы
1 Способы создания объекта
2 Цепочка прототипов
3 Разница между call, apply и bind
4 Json и основные операции с ним
5 Для чего нужен метод slice
6 Для чего нужен метод splice
7 Разница между slice() и splice()
8 Как сравнить Object и Map
9 Разница между == и === операторами
10 Лямбда функции и стрелочные функции
11 Что такое функция первого класса в JavaScript?
12 Функции первого порядка
13 Что такое функция высшего порядка в JavaScript?
14 Унарная функция
15 Что такое каррирование в JavaScript?
16 Что такое чистая функция в JavaScript?
17 Какова цель ключевого слова "let" в JavaScript?
18 В чем разница между let и var в JavaScript?
19 Как переопределить переменные в блоке switch без ошибки в JavaScript?
20 Что такое "Temporal Dead Zone" в JavaScript?
21 Что такое IIFE (Immediately Invoked Function Expression) в JavaScript?
22 Как декодировать или закодировать URL в JavaScript?
23 Что такое мемоизация (memoization) в JavaScript?
24 Что такое хойстинг (hoisting) в JavaScript?
25 Что такое классы в ES6 (ECMAScript 2015)?
26 Что такое замыкания (closures) в JavaScript?
27 Что такое модули (modules) в JavaScript?
28 Что такое область видимости (scope) в JavaScript?
29 Что такое сервисный работник (service worker) в JavaScript?
30 Как осуществлять изменение DOM с использованием сервисного работника?
31 Как переиспользовать информацию между перезапусками сервисного работника?
32 Что такое IndexedDB в JavaScript?
33 Что такое веб-хранилище (web storage) в JavaScript?
34 Что такое сообщение postMessage в JavaScript?
35 Что такое cookie (куки)?
36 Зачем нужны куки (Cookies)?
37 Какие параметры можно задать в куки (Cookie)?
38 Как удалить куки (Cookie)?
39 В чем разница между куками, локальным хранилищем и сессионным хранилищем?
40 В чем основное различие между локальным хранилищем и сессионным хранилищем?
41 Как получить доступ к веб-хранилищу (web storage)?
42 Какие методы доступны в сессионном хранилище (sessionStorage)?
43 Что такое событие хранилища (storage event) и его обработчик событий в JavaScript?
44 Зачем нужно веб-хранилище (web storage)?
45 Как проверить поддержку веб-хранилища браузером?
46 Как проверить поддержку веб-воркеров (web workers) в браузере?
47 Приведите пример использования веб-воркера (web worker) в JavaScript
48 Какие ограничения существуют у веб-воркеров по работе с DOM?
49 Что такое промис (Promise)?
50 Зачем нужен промис (Promise)?
51 Каковы три состояния промиса (Promise)?
51 Что такое функция обратного вызова (callback function)?
53 Зачем нужны функции обратного вызова (callback)?
54 Что такое "callback hell"?
55 Что такое события, отправляемые с сервера (Server-Sent Events)?
56 Как получать уведомления событий, отправляемых с сервера (Server-Sent Events)?
57 Как проверить поддержку браузером событий, отправляемых с сервера (Server-Sent Events)?
58 Какие события доступны для событий, отправляемых с сервера (Server-Sent Events)?
59 Каковы основные правила работы с промисами (Promise)?
60 то такое "callback внутри callbackа" (callback in callback)?
61 Что такое цепочка промисов (Promise Chaining)?
62 Что такое Promise.all?
63 Какова цель метода race в промисах?
64 Что такое строгий режим (strict mode) в JavaScript?
65 Зачем нужен строгий режим (strict mode)?
66 Как объявить строгий режим (strict mode)?
67 Какова цель двойного восклицательного знака в JavaScript?
68 Какова цель оператора delete в JavaScript?
69 Что такое оператор typeof?
70 Что такое свойство со значением undefined?
71 Что такое значение null?
72 В чем разница между значениями null и undefined?
73 Что такое eval?
74 В чем разница между window и document?
75 Как получить доступ к истории браузера в JavaScript?
76 Как определить, включена ли клавиша Caps Lock?
77 Что такое isNaN?
78 Каковы различия между необъявленными и неопределенными переменными?
79 Что такое глобальные переменные?
80 Какие проблемы связаны с использованием глобальных переменных?
81 Что такое свойство NaN?
82 Каково назначение функции isFinite?
83 Что такое поток событий (Event Flow)?
84 Что такое всплытие событий (Event Bubbling)?
85 Что такое захват событий (Event Capturing)?
86 Как отправить форму с помощью JavaScript?
87 Как получить информацию о операционной системе?
88 В чем разница между событиями загрузки документа и DOMContentLoaded?
89 В чем разница между встроенными, хост объектами и объектами пользовательского кода?
90 Какие инструменты или методы используются для отладки кода на JavaScript?
91 Каковы плюсы и минусы промисов по сравнению с обратными вызовами?
92 В чем разница между атрибутом и свойством?
93 Что такое политика одного источника (Same Origin Policy)?
94 Какова цель использования void 0 в JavaScript?
95 Является ли JavaScript компилируемым или интерпретируемым языком?
96 Является ли JavaScript языком, чувствительным к регистру символов?
97 Что такое события (events)?

Способы создания объекта

  1. Литеральная нотация:
var obj = {}; // пустой объект
var person = {
  name: "John",
  age: 30,
  location: "New York"
};
  1. Функция-конструктор:
function Person(name, age, location) {
  this.name = name;
  this.age = age;
  this.location = location;
}

var john = new Person("John", 30, "New York");
  1. Object.create():
var personProto = {
  sayHello: function() {
    console.log("Hello!");
  }
};

var john = Object.create(personProto);
john.name = "John";
john.age = 30;
john.location = "New York";
  1. Class (введена в ECMAScript 2015):
class Person {
  constructor(name, age, location) {
    this.name = name;
    this.age = age;
    this.location = location;
  }
}

var john = new Person("John", 30, "New York");

⬆ Наверх

Цепочка прототипов

Прототипное наследование в JavaScript основано на концепции цепочки прототипов, или прототипной цепочки. Каждый объект в JavaScript имеет свойство прототипа (proto), которое ссылается на другой объект, называемый прототипом.

Если свойство не найдено в самом объекте, JavaScript будет искать его в прототипе, а затем в прототипе прототипа, и так далее, пока не будет найдено свойство или прототип станет равным null. Эта последовательность поиска свойств называется прототипной цепочкой.

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

Например, если у объекта obj нет свойства x, JavaScript будет искать его в obj.__proto__, затем в obj.__proto__.__proto__ и так далее, пока не будет найдено либо встретится null. ⬆ Наверх

Разница между call, apply и bind

В JavaScript, методы call, apply и bind используются для установки контекста выполнения функции и передачи аргументов.

Метод call вызывает функцию с заданным контекстом и передает аргументы в виде отдельных значений. Синтаксис: function.call(context, arg1, arg2, ...).

Метод apply также вызывает функцию с заданным контекстом, но передает аргументы в виде массива. Синтаксис: function.apply(context, [arg1, arg2, ...]).

Метод bind создает новую функцию, привязывая ее к определенному контексту выполнения и, при необходимости, предоставляя некоторые аргументы. Этот метод не вызывает функцию немедленно, а возвращает новую функцию, которую можно вызвать позже. Синтаксис: function.bind(context, arg1, arg2, ...). Вызов новой функции bind с переданными аргументами вызовет исходную функцию с указанным контекстом.

Основное отличие между call, apply и bind заключается в способе передачи аргументов. call передает аргументы в виде отдельных значений, apply передает аргументы в виде массива, а bind создает новую функцию с предустановленными аргументами. ⬆ Наверх

Json и основные операции с ним

JSON (JavaScript Object Notation) - это формат обмена данными, основанный на языке JavaScript. Он используется для передачи структурированных данных между клиентским и серверным приложениями. JSON представляет данные в удобном для чтения и записи формате и легко интерпретируется как людьми, так и компьютерами.

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

  1. Создание JSON-объекта: Можно создавать JSON-объекты, используя фигурные скобки {}. Внутри объекта можно определить пары "ключ-значение".

  2. Запись данных в JSON: Значения могут быть строками, числами, логическими значениями (true/false), null или другими JSON-объектами или массивами.

  3. Чтение данных из JSON: Можно обратиться к значениям в JSON с помощью их ключей и получить доступ к содержимому.

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

  5. Удаление данных из JSON: Ключи и их значения могут быть удалены из JSON-объекта.

  6. Парсинг и сериализация: JSON может быть преобразован из строки в формате JSON в структуру данных и обратно с помощью парсинга и сериализации.

JSON является широко распространенным форматом данных, который часто используется в веб-разработке и API. Он легко читается компьютерами и людьми, и может быть использован практически на любом языке программирования. ⬆ Наверх

Для чего нужен метод slice

Метод slice() в JavaScript используется для создания нового массива, содержащего копию части исходного массива. Он позволяет выбирать элементы из исходного массива, начиная с указанного индекса и до определенного индекса (не включая его).

Синтаксис метода slice() выглядит следующим образом:

array.slice(start, end);

⬆ Наверх Где:

  • start - необязательный параметр, определяющий индекс, с которого начинается выбор элементов. Если start не указан, метод начинает выбор с индекса 0.
  • end - необязательный параметр, указывающий индекс, до которого выбираются элементы. Метод выбирает элементы до этого индекса, но не включая его. Если end не указан, метод выбирает все элементы от start до конца массива.

Метод slice() возвращает новый массив, содержащий выбранные элементы. Исходный массив при этом не изменяется.

Пример использования метода slice():

let fruits = ["apple", "banana", "orange", "grapefruit", "kiwi"];

let citrus = fruits.slice(2, 4);
console.log(citrus); // ['orange', 'grapefruit']

let lastTwo = fruits.slice(-2);
console.log(lastTwo); // ['grapefruit', 'kiwi']

let copy = fruits.slice();
console.log(copy); // ['apple', 'banana', 'orange', 'grapefruit', 'kiwi']

В первом примере метод slice(2, 4) выбирает элементы с индексами 2 и 3 из массива fruits и возвращает новый массив ['orange', 'grapefruit'].

Во втором примере метод slice(-2) выбирает последние два элемента из массива fruits и возвращает новый массив ['grapefruit', 'kiwi'].

В последнем примере метод slice() без аргументов создает копию исходного массива fruits и возвращает новый массив ['apple', 'banana', 'orange', 'grapefruit', 'kiwi']. ⬆ Наверх

Для чего нужен метод splice

Метод splice() в JavaScript используется для изменения содержимого массива путем удаления, замены или добавления элементов. Он может принимать несколько аргументов, включая индекс начала изменения, количество элементов для удаления и элементы, которые нужно добавить.

Например, если мы хотим удалить элементы из массива, мы можем использовать splice() следующим образом:

const fruits = ["яблоко", "груша", "банан", "апельсин"];

// Удаляем один элемент начиная с индекса 1
fruits.splice(1, 1);
// Результат: ['яблоко', 'банан', 'апельсин']

// Удаляем два элемента начиная с индекса 0 и заменяем их другими элементами
fruits.splice(0, 2, "манго", "киви");
// Результат: ['манго', 'киви', 'банан', 'апельсин']

Таким образом, метод splice() позволяет нам гибко изменять содержимое массива, добавлять новые элементы и удалять существующие. ⬆ Наверх

Разница между slice() и splice()

Методы slice() и splice() в JavaScript имеют разные цели и функциональность.

Метод slice() используется для создания нового массива, который будет содержать выбранные элементы из исходного массива. Он принимает два аргумента: начальный индекс и конечный индекс (не включая сам элемент с указанным конечным индексом). slice() возвращает новый массив, содержащий выбранные элементы, исходный массив остается неизменным.

Пример использования slice():

const fruits = ["яблоко", "груша", "банан", "апельсин"];

const selectedFruits = fruits.slice(1, 3);
// Результат: ['груша', 'банан']

Метод splice(), напротив, изменяет исходный массив, позволяя удалять, заменять или добавлять элементы. Он принимает несколько аргументов, включая индекс начала изменений, количество элементов для удаления, а также элементы, которые нужно добавить в массив. splice() возвращает массив удаленных элементов или пустой массив (если ничего не было удалено).

Пример использования splice():

const fruits = ["яблоко", "груша", "банан", "апельсин"];

fruits.splice(1, 2);
// Результат: ['яблоко', 'апельсин']

fruits.splice(1, 0, "манго", "киви");
// Результат: ['яблоко', 'манго', 'киви', 'апельсин']

Таким образом, основное отличие между slice() и splice() заключается в том, что slice() создает новый массив, содержащий выбранные элементы, не изменяя исходный массив, а splice() изменяет исходный массив путем удаления, замены или добавления элементов. ⬆ Наверх

Как сравнить Object и Map

Объекты (Objects) и карты (Maps) являются структурами данных в JavaScript и используются для хранения пар ключ-значение. Однако у них есть некоторые различия в функциональности и использовании.

Объекты в JavaScript являются коллекциями свойств, где каждое свойство имеет имя (ключ) и соответствующее значение. Ключи в объектах являются строками или символами. Объекты поддерживают доступ к значениям по ключу, добавление и удаление свойств, итерацию по свойствам и прочие операции. Однако у объектов также есть прототипы и методы, которые позволяют наследовать и расширять свойства и функциональность объектов.

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

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

Разница между == и === операторами

Оператор "==" используется для сравнения значений двух операндов и возвращает true, если значения равны. Однако, при использовании оператора "==" не происходит проверка на тип данных операндов.

Оператор "===" (тройное равенство) используется для строгого сравнения значений и типов данных двух операндов. Он возвращает true, только если значения и типы данных операндов полностью совпадают.

Например:

1 == "1" возвращает true, так как значения равны, несмотря на разные типы данных (число и строка).

1 === "1" возвращает false, так как значения отличаются и типы данных тоже отличны (число и строка). ⬆ Наверх

Лямбда функции и стрелочные функции

Лямбда-функции или стрелочные функции в JavaScript представляют собой сокращенный синтаксис для создания функций. Они были добавлены в стандарт ECMAScript 6 (ES6) и позволяют определить функции более компактно и кратко.

Синтаксис лямбда-функции выглядит следующим образом:

(parameter1, parameter2, ..., parameterN) => { // код функции }

Этот синтаксис позволяет передавать параметры функции в скобках и описывать тело функции после стрелки (=>). Если тело функции состоит из единственного выражения, то оно может быть написано без фигурных скобок. В этом случае значение этого выражения автоматически станет возвращаемым значением функции.

Примеры использования лямбда-функций:

// Обычная функция function multiply(a, b) { return a * b; }

// Лямбда-функция const multiply = (a, b) => a * b;

// Вызов функции console.log(multiply(2, 3)); // Выведет 6

Лямбда-функции очень удобны в тех случаях, когда требуется использовать функции как аргументы в других функциях (например, методы массивов, такие как map, filter, reduce и т.д.), либо для определения кратких, однострочных функций. ⬆ Наверх

Что такое функция первого класса в JavaScript?

Функция первого класса в JavaScript - это функция, которая может быть присвоена переменной, передана как аргумент в другую функцию и возвращена из функции в качестве результата. В JavaScript функции являются объектами и могут быть использованы также, как и другие типы данных, такие как строки или числа. Это означает, что функции могут быть сохранены в переменных, использованы в качестве аргументов других функций и возвращены из функций. Функции первого класса играют важную роль в функциональном программировании и позволяют использовать функции в качестве модулей, создавать замыкания и применять другие функциональные парадигмы программирования. ⬆ Наверх

Функции первого порядка

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

Вот пример первоклассной функции в JavaScript:

function sayHello(name) {
  console.log("Привет, " + name + "!");
}

var greeting = sayHello; // присвоение функции переменной
greeting("Максим"); // вызов функции через переменную

В данном примере функция sayHello присваивается переменной greeting и далее вызывается через эту переменную. Это один из примеров использования первоклассных функций в JavaScript. ⬆ Наверх

Что такое функция высшего порядка в JavaScript?

Функция высшего порядка (higher order function) в JavaScript - это функция, которая принимает другую функцию в качестве аргумента или возвращает функцию в качестве результата. Это особое свойство языка, которое позволяет работать с функциями как с данными и использовать их в различных сценариях.

Пример функции высшего порядка в JavaScript:

function multiplyBy(factor) {
  return function (number) {
    return number * factor;
  };
}

var multiplyByTwo = multiplyBy(2);
var multiplyByThree = multiplyBy(3);

console.log(multiplyByTwo(4)); // Вывод: 8
console.log(multiplyByThree(4)); // Вывод: 12

В этом примере функция multiplyBy принимает фактор и возвращает анонимную функцию, которая умножает число на данный фактор. Затем функции multiplyByTwo и multiplyByThree используются для умножения чисел на 2 и 3 соответственно.

Функции высшего порядка являются мощным инструментом в JavaScript и могут быть использованы для создания более гибкого и абстрактного кода. ⬆ Наверх

Унарная функция

Унарная функция (unary function) в JavaScript - это функция, которая принимает только один аргумент. Она обрабатывает этот аргумент и возвращает результат. Вот пример унарной функции на русском языке:

// Унарная функция, преобразующая число в его квадрат
function квадрат(число) {
  return число * число;
}

// Вызов унарной функции
let число = 5;
let квадратЧисла = квадрат(число);
console.log(квадратЧисла); // Выведет 25

⬆ Наверх

Что такое каррирование в JavaScript?

Каррирование (currying) - это техника функционального программирования, которая позволяет превратить функцию с несколькими аргументами в последовательность функций, каждая из которых принимает только один аргумент.

Вот пример каррированной функции на русском языке, которая складывает два числа:

// Каррированная функция, складывающая два числа
function сложить(a) {
  return function (b) {
    return a + b;
  };
}

// Вызов каррированной функции
let результат = сложить(2)(3);
console.log(результат); // Выведет 5

В этом примере сложить(2) возвращает функцию, которая принимает один аргумент b и возвращает сумму a + b. Затем сложить(2)(3) принимает второй аргумент 3 и возвращает результат сложения 2 + 3. ⬆ Наверх

Что такое чистая функция в JavaScript?

Чистая функция (pure function) - это функция, которая всегда возвращает одинаковый результат при одинаковых входных данных и не имеет побочных эффектов. Она не изменяет состояние программы или какие-либо внешние переменные.

Вот пример чистой функции на русском языке, которая складывает два числа:

// Чистая функция, складывающая два числа
function сложить(a, b) {
  return a + b;
}

// Вызов чистой функции
let результат = сложить(2, 3);
console.log(результат); // Выведет 5

В этом примере функция сложить всегда возвращает одинаковый результат для одних и тех же входных данных a и b, и она не влияет на состояние программы или внешние переменные. ⬆ Наверх

Какова цель ключевого слова "let" в JavaScript?

В JavaScript ключевое слово "let" используется для объявления блочной переменной, которая имеет область видимости ограниченную блоком кода, в котором она объявлена. Это отличается от ключевого слова "var", которое имеет функциональную область видимости.

Вот пример использования ключевого слова "let" на русском языке:

function примерФункции() {
  if (условие) {
    let переменная = "Значение переменной";
    console.log(переменная); // Выведет "Значение переменной"
  }

  console.log(переменная); // Вызовет ошибку ReferenceError: переменная is not defined
}

примерФункции();

В этом примере переменная "переменная" объявлена с помощью ключевого слова "let" внутри блока кода условия. Она доступна только внутри этого блока, и обращение к ней за пределами блока вызовет ошибку. ⬆ Наверх

В чем разница между let и var в JavaScript?

В JavaScript существуют два ключевых слова для объявления переменных: let и var. Вот основные различия между ними:

  1. Область видимости (scope):

    • Переменные, объявленные с помощью var, имеют функциональную область видимости. Это означает, что они доступны внутри функции, в которой они объявлены, независимо от блока кода.
    • Переменные, объявленные с помощью let, имеют блочную область видимости. Они доступны только в пределах блока кода, в котором они объявлены.
  2. Поднятие (hoisting):

    • Переменные, объявленные с помощью var, поднимаются (hoisting) вверх области видимости. Это означает, что их можно использовать до того, как они были объявлены в коде.
    • Переменные, объявленные с помощью let, не поднимаются. Они существуют только после того, как они были объявлены в коде.
  3. Повторное объявление:

    • Переменные, объявленные с помощью var, могут быть повторно объявлены в той же области видимости без вызова ошибки. Новое значение будет присвоено переменной.
    • Переменные, объявленные с помощью let, не могут быть повторно объявлены в той же области видимости. Попытка повторного объявления вызовет ошибку.

Вот пример, демонстрирующий разницу между let и var на русском языке:

function примерФункции() {
  if (true) {
    var переменнаяVar = "Значение var";
    let переменнаяLet = "Значение let";
  }

  console.log(переменнаяVar); // Выведет "Значение var"
  console.log(переменнаяLet); // Вызовет ошибку ReferenceError: переменнаяLet is not defined
}

примерФункции();

В этом примере переменная переменнаяVar, объявленная с помощью var, доступна за пределами блока кода условия. Однако переменная переменнаяLet, объявленная с помощью let, не доступна за пределами блока и вызовет ошибку. ⬆ Наверх

Как переопределить переменные в блоке switch без ошибки в JavaScript?

В JavaScript, переменные внутри блока switch могут быть переопределены без ошибки, так как блок switch создает свою собственную область видимости для каждого случая (case). Это позволяет использовать одно и то же имя переменной в разных случаях без конфликтов.

Пример:

let option = 2;
switch (option) {
  case 1:
    let message = "Первый вариант";
    console.log(message);
    break;
  case 2:
    let message = "Второй вариант"; // Нет ошибки, так как это отдельная область видимости
    console.log(message);
    break;
  default:
    let message = "Другой вариант";
    console.log(message);
}

В этом примере каждый блок case имеет свою собственную область видимости для переменной message, поэтому нет ошибок при переопределении переменной внутри блока switch. ⬆ Наверх

Что такое "Temporal Dead Zone" в JavaScript?

"Temporal Dead Zone" (временная мертвая зона) в JavaScript - это период существования переменной, когда она уже была объявлена с использованием ключевых слов let или const, но еще не может быть использована до тех пор, пока не будет до нее достигнут код выполнения. В этот период попытка доступа к переменной приведет к ошибке.

Это связано с тем, что переменные, объявленные с использованием let и const, имеют блочную область видимости и не подвергаются "всплытию" (hoisting) в начало своего блока. Они существуют только после объявления и до того момента, как выполнение программы достигнет строки, на которой они были объявлены.

Пример:

console.log(name); // Будет ошибка временной мертвой зоны
let name = "Alice";

В этом примере будет ошибка "ReferenceError", потому что переменная name уже объявлена, но на момент вывода она все еще находится во временной мертвой зоне, и к ней нельзя обратиться до фактического объявления. ⬆ Наверх

Что такое IIFE (Immediately Invoked Function Expression) в JavaScript?

IIFE (Immediately Invoked Function Expression) в JavaScript - это паттерн, при котором функция определяется и немедленно вызывается (выполняется) в том же месте, где она была объявлена. Этот подход позволяет создать локальную область видимости для изолирования переменных и кода, исключая возможные конфликты имён с другими частями программы.

Пример:

(function () {
  var message = "Привет из IIFE!";
  console.log(message);
})(); // Функция вызывается сразу после объявления

// Нельзя обратиться к переменной message вне IIFE, так как она находится в её области видимости
console.log(message); // Это вызовет ошибку

Здесь анонимная функция определена внутри круглых скобок (function() {...}) и сразу же вызывается, заключив () в конце. Это создает свою область видимости, в которой можно безопасно определять переменные, не затрагивая глобальное пространство имён. ⬆ Наверх

Как декодировать или закодировать URL в JavaScript?

В JavaScript для декодирования (преобразования из закодированного вида в читаемый) или кодирования (преобразования из читаемого вида в закодированный) URL используются методы decodeURI(), encodeURI(), decodeURIComponent() и encodeURIComponent().

Декодирование:

  • decodeURI() используется для декодирования всего URL.
  • decodeURIComponent() применяется для декодирования компонентов URL, таких как параметры.

Пример декодирования:

let encodedURL =
  "https%3A%2F%2Fexample.com%2F%3Fq%3D%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80";
let decodedURL = decodeURIComponent(encodedURL);
console.log(decodedURL);

⬆ Наверх

Кодирование:

  • encodeURI() используется для кодирования всего URL.
  • encodeURIComponent() применяется для кодирования компонентов URL, чтобы делать их безопасными для передачи.

Пример кодирования:

let url = "https://example.com/?q=пример";
let encodedURL = encodeURI(url);
console.log(encodedURL);

При использовании encodeURIComponent():

let query = "пример запроса";
let encodedQuery = encodeURIComponent(query);
console.log(encodedQuery);

Важно понимать разницу между этими методами и выбирать правильный в зависимости от контекста.

Что такое мемоизация (memoization) в JavaScript?

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

Пример мемоизации:

function expensiveCalculation(n) {
  console.log("Вычисление для", n);
  return n * 2;
}

function memoizedCalculation() {
  let cache = {}; // Кеш для результатов

  return function (n) {
    if (n in cache) {
      console.log("Используется кеш для", n);
      return cache[n];
    } else {
      cache[n] = expensiveCalculation(n);
      return cache[n];
    }
  };
}

const memoized = memoizedCalculation();

console.log(memoized(5)); // Первый вызов, вычисление для 5
console.log(memoized(5)); // Используется кеш для 5
console.log(memoized(8)); // Первый вызов, вычисление для 8
console.log(memoized(8)); // Используется кеш для 8

В этом примере memoizedCalculation() возвращает функцию, которая использует кеш для хранения результатов expensiveCalculation(). При первом вызове функции с определенным аргументом результат вычисления сохраняется в кеше, а при последующих вызовах для того же аргумента результат берется из кеша, что сэкономит время и вычислительные ресурсы. ⬆ Наверх

Что такое хойстинг (hoisting) в JavaScript?

Хостинг (hoisting) в JavaScript - это поведение, при котором объявления переменных и функций перемещаются в начало своей области видимости во время компиляции (до выполнения кода). Это может привести к тому, что вы можете обращаться к переменным или функциям до их фактического объявления.

Пример хойстинга переменных:

console.log(message); // undefined, но не будет ошибки
var message = "Привет, хойстинг!";
console.log(message); // "Привет, хостинг!"

Первый вызов console.log() покажет undefined, потому что переменная message уже поднята (hoisted) в начало области видимости, но ей еще не присвоено значение. Второй вызов покажет фактическое значение переменной.

Пример хойстинга функций:

greet(); // "Привет, хойстинг функций!"

function greet() {
  console.log("Привет, хойстинг функций!");
}

В этом примере функция greet() также поднимается в начало области видимости, поэтому её можно вызвать до фактического объявления.

Хойстинг может быть запутанным и привести к неожиданным результатам, поэтому рекомендуется всегда объявлять переменные и функции перед их использованием. ⬆ Наверх

Что такое классы в ES6 (ECMAScript 2015)?

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

Пример класса в ES6:

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

  sayHello() {
    console.log(`Привет, меня зовут ${this.name} и мне ${this.age} лет.`);
  }
}

const person1 = new Person("Алиса", 25);
person1.sayHello(); // "Привет, меня зовут Алиса и мне 25 лет."

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

Классы также могут иметь методы get и set для работы с свойствами объекта, а также наследоваться с помощью ключевого слова extends. ⬆ Наверх

Пример использования наследования:

class Student extends Person {
  constructor(name, age, course) {
    super(name, age);
    this.course = course;
  }

  study() {
    console.log(`${this.name} изучает курс ${this.course}.`);
  }
}

const student1 = new Student("Боб", 21, "Информатика");
student1.sayHello(); // "Привет, меня зовут Боб и мне 21 год."
student1.study(); // "Боб изучает курс Информатика."

В этом примере Student наследует свойства и методы от класса Person и добавляет свои собственные. ⬆ Наверх

Что такое замыкания (closures) в JavaScript?

Замыкания (closures) в JavaScript - это феномен, при котором функция сохраняет доступ к переменным из внешней области видимости, даже после завершения выполнения этой функции. Это позволяет функции "запомнить" значения переменных, существующих в том контексте, в котором она была создана.

Пример замыкания:

function createCounter() {
  let count = 0;

  return function () {
    count++;
    return count;
  };
}

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

В этом примере createCounter() возвращает функцию, которая имеет доступ к переменной count, хотя createCounter() уже выполнена. Это происходит из-за замыкания: функция "запоминает" контекст, в котором она была создана, и сохраняет доступ к переменным этого контекста.

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

Пример использования замыкания в функции обратного вызова:

function doSomething(callback) {
  let result = 42;
  callback(result);
}

doSomething(function (data) {
  console.log("Получено:", data); // "Получено: 42"
});

Функция обратного вызова сохраняет доступ к переменной result благодаря замыканию. ⬆ Наверх

Что такое модули (modules) в JavaScript?

Модули (modules) в JavaScript - это механизм организации кода, который позволяет разбивать программу на небольшие независимые части, называемые модулями. Каждый модуль содержит свои функции, переменные, классы и другие сущности, и предоставляет интерфейс для работы с ними. Модули помогают управлять сложностью кода, обеспечивая изоляцию и переиспользуемость.

Пример модуля в ES6:

// Модуль в файле math.js
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

// Другой файл
import { add, subtract } from "./math.js";

console.log(add(5, 3)); // 8
console.log(subtract(10, 4)); // 6

В этом примере модуль math.js экспортирует функции add и subtract, которые могут быть импортированы и использованы в другом файле.

Модули также могут экспортировать и импортировать по умолчанию, а также содержать частные (недоступные извне) и публичные (доступные извне) члены.

Пример экспорта и импорта по умолчанию:

// Модуль в файле greetings.js
export default function greet(name) {
  return `Привет, ${name}!`;
}

// Другой файл
import greet from "./greetings.js";

console.log(greet("Алиса")); // "Привет, Алиса!"

В этом примере функция greet экспортируется по умолчанию и импортируется в другом файле без фигурных скобок. ⬆ Наверх

Зачем нужны модули?

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

Преимущества использования модулей:

  1. Изоляция: Модули создают свою собственную область видимости, что предотвращает конфликты имён и позволяет объявлять частные члены, недоступные извне модуля.

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

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

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

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

Пример использования модулей:

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

Что такое область видимости (scope) в JavaScript?

Область видимости (scope) в JavaScript определяет, где и какие переменные и функции будут видимы и доступны в определенной части кода. Область видимости контролирует, какие имена переменных можно использовать в данной части программы и какие не мешают друг другу. ⬆ Наверх

Пример области видимости:

function outer() {
  let outerVar = "Я виден только внутри outer()";

  function inner() {
    let innerVar = "Я виден только внутри inner()";
    console.log(innerVar); // "Я виден только внутри inner()"
    console.log(outerVar); // "Я виден только внутри outer()"
  }

  inner();

  // Нельзя обратиться к innerVar здесь
}

// Нельзя обратиться к outerVar здесь

В этом примере функция inner() имеет доступ как к переменной innerVar, так и к переменной outerVar, потому что она находится внутри области видимости функции outer(). Однако переменная innerVar недоступна за пределами функции inner(), и переменная outerVar недоступна за пределами функции outer().

Область видимости может быть глобальной или локальной. Глобальная область видимости означает, что переменная или функция доступны во всем коде, а локальная область видимости ограничивает доступ только внутри определенной функции или блока кода. ⬆ Наверх

Что такое сервисный работник (service worker) в JavaScript?

Сервисный работник (service worker) в JavaScript - это скрипт, который выполняется в фоновом режиме, независимо от веб-страницы, которая его зарегистрировала. Сервисные работники широко используются для реализации различных задач, таких как кэширование ресурсов, работа в офлайн-режиме, пуш-уведомления и другие.

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

Пример использования сервисного работника:

// Регистрация сервисного работника
if ("serviceWorker" in navigator) {
  navigator.serviceWorker
    .register("/service-worker.js")
    .then((registration) => {
      console.log("Сервисный работник зарегистрирован:", registration);
    })
    .catch((error) => {
      console.error("Ошибка при регистрации сервисного работника:", error);
    });
}

Создайте файл service-worker.js и добавьте в него логику работы сервисного работника:

// service-worker.js
self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open("my-cache").then((cache) => {
      return cache.addAll(["/", "/index.html", "/styles.css", "/script.js"]);
    })
  );
});

self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});

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

Как осуществлять изменение DOM с использованием сервисного работника?

Сервисные работники (service workers) не имеют прямого доступа к DOM (Document Object Model) из-за своей асинхронной природы и независимости от конкретных веб-страниц. Однако, вы можете использовать сервисные работники для перехвата сетевых запросов, кеширования ресурсов и динамической загрузки контента в DOM.

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

Предположим, у вас есть элемент с идентификатором dynamic-content, и вы хотите динамически загрузить контент в него с использованием сервисного работника.

// В файле service-worker.js
self.addEventListener("fetch", (event) => {
  if (event.request.url.endsWith("/dynamic-content")) {
    event.respondWith(
      fetch("https://api.example.com/data") // Пример запроса к серверу для получения данных
        .then((response) => response.text())
        .then(
          (data) =>
            new Response(data, { headers: { "Content-Type": "text/html" } })
        )
    );
  }
});

В этом примере, при запросе к URL, оканчивающемуся на /dynamic-content, сервисный работник перехватывает запрос, отправляет запрос на сервер для получения данных и затем создает и возвращает новый Response с этими данными.

<!-- В вашей веб-странице -->
<div id="dynamic-content"></div>

<script>
  // В этом примере JavaScript на вашей веб-странице
  if ("serviceWorker" in navigator) {
    navigator.serviceWorker
      .register("/service-worker.js")
      .then((registration) => {
        console.log("Сервисный работник зарегистрирован:", registration);
      })
      .catch((error) => {
        console.error("Ошибка при регистрации сервисного работника:", error);
      });
  }
</script>

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

Обратите внимание, что манипуляции DOM непосредственно из сервисного работника невозможны из-за их асинхронной природы и того, что они могут работать вне контекста конкретной страницы. ⬆ Наверх

Как переиспользовать информацию между перезапусками сервисного работника?

Для переиспользования информации между перезапусками сервисного работника можно использовать браузерное хранилище, такое как localStorage, IndexedDB или кэш сервисного работника.

Пример использования кэша сервисного работника для сохранения информации:

// В файле service-worker.js

self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open("my-cache").then((cache) => {
      return cache.addAll(["/static-resource"]); // Пример статического ресурса для кэширования
    })
  );
});

self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      if (response) {
        return response;
      }

      return fetch(event.request);
    })
  );
});

self.addEventListener("message", (event) => {
  if (event.data.action === "saveInfo") {
    caches.open("my-cache").then((cache) => {
      cache.put("saved-info", new Response(JSON.stringify(event.data.info)));
    });
  }
});
// На веб-странице

if ("serviceWorker" in navigator) {
  navigator.serviceWorker
    .register("/service-worker.js")
    .then((registration) => {
      console.log("Сервисный работник зарегистрирован:", registration);
    })
    .catch((error) => {
      console.error("Ошибка при регистрации сервисного работника:", error);
    });
}

navigator.serviceWorker.ready.then((registration) => {
  const savedInfo = { data: "Это сохраненная информация" };

  // Отправляем сообщение сервисному работнику для сохранения информации в кэше
  registration.active.postMessage({ action: "saveInfo", info: savedInfo });
});

В этом примере, при установке сервисного работника, статический ресурс ('/static-resource') кэшируется. При перезапуске сервисного работника, сохраненная информация (savedInfo) отправляется сервисному работнику через сообщение (postMessage), и он сохраняет эту информацию в кэше. Таким образом, информация переиспользуется между перезапусками. ⬆ Наверх

Что такое IndexedDB в JavaScript?

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

Пример использования IndexedDB:

// Открываем или создаем базу данных "my-database" с версией 1
var request = indexedDB.open("my-database", 1);

// Обработчик успешного открытия базы данных
request.onsuccess = function (event) {
  var db = event.target.result;

  // Создаем транзакцию для доступа к объектному хранилищу "my-store"
  var transaction = db.transaction(["my-store"], "readwrite");

  // Получаем объектное хранилище
  var store = transaction.objectStore("my-store");

  // Добавляем данные в хранилище
  store.add({ id: 1, name: "Алиса" });
};

// Обработчик создания или обновления базы данных
request.onupgradeneeded = function (event) {
  var db = event.target.result;

  // Создаем объектное хранилище "my-store" с индексом "name"
  var store = db.createObjectStore("my-store", { keyPath: "id" });
  store.createIndex("name", "name", { unique: false });
};

В этом примере создается база данных "my-database" с объектным хранилищем "my-store". Данные добавляются в хранилище с использованием транзакции. Также создается индекс "name" для поиска по имени.

IndexedDB предоставляет более сложные функции по сравнению с простыми хранилищами, такими как localStorage, и позволяет производить запросы, индексировать данные и выполнять сложные операции с базой данных на стороне клиента. ⬆ Наверх

Что такое веб-хранилище (web storage) в JavaScript?

Веб-хранилище (web storage) - это механизм для хранения данных на стороне клиента в браузере. Он предоставляет два объекта, localStorage и sessionStorage, которые позволяют сохранять данные в формате ключ-значение. Данные хранятся в браузере и доступны даже после перезагрузки страницы.

Пример использования localStorage:

// Сохраняем данные в localStorage
localStorage.setItem("username", "Alice");
localStorage.setItem("age", "25");

// Получаем данные из localStorage
const username = localStorage.getItem("username");
const age = localStorage.getItem("age");

console.log(username); // "Alice"
console.log(age); // "25"

// Удаляем данные из localStorage
localStorage.removeItem("username");
localStorage.clear(); // Очищаем все данные

Пример использования sessionStorage:

// Сохраняем данные в sessionStorage
sessionStorage.setItem("city", "New York");

// Получаем данные из sessionStorage
const city = sessionStorage.getItem("city");

console.log(city); // "New York"

// Удаляем данные из sessionStorage
sessionStorage.removeItem("city");

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

Веб-хранилище обычно используется для сохранения небольших объемов данных, таких как настройки пользователя, состояния приложения или кэширования данных. ⬆ Наверх

Что такое сообщение postMessage в JavaScript?

Сообщение postMessage в JavaScript - это механизм коммуникации между окнами/вкладками браузера, работающими на одном и том же домене. Он позволяет отправлять данные и сообщения от одного окна к другому в безопасной среде.

Пример использования postMessage:

Предположим, у вас есть две веб-страницы, parent.html и child.html, открытые в разных вкладках браузера.

<!-- parent.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>Родитель</title>
  </head>
  <body>
    <iframe src="child.html" id="childFrame"></iframe>

    <script>
      const childFrame = document.getElementById("childFrame").contentWindow;

      function sendMessage() {
        childFrame.postMessage("Привет, дочка!", "http://localhost:8000"); // Замените на свой домен
      }
    </script>
  </body>
</html>
<!-- child.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>Дочь</title>
  </head>
  <body>
    <script>
      window.addEventListener("message", (event) => {
        if (event.origin === "http://localhost:8000") {
          // Замените на свой домен
          console.log("Получено сообщение от родителя:", event.data);
        }
      });
    </script>
  </body>
</html>

В этом примере, при вызове функции sendMessage на странице parent.html, сообщение "Привет, дочка!" будет отправлено во фрейм child.html. Фрейм прослушивает событие message и выводит полученное сообщение в консоль.

Важно обратить внимание, что postMessage безопасен, только если вы явно проверяете источник (поле event.origin) при обработке сообщений, чтобы избежать возможных атак через сообщения. ⬆ Наверх

Что такое cookie (куки)?

Cookie (куки) - это небольшие фрагменты данных, которые веб-сайты отправляют и хранят на компьютере пользователя через веб-браузер. Куки используются для хранения информации о состоянии, настройках пользователя, а также для отслеживания и аутентификации.

Пример использования cookie:

Предположим, у вас есть веб-сайт, который сохраняет язык, выбранный пользователем.

// Записываем значение в cookie
document.cookie =
  "language=english; expires=Fri, 31 Dec 2023 23:59:59 GMT; path=/";

// Чтение значения из cookie
const cookies = document.cookie;
console.log(cookies); // "language=english; ..."

В этом примере значение "language=english" записывается в cookie. Это значение будет доступно на всех страницах сайта, которые находятся в той же директории (путь /), до указанной даты и времени (здесь до конца 2023 года).

Cookie могут иметь различные параметры, такие как срок годности (expires), путь (path), домен (domain), безопасность (secure), и т. д.

Куки могут быть использованы для сохранения сессионной информации, аутентификации пользователя, отслеживания действий пользователя на сайте и других задач. Однако, стоит помнить, что куки имеют ограниченный объем хранения (обычно до 4 килобайт) и могут вызывать проблемы с конфиденциальностью, если не используются правильно.

Зачем нужны куки (Cookies)?

Куки (Cookies) в веб-разработке используются для хранения информации о состоянии и настройках пользователя на веб-сайте. Они имеют ряд важных применений, включая сессионное управление, аутентификацию, сохранение предпочтений пользователя и отслеживание активности. ⬆ Наверх

Примеры применения куки:

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

  2. Аутентификация: Куки позволяют сохранить данные аутентификации пользователя. Например, при успешной аутентификации, сервер может установить куки с токеном, который подтверждает аутентичность пользователя.

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

  4. Отслеживание активности: Куки могут использоваться для анализа поведения пользователей на сайте, что помогает в понимании, какие страницы чаще посещаются и какие действия выполняются.

  5. Подготовка корзины покупок: В интернет-магазинах куки могут использоваться для отслеживания добавленных товаров в корзину, даже если пользователь переходит между страницами.

Пример использования куки:

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

// При выборе пользователем темы "dark"
document.cookie = "theme=dark; expires=Fri, 31 Dec 2023 23:59:59 GMT; path=/";

// При загрузке страницы
const cookies = document.cookie;
const themeCookie = cookies
  .split("; ")
  .find((cookie) => cookie.startsWith("theme="));

if (themeCookie) {
  const theme = themeCookie.split("=")[1];
  applyTheme(theme);
}

В этом примере, при выборе пользователем темы "dark", куки сохраняется, и при следующем посещении сайта применяется выбранная тема. ⬆ Наверх

Какие параметры можно задать в куки (Cookie)?

Куки (Cookies) имеют различные параметры, которые можно установить для контроля их поведения. Ниже приведены некоторые из наиболее часто используемых параметров.

Примеры параметров в куки:

  1. expires (срок действия): Определяет, когда куки истекает и становится недействительным. Значение может быть указано в виде строки с датой и временем в формате GMT.

    document.cookie =
      "username=John; expires=Fri, 31 Dec 2023 23:59:59 GMT; path=/";
  2. path (путь): Определяет путь, для которого куки действительно. Куки будут доступны только для страниц, которые находятся в этом пути.

    document.cookie =
      "username=John; expires=Fri, 31 Dec 2023 23:59:59 GMT; path=/admin";
  3. domain (домен): Определяет домен, для которого куки действительно. По умолчанию, куки доступны только для текущего домена.

    document.cookie =
      "username=John; expires=Fri, 31 Dec 2023 23:59:59 GMT; domain=example.com";
  4. secure (безопасность): Если этот параметр установлен, куки будет передаваться только через защищенное (HTTPS) соединение.

    document.cookie =
      "username=John; expires=Fri, 31 Dec 2023 23:59:59 GMT; secure";
  5. samesite: Определяет, как куки будут отправляться на сервер при запросах с других сайтов. Значения могут быть "strict", "lax" или "none".

    document.cookie =
      "username=John; expires=Fri, 31 Dec 2023 23:59:59 GMT; samesite=lax";

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

Как удалить куки (Cookie)?

Для удаления куки (Cookie) необходимо установить его срок действия в прошедшее время или использовать опцию "Max-Age" с отрицательным значением. Это приведет к тому, что браузер считает куки недействительным и удалит его.

Пример удаления куки:

// Удаление куки по имени
function deleteCookie(cookieName) {
  document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
}

// Пример вызова функции для удаления куки "username"
deleteCookie("username");

В этом примере, функция deleteCookie устанавливает срок действия куки "username" в прошедшее время, что приводит к его удалению. Удаление происходит путем установки даты и времени истечения куки (expires) на дату в прошлом. Важно указать путь (path), который соответствует пути, для которого куки было установлено.

Пожалуйста, обратите внимание, что куки можно удалить только на том же домене и пути, где они были установлены. ⬆ Наверх

В чем разница между куками, локальным хранилищем и сессионным хранилищем?

Куки (cookie), локальное хранилище (localStorage) и сессионное хранилище (sessionStorage) - это три разных механизма хранения данных на стороне клиента в браузере, и у них есть существенные различия.

Куки (Cookie):

  • Куки являются небольшими фрагментами данных, которые хранятся на стороне клиента.
  • Используются для хранения небольших объемов данных и обычно имеют ограничение в размере до 4 килобайт.
  • Отправляются в заголовке HTTP-запроса при каждом запросе к серверу, что может замедлить загрузку страницы.
  • Имеют параметры срока действия, пути, домена, безопасности и другие.
  • Могут быть доступны как на текущей странице, так и на других страницах или доменах в зависимости от настроек параметров.

Локальное хранилище (localStorage):

  • Предоставляет механизм хранения ключ-значение без срока действия (данные остаются даже после перезагрузки браузера).
  • Позволяет хранить более объемные данные (обычно до 5-10 мегабайт).
  • Данные в локальном хранилище доступны на всех страницах с одинаковым протоколом (http/https) и доменом.
  • Доступ к данным возможен через JavaScript из любой вкладки или окна с одним и тем же доменом.

Сессионное хранилище (sessionStorage):

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

Пример сравнения:

Предположим, у вас есть задача сохранить предпочтения пользователя на сайте.

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

В чем основное различие между локальным хранилищем и сессионным хранилищем?

Основное различие между локальным хранилищем (localStorage) и сессионным хранилищем (sessionStorage) заключается в продолжительности хранения данных и доступности данных между вкладками браузера.

Локальное хранилище (localStorage):

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

Сессионное хранилище (sessionStorage):

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

Пример сравнения:

Допустим, вы разрабатываете веб-приложение для заметок.

  • Используйте локальное хранилище (localStorage), если хотите, чтобы заметки оставались доступными даже после закрытия браузера и перезагрузки страницы. Пользователь сможет получить доступ к своим заметкам на разных устройствах и в разных вкладках.
  • Используйте сессионное хранилище (sessionStorage), если хотите, чтобы заметки сохранялись только в рамках одной сессии браузера. Например, пользователь может создавать временные заметки, которые автоматически удаляются после закрытия вкладки.

Выбор между localStorage и sessionStorage зависит от требований к продолжительности хранения данных и ожидаемого поведения на разных устройствах и вкладках. ⬆ Наверх

Как получить доступ к веб-хранилищу (web storage)?

Для доступа к веб-хранилищу (web storage) в JavaScript используются объекты localStorage и sessionStorage. Эти объекты позволяют сохранять и извлекать данные на стороне клиента в браузере.

Пример доступа к веб-хранилищу:

Доступ к локальному хранилищу (localStorage):

// Сохраняем данные в localStorage
localStorage.setItem("username", "Alice");
localStorage.setItem("age", "25");

// Получаем данные из localStorage
const username = localStorage.getItem("username");
const age = localStorage.getItem("age");

console.log(username); // "Alice"
console.log(age); // "25"

// Удаляем данные из localStorage
localStorage.removeItem("username");

Доступ к сессионному хранилищу (sessionStorage):

// Сохраняем данные в sessionStorage
sessionStorage.setItem("city", "New York");

// Получаем данные из sessionStorage
const city = sessionStorage.getItem("city");

console.log(city); // "New York"

// Удаляем данные из sessionStorage
sessionStorage.removeItem("city");

Для доступа к данным в веб-хранилище используется метод getItem для извлечения данных по ключу, метод setItem для сохранения данных, и метод removeItem для удаления данных. Данные сохраняются в виде пары ключ-значение.

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

Какие методы доступны в сессионном хранилище (sessionStorage)?

В сессионном хранилище (sessionStorage) доступны следующие методы для работы с данными:

  1. setItem(key, value): Сохраняет пару ключ-значение в сессионном хранилище.

    sessionStorage.setItem("username", "Alice");
  2. getItem(key): Извлекает значение по ключу из сессионного хранилища.

    const username = sessionStorage.getItem("username");
    console.log(username); // "Alice"
  3. removeItem(key): Удаляет данные по указанному ключу из сессионного хранилища.

    sessionStorage.removeItem("username");
  4. clear(): Удаляет все данные из сессионного хранилища.

    sessionStorage.clear();

Эти методы позволяют управлять данными в сессионном хранилище, добавлять новые данные, извлекать существующие значения, удалять данные и очищать всё хранилище. Обратите внимание, что данные, сохраненные в сессионном хранилище, будут доступны только в рамках текущей сессии браузера и будут удалены после закрытия вкладки или браузера. ⬆ Наверх

Что такое событие хранилища (storage event) и его обработчик событий в JavaScript?

Событие хранилища (storage event) - это событие, которое возникает, когда данные в веб-хранилище (localStorage или sessionStorage) изменяются в другой вкладке или окне браузера. С помощью этого события вы можете отслеживать изменения данных между разными сессиями в рамках одного домена.

Пример использования события хранилища:

В первой вкладке:

// Сохраняем данные в localStorage
localStorage.setItem("username", "Alice");

Во второй вкладке (или другом окне):

// Слушаем событие хранилища
window.addEventListener("storage", (event) => {
  if (event.key === "username") {
    console.log(`Изменено имя пользователя на: ${event.newValue}`);
  }
});

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

Обработчик события хранилища (storage event handler):

Обработчик события хранилища - это функция, которая будет выполнена при возникновении события хранилища. Он принимает объект события в качестве параметра, который содержит информацию о событии, включая измененный ключ (event.key), старое значение (event.oldValue), новое значение (event.newValue), домен и другие.

// Обработчик события хранилища
function handleStorageChange(event) {
  console.log(`Ключ: ${event.key}`);
  console.log(`Старое значение: ${event.oldValue}`);
  console.log(`Новое значение: ${event.newValue}`);
}

// Добавляем обработчик события хранилища
window.addEventListener("storage", handleStorageChange);

Событие хранилища полезно, когда вам нужно отслеживать изменения данных между разными вкладками или окнами вашего веб-приложения. ⬆ Наверх

Зачем нужно веб-хранилище (web storage)?

Веб-хранилище (web storage) - это механизм, который позволяет веб-приложениям сохранять данные на стороне клиента, в браузере пользователя. Оно имеет несколько важных применений для улучшения пользовательского опыта и работы веб-приложений.

Примеры применения веб-хранилища:

  1. Локальное сохранение данных: Веб-хранилище позволяет приложениям сохранять данные, которые будут доступны даже после перезагрузки страницы или закрытия браузера. Это полезно для хранения настроек пользователя, последних действий или состояния приложения.

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

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

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

  5. Отслеживание состояния приложения: Веб-хранилище позволяет сохранять текущее состояние приложения, например, активную вкладку, выбранный раздел и другие параметры. ⬆ Наверх

Пример использования веб-хранилища:

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

// Сохраняем заметку в локальное хранилище
localStorage.setItem("note1", "Список покупок: молоко, яйца, хлеб");

// Извлекаем заметку из локального хранилища
const savedNote = localStorage.getItem("note1");
console.log(savedNote); // "Список покупок: молоко, яйца, хлеб"

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

В целом, веб-хранилище предоставляет удобный способ хранения данных на стороне клиента, улучшая пользовательский опыт и функциональность веб-приложений. ⬆ Наверх

Как проверить поддержку веб-хранилища браузером?

Для проверки поддержки веб-хранилища (web storage) в браузере можно использовать проверку наличия соответствующих объектов localStorage и sessionStorage.

Пример проверки поддержки веб-хранилища:

if (typeof Storage !== "undefined") {
  // Веб-хранилище поддерживается
  console.log("Веб-хранилище поддерживается в этом браузере.");
} else {
  // Веб-хранилище не поддерживается
  console.log("Веб-хранилище не поддерживается в этом браузере.");
}

Этот код проверяет, существует ли объект Storage (который используется для работы с веб-хранилищем) в глобальном контексте. Если поддержка есть, вы увидите сообщение о поддержке в консоли.

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

Как проверить поддержку веб-воркеров (web workers) в браузере?

Для проверки поддержки веб-воркеров (web workers) в браузере можно использовать проверку наличия объекта Worker.

Пример проверки поддержки веб-воркеров:

if (typeof Worker !== "undefined") {
  // Веб-воркеры поддерживаются
  console.log("Веб-воркеры поддерживаются в этом браузере.");
} else {
  // Веб-воркеры не поддерживаются
  console.log("Веб-воркеры не поддерживаются в этом браузере.");
}

Этот код проверяет, существует ли объект Worker (который используется для создания веб-воркеров) в глобальном контексте. Если поддержка есть, вы увидите сообщение о поддержке в консоли.

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

Приведите пример использования веб-воркера (web worker) в JavaScript

Веб-воркеры (web workers) - это фоновые потоки выполнения JavaScript, которые позволяют выполнять вычисления и задачи в отдельном потоке, не блокируя основной поток браузера. Они полезны для выполнения тяжелых вычислений и долгих операций, не влияя на отзывчивость пользовательского интерфейса.

Пример веб-воркера:

// Создаем файл worker.js

// worker.js
self.onmessage = function (event) {
  // Получаем данные из основного потока
  const data = event.data;

  // Выполняем вычисления (например, факториал)
  const result = calculateFactorial(data);

  // Отправляем результат обратно в основной поток
  postMessage(result);
};

function calculateFactorial(n) {
  if (n <= 1) {
    return 1;
  } else {
    return n * calculateFactorial(n - 1);
  }
}

В основном скрипте:

// Создаем веб-воркера
const worker = new Worker("worker.js");

// Отправляем данные на обработку в веб-воркер
worker.postMessage(5);

// Получаем результат из веб-воркера
worker.onmessage = function (event) {
  const result = event.data;
  console.log(`Факториал: ${result}`);
};

// При необходимости завершаем работу веб-воркера
worker.terminate();

В этом примере мы создаем веб-воркера, который вычисляет факториал числа. Мы отправляем данные на обработку в веб-воркер, а затем получаем результат через событие onmessage. Обратите внимание, что веб-воркеры могут выполняться в отдельном файле (как worker.js) и не имеют доступа к DOM.

Веб-воркеры удобно использовать для выполнения вычислительно интенсивных операций, которые не должны блокировать основной поток браузера. ⬆ Наверх

Какие ограничения существуют у веб-воркеров по работе с DOM?

Веб-воркеры (web workers) предоставляют возможность выполнять код в отдельных фоновых потоках, что позволяет избежать блокировки основного потока браузера. Однако у веб-воркеров есть некоторые ограничения в отношении доступа и взаимодействия с DOM.

Ограничения веб-воркеров по работе с DOM:

  1. Отсутствие доступа к DOM: Веб-воркеры не имеют прямого доступа к DOM. Это означает, что они не могут взаимодействовать с элементами DOM, менять HTML-структуру или стили страницы.

  2. Отсутствие доступа к глобальным переменным: Веб-воркеры не имеют доступа к глобальным переменным и функциям основного потока.

  3. Синхронизация и обмен данными: Для обмена данными между веб-воркерами и основным потоком используются асинхронные механизмы, такие как события (postMessage). Это может привести к сложностям в синхронизации и обработке данных.

Пример ограничений:

// Веб-воркер
self.onmessage = function (event) {
  // Нельзя изменить DOM или получить доступ к window
  // Нельзя использовать глобальные переменные из основного потока
  // Это не сработает: document.getElementById("myElement").textContent = "Hello";

  // Можно только отправить сообщение обратно в основной поток
  postMessage("Hello from the worker!");
};

Поскольку веб-воркеры выполняются в отдельных потоках, они не могут напрямую влиять на пользовательский интерфейс и DOM. Однако они идеально подходят для вычислительно интенсивных операций и обработки данных, не связанных с изменением DOM. ⬆ Наверх

Что такое промис (Promise)?

Промис (Promise) - это объект в JavaScript, представляющий результат успешного завершения или ошибки асинхронной операции. Он позволяет более удобно и читаемо обрабатывать асинхронный код, делая его более структурированным и предсказуемым.

Пример промиса:

// Пример асинхронной функции, которая возвращает промис
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = "Данные получены";
      resolve(data); // Успешное завершение
      // Если произошла ошибка: reject(new Error("Ошибка получения данных"));
    }, 2000);
  });
}

// Использование промиса
fetchData()
  .then((result) => {
    console.log(result); // "Данные получены"
  })
  .catch((error) => {
    console.error(error);
  });

В этом примере функция fetchData возвращает промис, который успешно завершается через 2 секунды. Мы используем метод .then для обработки успешного выполнения промиса и метод .catch для обработки ошибки.

Промисы позволяют создавать цепочки асинхронных операций, улучшая читаемость и управляемость кода. Они также предоставляют механизмы для обработки нескольких асинхронных операций сразу, например, с помощью Promise.all или Promise.race.

Зачем нужен промис (Promise)?

Промис (Promise) в JavaScript используется для более удобной и структурированной обработки асинхронного кода. Асинхронные операции, такие как запросы к серверу, чтение/запись в файлы или таймеры, могут занять некоторое время и могут быть завершены в будущем. Промисы помогают справиться с такими ситуациями и улучшить читаемость кода.

Пример использования промиса:

// Пример асинхронной функции с промисом
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = "Данные получены";
      resolve(data); // Успешное завершение
    }, 2000);
  });
}

// Использование промиса
fetchData()
  .then((result) => {
    console.log(result); // "Данные получены"
  })
  .catch((error) => {
    console.error(error);
  });

Почему промисы полезны:

  1. Обработка асинхронности: Промисы предоставляют четкий способ обрабатывать асинхронные операции, позволяя избежать "callback hell" - глубоко вложенных коллбэков.

  2. Читаемость кода: Код с использованием промисов более структурирован и легко читается, так как асинхронные операции описываются последовательно с помощью методов .then и .catch.

  3. Управление ошибками: Промисы предоставляют механизм для обработки ошибок с помощью метода .catch, что делает код более надежным и предсказуемым.

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

  5. Параллельные операции: Промисы также позволяют выполнять несколько асинхронных операций параллельно и ждать, пока все они завершатся.

Промисы стали стандартной практикой для обработки асинхронного кода и являются фундаментальным элементом при работе с современными веб-приложениями. ⬆ Наверх

Каковы три состояния промиса (Promise)?

Промис (Promise) в JavaScript имеет три основных состояния, которые описывают текущее состояние выполнения асинхронной операции.

  1. Ожидание (Pending): Начальное состояние, когда промис создан, но операция, связанная с ним, еще не завершена. Промис находится в ожидании результата.

  2. Выполнено (Fulfilled): Состояние, в котором асинхронная операция успешно завершена. Промис переходит в это состояние, когда вызывается функция resolve(), передавая ей результат операции.

  3. Отклонено (Rejected): Состояние, в котором асинхронная операция завершается с ошибкой. Промис переходит в это состояние, когда вызывается функция reject(), передавая ей информацию об ошибке.

Пример использования состояний промиса:

const promise = new Promise((resolve, reject) => {
  // Имитация асинхронной операции
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve("Операция успешно выполнена");
    } else {
      reject(new Error("Произошла ошибка"));
    }
  }, 2000);
});

promise
  .then((result) => {
    console.log(result); // "Операция успешно выполнена"
  })
  .catch((error) => {
    console.error(error.message); // "Произошла ошибка"
  });

В этом примере промис переходит в состояние "Выполнено" (Fulfilled) при успешном завершении асинхронной операции, и в состояние "Отклонено" (Rejected) при ошибке. С помощью методов .then и .catch мы обрабатываем соответствующие состояния промиса. ⬆ Наверх

Что такое функция обратного вызова (callback function)?

Функция обратного вызова (callback function) в JavaScript - это функция, которая передается в качестве аргумента другой функции и вызывается после завершения определенной операции или события. Она позволяет создавать асинхронный код и контролировать его поток выполнения.

Пример функции обратного вызова:

// Пример асинхронной функции с функцией обратного вызова
function fetchData(callback) {
  setTimeout(() => {
    const data = "Данные получены";
    callback(data);
  }, 2000);
}

// Использование функции обратного вызова
fetchData((result) => {
  console.log(result); // "Данные получены"
});

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

Функции обратного вызова используются часто для обработки асинхронных операций, обработки событий, запросов к серверу и других сценариев, где результат операции может быть неизвестен на момент вызова функции. Однако, использование большого количества вложенных коллбэков может привести к "callback hell" - сложному для читаемости и поддержки коду. ⬆ Наверх

Зачем нужны функции обратного вызова (callback)?

Функции обратного вызова (callback) в JavaScript используются для управления асинхронным кодом и выполнения операций, которые зависят от завершения других операций. Они позволяют создавать гибкое и масштабируемое асинхронное программирование.

Пример использования функций обратного вызова:

// Пример асинхронной функции с функцией обратного вызова
function fetchData(callback) {
  setTimeout(() => {
    const data = "Данные получены";
    callback(data);
  }, 2000);
}

// Использование функции обратного вызова
fetchData((result) => {
  console.log(result); // "Данные получены"
});

Почему функции обратного вызова полезны:

  1. Асинхронность: Функции обратного вызова позволяют обрабатывать асинхронные операции, такие как запросы к серверу, чтение файлов или таймеры, без блокировки основного потока выполнения.

  2. Управление потоком: Функции обратного вызова позволяют контролировать порядок выполнения операций, например, вызывать вторую функцию только после завершения первой.

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

  4. Параметризация поведения: Функции обратного вызова позволяют параметризовать, какой код должен быть выполнен после завершения операции. Это делает код более гибким и переиспользуемым.

  5. Избегание блокировок: Они позволяют избежать блокировки пользовательского интерфейса, что делает приложение более отзывчивым.

Хотя функции обратного вызова очень полезны, при использовании большого количества вложенных коллбэков может возникнуть проблема "callback hell". Эту проблему можно решить с помощью промисов или асинхронных функций в более современных версиях JavaScript. ⬆ Наверх

Что такое "callback hell"?

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

Пример "callback hell":

asyncOperation1(function (result1) {
  asyncOperation2(result1, function (result2) {
    asyncOperation3(result2, function (result3) {
      // И так далее...
    });
  });
});

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

Почему это проблема:

  1. Читаемость: Код становится трудночитаемым, сложно понять поток выполнения и логику операций.

  2. Обработка ошибок: Обработка ошибок становится более сложной из-за множества точек неудачи.

  3. Поддержка и изменения: Такой код сложно поддерживать и изменять, особенно когда требуется добавление или изменение функциональности.

Как избежать "callback hell":

  1. Промисы: Использование промисов позволяет создавать более структурированный код с использованием методов .then и .catch, избегая глубокой вложенности.

  2. Асинхронные функции: В современных версиях JavaScript можно использовать ключевое слово async вместе с await для более линейного кода.

  3. Библиотеки: Множество библиотек, таких как async/await, Bluebird и другие, предоставляют инструменты для более удобной работы с асинхронным кодом.

Соблюдение лучших практик и использование современных подходов помогут избежать "callback hell" и сделать код более читаемым и управляемым. ⬆ Наверх

Что такое события, отправляемые с сервера (Server-Sent Events)?

События, отправляемые с сервера (Server-Sent Events или SSE), представляют собой механизм веб-браузера для установления однонаправленного потока данных от сервера к клиенту по протоколу HTTP. Этот механизм позволяет серверу отправлять информацию клиенту без необходимости, чтобы клиент делал повторные запросы.

Пример использования событий, отправляемых с сервера:

Сервер (Node.js):

const http = require("http");

http
  .createServer((req, res) => {
    res.writeHead(200, {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
    });

    setInterval(() => {
      res.write(`data: Сообщение с сервера\n\n`);
    }, 1000);
  })
  .listen(3000);

Клиент (HTML/JavaScript):

<!DOCTYPE html>
<html>
  <head>
    <title>Server-Sent Events Example</title>
  </head>
  <body>
    <div id="sse-data"></div>

    <script>
      const eventSource = new EventSource("/sse");

      eventSource.onmessage = (event) => {
        const sseDataElement = document.getElementById("sse-data");
        sseDataElement.innerHTML += `<p>${event.data}</p>`;
      };

      eventSource.onerror = (error) => {
        console.error("Error:", error);
      };
    </script>
  </body>
</html>

В этом примере сервер на Node.js отправляет события, содержащие текстовое сообщение, каждую секунду по пути /sse. Клиентский код создает экземпляр EventSource и слушает события, которые приходят с сервера. Полученные данные выводятся на страницу.

События, отправляемые с сервера, предоставляют простой и эффективный способ передачи данных от сервера к клиенту в режиме реального времени. Они особенно полезны для обновления информации на веб-странице без необходимости перезагрузки страницы или активных запросов от клиента. ⬆ Наверх

Как получать уведомления событий, отправляемых с сервера (Server-Sent Events)?

Для получения уведомлений о событиях, отправляемых с сервера (Server-Sent Events или SSE), в веб-браузере используется объект EventSource. Этот объект позволяет установить соединение с сервером и прослушивать события, приходящие с сервера в режиме реального времени.

Пример получения уведомлений событий, отправляемых с сервера:

Сервер (Node.js):

const http = require("http");

http
  .createServer((req, res) => {
    res.writeHead(200, {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
    });

    setInterval(() => {
      res.write(`data: Сообщение с сервера\n\n`);
    }, 1000);
  })
  .listen(3000);

Клиент (HTML/JavaScript):

<!DOCTYPE html>
<html>
  <head>
    <title>Server-Sent Events Example</title>
  </head>
  <body>
    <div id="sse-data"></div>

    <script>
      const eventSource = new EventSource("/sse");

      eventSource.onmessage = (event) => {
        const sseDataElement = document.getElementById("sse-data");
        sseDataElement.innerHTML += `<p>${event.data}</p>`;
      };

      eventSource.onerror = (error) => {
        console.error("Ошибка:", error);
      };
    </script>
  </body>
</html>

В этом примере, когда сервер на Node.js отправляет события, клиентский код создает экземпляр EventSource и слушает события, которые приходят с сервера. Полученные данные выводятся на страницу. Каждую секунду сервер отправляет сообщение, и это сообщение отображается на веб-странице в реальном времени.

Использование объекта EventSource позволяет устанавливать длительное соединение с сервером и автоматически получать уведомления о событиях. ⬆ Наверх

Как проверить поддержку браузером событий, отправляемых с сервера (Server-Sent Events)?

Для проверки поддержки браузером событий, отправляемых с сервера (Server-Sent Events или SSE), вы можете использовать объект EventSource и проверить его наличие и функциональность.

Пример проверки поддержки браузером событий, отправляемых с сервера:

if (typeof EventSource !== "undefined") {
  // Браузер поддерживает SSE
  const eventSource = new EventSource("/sse");

  eventSource.onmessage = (event) => {
    console.log("Получено событие:", event.data);
  };

  eventSource.onerror = (error) => {
    console.error("Ошибка:", error);
  };
} else {
  // Браузер не поддерживает SSE
  console.error("Браузер не поддерживает Server-Sent Events.");
}

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

Проверка поддержки SSE особенно важна, чтобы предоставить альтернативное поведение для браузеров, которые не поддерживают эту технологию. ⬆ Наверх

Какие события доступны для событий, отправляемых с сервера (Server-Sent Events)?

Для событий, отправляемых с сервера (Server-Sent Events или SSE), доступны следующие типы событий:

  1. message: Это событие возникает, когда сервер отправляет новое событие. Вы можете использовать обработчик события onmessage, чтобы обрабатывать приходящие данные.

  2. error: Это событие возникает, если происходит ошибка во время соединения или передачи данных. Вы можете использовать обработчик события onerror, чтобы обрабатывать ошибки.

  3. open: Это событие возникает, когда соединение с сервером устанавливается. Однако, оно редко используется, так как события, отправляемые с сервера, подразумевают постоянное открытое соединение.

Пример использования обработчиков событий:

const eventSource = new EventSource("/sse");

eventSource.onmessage = (event) => {
  console.log("Получено событие:", event.data);
};

eventSource.onerror = (error) => {
  console.error("Ошибка:", error);
};

В этом примере мы устанавливаем обработчики для событий message и error. Когда на сервере отправляется новое событие, будет вызван обработчик onmessage, и мы выведем данные этого события в консоль. Если произойдет ошибка в соединении, будет вызван обработчик onerror, и мы выведем информацию об ошибке. ⬆ Наверх

Каковы основные правила работы с промисами (Promise)?

Промисы (Promise) в JavaScript предоставляют механизм для управления асинхронными операциями и обработки их результатов. Вот основные правила работы с промисами:

  1. Создание промиса: Промис можно создать с помощью конструктора Promise. Внутри конструктора находится функция с двумя параметрами - resolve и reject, которые используются для завершения промиса успешно или с ошибкой.

  2. Обработка результатов: Используйте методы .then() и .catch() для обработки успешного завершения и ошибок соответственно.

  3. Цепочки промисов: Метод .then() также возвращает новый промис, что позволяет создавать цепочки операций.

  4. Обработка ошибок: Используйте метод .catch() для централизованной обработки ошибок в цепочке промисов.

  5. Обработка асинхронных операций: Код внутри промиса выполняется асинхронно. Можно использовать setTimeout, fetch, XMLHttpRequest и другие асинхронные операции.

  6. Состояния промиса: Промис имеет три основных состояния - ожидание (pending), выполнено (fulfilled), отклонено (rejected).

  7. Невозможность изменения состояния: После того как промис перешел в состояние "выполнено" или "отклонено", его состояние не может измениться.

Пример использования промисов:

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const data = "Данные получены";
    if (data) {
      resolve(data); // Успешное выполнение
    } else {
      reject("Произошла ошибка"); // Ошибка
    }
  }, 2000);
});

fetchData
  .then((result) => {
    console.log(result); // "Данные получены"
  })
  .catch((error) => {
    console.error(error); // "Произошла ошибка"
  });

В этом примере создается промис fetchData, который после двух секунд успешно завершается или завершается с ошибкой. Мы используем методы .then() и .catch() для обработки результатов и ошибок соответственно. ⬆ Наверх

Что такое "callback внутри callbackа" (callback in callback)?

"Callback внутри callbackа" означает использование одной или нескольких функций обратного вызова (callback) внутри другой функции обратного вызова. Это может произойти, когда выполнение асинхронного кода требует последовательности операций или обработки результатов одной асинхронной операции перед выполнением другой.

Пример "callback внутри callbackа":

function fetchUserData(userId, onSuccess, onError) {
  // Эмуляция асинхронного запроса данных пользователя
  setTimeout(() => {
    const userData = { id: userId, name: "John" };
    if (userData) {
      onSuccess(userData);
    } else {
      onError("Ошибка при получении данных пользователя");
    }
  }, 1000);
}

function fetchUserPosts(user, onSuccess, onError) {
  // Эмуляция асинхронного запроса постов пользователя
  setTimeout(() => {
    const posts = ["Пост 1", "Пост 2"];
    if (posts) {
      onSuccess(posts);
    } else {
      onError("Ошибка при получении постов пользователя");
    }
  }, 1500);
}

fetchUserData(
  123,
  (user) => {
    console.log("Данные пользователя:", user);

    fetchUserPosts(
      user,
      (posts) => {
        console.log("Посты пользователя:", posts);
      },
      (error) => {
        console.error("Ошибка:", error);
      }
    );
  },
  (error) => {
    console.error("Ошибка:", error);
  }
);

В этом примере мы используем две функции обратного вызова: fetchUserData и fetchUserPosts. Внутри успешного коллбэка первой функции мы вызываем вторую функцию обратного вызова для получения постов пользователя. Это демонстрирует "callback внутри callbackа" - асинхронные операции, которые зависят друг от друга. ⬆ Наверх

Что такое цепочка промисов (Promise Chaining)?

Цепочка промисов (Promise Chaining) - это метод использования промисов в JavaScript, который позволяет последовательно связывать несколько асинхронных операций в виде цепочки, где результат одной операции передается в следующую.

Пример цепочки промисов:

function fetchUserData(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const userData = { id: userId, name: "John" };
      if (userData) {
        resolve(userData);
      } else {
        reject("Ошибка при получении данных пользователя");
      }
    }, 1000);
  });
}

function fetchUserPosts(user) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const posts = ["Пост 1", "Пост 2"];
      if (posts) {
        resolve(posts);
      } else {
        reject("Ошибка при получении постов пользователя");
      }
    }, 1500);
  });
}

fetchUserData(123)
  .then((user) => {
    console.log("Данные пользователя:", user);
    return fetchUserPosts(user);
  })
  .then((posts) => {
    console.log("Посты пользователя:", posts);
  })
  .catch((error) => {
    console.error("Ошибка:", error);
  });

В этом примере мы используем метод .then() для связывания двух асинхронных операций - fetchUserData и fetchUserPosts. Результат операции fetchUserData передается в метод .then(), где выполняется операция fetchUserPosts. Это позволяет нам последовательно выполнять асинхронные операции в линейной цепочке.

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

Что такое Promise.all?

Promise.all - это метод в JavaScript, который позволяет объединить несколько промисов в массиве в один промис. Этот метод ожидает выполнения всех промисов в массиве и возвращает новый промис, который разрешается массивом результатов, когда все промисы успешно выполнились, или отклоняется с ошибкой, если хотя бы один промис отклонен.

Пример использования Promise.all:

function fetchUserData(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const userData = { id: userId, name: "John" };
      if (userData) {
        resolve(userData);
      } else {
        reject("Ошибка при получении данных пользователя");
      }
    }, 1000);
  });
}

function fetchUserPosts(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const posts = ["Пост 1", "Пост 2"];
      if (posts) {
        resolve(posts);
      } else {
        reject("Ошибка при получении постов пользователя");
      }
    }, 1500);
  });
}

const userId = 123;

Promise.all([fetchUserData(userId), fetchUserPosts(userId)])
  .then((results) => {
    const userData = results[0];
    const userPosts = results[1];
    console.log("Данные пользователя:", userData);
    console.log("Посты пользователя:", userPosts);
  })
  .catch((error) => {
    console.error("Ошибка:", error);
  });

В этом примере мы используем Promise.all для параллельного выполнения fetchUserData и fetchUserPosts для одного и того же userId. Когда оба промиса успешно выполняются, мы получаем массив результатов и можем обработать их с помощью .then(). Если хотя бы один промис отклонен, обработчик ошибок будет вызван.

Promise.all особенно полезен, когда нужно выполнить несколько асинхронных операций параллельно и дождаться их завершения. ⬆ Наверх

Какова цель метода race в промисах?

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

Пример использования метода race:

function fetchUserData(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const userData = { id: userId, name: "John" };
      if (userData) {
        resolve(userData);
      } else {
        reject("Ошибка при получении данных пользователя");
      }
    }, 1000);
  });
}

function fetchUserPosts(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const posts = ["Пост 1", "Пост 2"];
      if (posts) {
        resolve(posts);
      } else {
        reject("Ошибка при получении постов пользователя");
      }
    }, 1500);
  });
}

const userId = 123;

Promise.race([fetchUserData(userId), fetchUserPosts(userId)])
  .then((result) => {
    console.log("Первый завершившийся результат:", result);
  })
  .catch((error) => {
    console.error("Ошибка:", error);
  });

В этом примере метод race используется для параллельного выполнения fetchUserData и fetchUserPosts для одного и того же userId. Результатом будет тот промис, который первым завершится. Если первый завершившийся промис успешно выполнится, будет вызван обработчик .then(). Если первый завершившийся промис отклонен, будет вызван обработчик ошибок через .catch().

Метод race полезен, когда нужно выполнить несколько асинхронных операций и использовать результат первой завершившейся. ⬆ Наверх

Что такое строгий режим (strict mode) в JavaScript?

Строгий режим (strict mode) - это специальный режим работы JavaScript, в котором применяются дополнительные правила и ограничения для улучшения безопасности и предотвращения ошибок. Включение строгого режима помогает разработчикам избегать определенных уязвимостей и нежелательных практик в коде.

Пример использования строгого режима:

"use strict";

x = 10; // Ошибка: x не определено

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

Преимущества строгого режима:

  1. Запрет на использование неявных глобальных переменных: В строгом режиме, если переменная не объявлена, будет выдана ошибка.

  2. Запрет на удаление переменных и функций: Нельзя удалять переменные и функции, объявленные с использованием var, let, const, function.

  3. Запрет на дублирование параметров функции: Нельзя использовать одинаковые имена параметров в одной функции.

  4. Запрет на использование некоторых нежелательных операторов: Например, with, который часто усложняет чтение и понимание кода.

  5. Строгая обработка ошибок: Некоторые незаметные ошибки в нестрогом режиме приводят к неожиданному поведению, в строгом режиме они приводят к выдаче ошибок.

Строгий режим рекомендуется использовать во всех новых проектах, так как он помогает сделать код более надежным и предотвращает множество потенциальных проблем. ⬆ Наверх

Зачем нужен строгий режим (strict mode)?

Строгий режим (strict mode) в JavaScript нужен для усиления контроля над вашим кодом и предотвращения многих распространенных ошибок. Он помогает сделать ваш код более надежным, предупреждает о нежелательных практиках и улучшает общую безопасность выполнения программы.

Пример:

Допустим, у нас есть следующий код:

x = 10; // Ошибка?
console.log(x);

В нестрогом режиме, это сработает без ошибок, но переменная x будет автоматически создана как глобальная. Это может привести к непредсказуемому поведению в вашей программе. Однако, если мы включим строгий режим:

"use strict";

x = 10; // Ошибка: x не определено
console.log(x);

В этом случае, код выдаст ошибку на строке x = 10;, так как попытка присвоения значения необъявленной переменной запрещена в строгом режиме. Это пример того, как строгий режим помогает выявить и предотвратить потенциальные ошибки.

Преимущества строгого режима:

  1. Предотвращение использования неявных глобальных переменных: Это помогает избегать случайного создания глобальных переменных и улучшает изоляцию кода.

  2. Обнаружение некоторых ошибок на этапе разработки: Например, использование зарезервированных слов, дублирование параметров функции, использование with, и т.д.

  3. Улучшение производительности: Строгий режим может позволить JavaScript-движку оптимизировать код для более эффективного выполнения.

  4. Улучшение безопасности: Строгий режим может предотвращать опасные операции, такие как использование eval для выполнения небезопасного кода.

  5. Соответствие современным стандартам: Строгий режим помогает писать код в соответствии с современными стандартами и рекомендациями.

Использование строгого режима рекомендуется во избежание многих ошибок и проблем, которые могут возникнуть в коде, особенно в больших и сложных проектах. ⬆ Наверх

Как объявить строгий режим (strict mode)?

Для объявления строгого режима (strict mode) в JavaScript используется директива "use strict";. Эта директива помещается в начало скрипта или функции и включает строгий режим для данного контекста.

Пример:

"use strict";

x = 10; // Ошибка: x не определено
console.log(x);

В этом примере строгий режим включается с помощью директивы "use strict"; перед использованием переменной x. При попытке присвоения значения необъявленной переменной будет выдана ошибка.

Варианты объявления строгого режима:

  1. Глобальный уровень: Директиву "use strict"; можно поместить в начало глобальной области видимости, что включит строгий режим для всего скрипта.
"use strict";

// Весь код в этом скрипте находится в строгом режиме
  1. Локальный уровень (внутри функции): Директиву "use strict"; также можно поместить в начало функции, чтобы включить строгий режим только для этой функции.
function myFunction() {
  "use strict";

  // Код внутри этой функции находится в строгом режиме
}

Обратите внимание, что строгий режим включается по отдельности для каждой функции или скрипта. Если вы хотите использовать его повсюду, включите директиву "use strict"; в каждый файл или функцию.

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

Какова цель двойного восклицательного знака в JavaScript?

Двойной восклицательный знак (!!) в JavaScript используется для преобразования значения в булевое (логическое) значение true или false. Это помогает сделать явное преобразование данных в булевый тип.

Пример:

const value = "Hello";

const booleanValue = !!value;
console.log(booleanValue); // Вывод: true

В этом примере, value содержит строку "Hello". При применении двойного восклицательного знака, значение будет преобразовано в булевое значение true, так как любая непустая строка в JavaScript рассматривается как true.

Полезность двойного восклицательного знака:

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

const number = 0;
const stringValue = "Some text";
const arrayValue = [];

console.log(!!number); // Вывод: false
console.log(!!stringValue); // Вывод: true
console.log(!!arrayValue); // Вывод: true

В этом примере, number со значением 0 преобразуется в false, а stringValue и arrayValue, содержащие данные, преобразуются в true.

Использование двойного восклицательного знака может быть полезным при необходимости преобразования значений в булевый тип для выполнения логических операций или проверок. ⬆ Наверх

Какова цель оператора delete в JavaScript?

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

Пример:

const person = {
  firstName: "John",
  lastName: "Doe",
  age: 30,
};

delete person.age;

console.log(person); // Вывод: { firstName: "John", lastName: "Doe" }

В этом примере мы создали объект person с тремя свойствами: firstName, lastName и age. С помощью оператора delete мы удаляем свойство age из объекта. После выполнения этой операции свойство age больше не существует в объекте.

Ограничения оператора delete:

  1. Оператор delete не может удалить переменные или функции.

  2. В строгом режиме (strict mode), попытка удаления неперечислимых свойств или свойств, принадлежащих прототипу объекта, вызовет ошибку.

"use strict";

const obj = {};
Object.defineProperty(obj, "myProperty", {
  value: "Hello",
  enumerable: false, // Свойство неперечислимое
});

delete obj.myProperty; // Ошибка в строгом режиме

Использование оператора delete:

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

Оператор delete часто применяется, когда нужно динамически управлять свойствами объектов или элементами массивов, но его использование следует осуществлять сознательно и внимательно. ⬆ Наверх

Что такое оператор typeof?

Оператор typeof в JavaScript используется для определения типа значения. Он возвращает строку, представляющую тип операнда.

Пример:

const number = 42;
const string = "Hello";
const boolean = true;
const object = { key: "value" };
const array = [1, 2, 3];

console.log(typeof number); // Вывод: "number"
console.log(typeof string); // Вывод: "string"
console.log(typeof boolean); // Вывод: "boolean"
console.log(typeof object); // Вывод: "object"
console.log(typeof array); // Вывод: "object"

В этом примере мы используем оператор typeof для определения типов различных значений. Он возвращает строку с именем типа. Обратите внимание, что typeof array возвращает "object", так как встроенный тип массива в JavaScript также является объектом.

Важные моменты:

  1. typeof null возвращает "object", что является исторической ошибкой в языке JavaScript.

  2. typeof function возвращает "function", что позволяет отличить функции от других объектов.

  3. typeof undefined возвращает "undefined".

Применение оператора typeof:

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

function printValue(value) {
  if (typeof value === "string") {
    console.log("Строка: " + value);
  } else if (typeof value === "number") {
    console.log("Число: " + value);
  } else {
    console.log("Неизвестный тип");
  }
}

printValue("Hello"); // Вывод: Строка: Hello
printValue(42); // Вывод: Число: 42
printValue(true); // Вывод: Неизвестный тип

⬆ Наверх

Что такое свойство со значением undefined?

Свойство со значением undefined в JavaScript указывает на то, что свойство существует в объекте, но не имеет присвоенного значения. Это означает, что переменная объявлена, но ей не было присвоено никакое конкретное значение.

Пример:

const person = {
  name: "John",
  age: undefined,
};

console.log(person.name); // Вывод: John
console.log(person.age); // Вывод: undefined

В этом примере у нас есть объект person с двумя свойствами: name и age. Свойство name имеет присвоенное значение "John", тогда как свойство age имеет значение undefined.

Зачем используется undefined:

  1. По умолчанию для неинициализированных переменных: Если переменная объявлена, но ей не было присвоено значение, то ее значение по умолчанию будет undefined.

  2. Для явного указания отсутствия значения: В коде можно явно указать, что свойство существует, но ему не присвоено значение, используя undefined.

  3. Проверка наличия свойства в объекте: Проверка наличия свойства в объекте может осуществляться с помощью undefined.

Применение в проверках:

const obj = {
  prop: undefined,
};

if (obj.prop === undefined) {
  console.log("Свойство не имеет значения");
}

В этом примере мы проверяем, имеет ли свойство prop в объекте obj значение undefined, чтобы определить, было ли ему присвоено какое-либо значение. ⬆ Наверх

Что такое значение null?

Значение null в JavaScript представляет собой специальное значение, которое указывает на отсутствие значения или пустое значение. Это не то же самое, что undefined. В то время как undefined означает, что значение переменной не было определено, null используется для явного указания отсутствия какого-либо значения.

Пример:

const myValue = null;

console.log(myValue); // Вывод: null

В этом примере переменной myValue присвоено значение null. Это показывает, что переменная существует, но ей специально присвоено значение null.

Зачем используется null:

  1. Явное указание отсутствия значения: В программировании иногда требуется явно указать, что у переменной нет значения. В таких случаях null может быть использован вместо неопределенного значения.

  2. Сброс значения: В некоторых ситуациях значение переменной может быть установлено на null для обозначения, что предыдущее значение больше не актуально.

  3. Ручное освобождение памяти: В некоторых языках программирования, значение null может использоваться для ручного освобождения памяти, хотя в JavaScript память освобождается автоматически.

Пример использования:

let user = {
  name: "John",
  age: null,
};

console.log(user.name); // Вывод: John
console.log(user.age); // Вывод: null

В этом примере мы используем null для свойства age объекта user вместо undefined, чтобы явно показать, что возраст пользователя неизвестен. ⬆ Наверх

В чем разница между значениями null и undefined?

В JavaScript null и undefined представляют отсутствие значения, но у них есть небольшие различия в их семантике и использовании.

undefined:

  • undefined означает, что переменная объявлена, но ей не было присвоено никакое значение.

null:

  • null означает, что переменная объявлена, но явно имеет пустое значение.

Примеры:

let variable1; // Значение переменной будет undefined
const variable2 = null; // Значение переменной будет null

console.log(variable1); // Вывод: undefined
console.log(variable2); // Вывод: null

console.log(variable1 === undefined); // Вывод: true
console.log(variable2 === null); // Вывод: true

Когда использовать каждое значение?

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

  • null используется, когда вы явно хотите указать, что переменная имеет пустое или отсутствующее значение. Это может быть полезным, например, при сбросе значения переменной на "ничто".

Обратите внимание, что при сравнении с помощью оператора ===, null и undefined равны друг другу, но не равны никаким другим значениям:

console.log(null === undefined); // Вывод: true
console.log(null == undefined); // Вывод: true

console.log(null === 0); // Вывод: false
console.log(undefined === 0); // Вывод: false

В общем, использование null и undefined зависит от контекста и задачи, но оба значения представляют отсутствие или пустое значение. ⬆ Наверх

Что такое eval?

eval в JavaScript представляет собой встроенную функцию, которая позволяет интерпретировать и выполнять строку как код JavaScript. Однако из-за своих потенциальных безопасностных и производственных проблем использование eval не рекомендуется в большинстве ситуаций.

Пример:

const x = 10;
const y = 20;
const code = "x + y";

const result = eval(code);
console.log(result); // Вывод: 30

В этом примере код в строке 'x + y' интерпретируется и выполняется как код JavaScript с помощью eval, что приводит к результату 30 при сложении x и y.

Ограничения и проблемы:

  1. Безопасность: Использование eval может представлять угрозу безопасности, так как оно позволяет выполнить произвольный код, включая вредоносный.

  2. Сложность отладки: Код, выполняемый через eval, труднее отлаживать, так как он может изменяться во время выполнения.

  3. Снижение производительности: Использование eval может снизить производительность, так как код, выполняемый с его помощью, не может быть заранее оптимизирован.

Альтернативы:

В большинстве случаев лучше использовать альтернативные подходы, такие как:

  • JSON.parse: Для разбора JSON-строк.

  • Функции конструктора: Для создания объектов.

  • Функции высшего порядка: Для выполнения динамического кода.

const x = 10;
const y = 20;
const code = (x, y) => x + y;

const result = code(x, y);
console.log(result); // Вывод: 30

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

В чем разница между window и document?

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

window:

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

  • window содержит множество свойств и методов, которые предоставляют доступ к браузерным функциям и свойствам, таким как размер окна, URL-адрес, таймеры, хранилища и многое другое.

document:

  • document является объектом, представляющим текущий HTML-документ в окне браузера. Он предоставляет доступ к элементам и структуре HTML-документа, позволяя манипулировать содержимым, добавлять, изменять и удалять элементы.

  • document также предоставляет методы для работы с событиями, стилями и многими другими аспектами веб-страницы.

Пример:

// Получение высоты окна
const windowHeight = window.innerHeight;

// Изменение текста элемента на странице
const myElement = document.getElementById("my-element");
myElement.textContent = "Новый текст";

В этом примере мы используем window.innerHeight, чтобы получить высоту окна браузера, и document.getElementById, чтобы получить элемент на странице и изменить его текстовое содержимое.

Заключение:

Коротко говоря, window представляет окно браузера и предоставляет доступ к его свойствам, в то время как document представляет текущий HTML-документ и позволяет манипулировать его содержимым. ⬆ Наверх

Как получить доступ к истории браузера в JavaScript?

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

Пример:

// Перейти на предыдущую страницу в истории
history.back();

// Перейти на следующую страницу в истории (если доступно)
history.forward();

// Перейти на определенное количество страниц назад или вперед
history.go(-2); // Перейти назад на две страницы
history.go(3); // Перейти вперед на три страницы

// Получить количество записей в истории
const historyLength = history.length;
console.log("Количество записей в истории: " + historyLength);

В этом примере мы используем методы back(), forward() и go() объекта history, чтобы перейти назад, вперед или на определенное количество страниц в истории. Мы также используем свойство length, чтобы получить количество записей в истории.

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

Использование в навигации:

Объект history полезен для управления навигацией между страницами внутри вашего веб-приложения. Он позволяет создавать пользовательские переходы и возвращения, сохраняя историю переходов между различными состояниями приложения. ⬆ Наверх

Как определить, включена ли клавиша Caps Lock?

Для определения, включена ли клавиша Caps Lock, можно использовать события клавиатуры в JavaScript. При этом проверяется состояние клавиши, когда пользователь вводит текст.

Пример:

// Событие обработки нажатия клавиши
document.addEventListener("keydown", function (event) {
  const capsLockOn = event.getModifierState("CapsLock");
  if (capsLockOn) {
    console.log("Клавиша Caps Lock включена");
  } else {
    console.log("Клавиша Caps Lock выключена");
  }
});

В этом примере мы добавляем обработчик события keydown на документ. При нажатии клавиши на клавиатуре мы используем метод getModifierState("CapsLock") для проверки состояния клавиши Caps Lock. Если она включена, выводится соответствующее сообщение.

Обратите внимание, что этот способ проверки зависит от обработки событий клавиатуры. Если пользователь вводит текст в поле ввода, например, в текстовом поле, то состояние клавиши Caps Lock можно определить по событиям этого поля.

Другой подход:

Еще одним способом может быть отслеживание состояния клавиши в реальном времени на поле ввода:

const inputElement = document.getElementById("my-input");

inputElement.addEventListener("input", function (event) {
  const text = event.target.value;
  const lastChar = text[text.length - 1];
  const isUpperCase =
    lastChar === lastChar.toUpperCase() && lastChar !== lastChar.toLowerCase();

  if (isUpperCase) {
    console.log("Клавиша Caps Lock включена");
  } else {
    console.log("Клавиша Caps Lock выключена");
  }
});

В этом случае мы отслеживаем событие input на поле ввода. После каждого ввода символа мы проверяем, является ли последний введенный символ заглавной буквой. Если да, то считаем, что клавиша Caps Lock включена. ⬆ Наверх

Что такое isNaN?

isNaN в JavaScript - это встроенная функция, которая используется для определения, является ли переданное значение "не числом" (Not-a-Number). Она возвращает true, если значение не может быть преобразовано в число, и false, если оно может быть.

Пример:

console.log(isNaN("Hello")); // Вывод: true, так как "Hello" не является числом
console.log(isNaN(42)); // Вывод: false, так как 42 - это число
console.log(isNaN("42")); // Вывод: false, так как "42" может быть преобразовано в число

В этом примере isNaN используется для проверки разных значений. Значение "Hello" не является числом, поэтому результат - true. Значение 42 является числом, поэтому результат - false. Значение "42" может быть преобразовано в число, поэтому также получается false.

Замечание:

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

console.log(isNaN("42px")); // Вывод: true, так как "42px" не может быть преобразовано в число

В этом случае "42px" не может быть корректно преобразовано в число, даже если оно начинается с числа. Поэтому результат - true.

Использование замен:

Для более точной проверки на числовое значение рекомендуется использовать Number.isNaN(), доступный в ECMAScript 6:

console.log(Number.isNaN("Hello")); // Вывод: false
console.log(Number.isNaN(42)); // Вывод: false
console.log(Number.isNaN("42")); // Вывод: false
console.log(Number.isNaN("42px")); // Вывод: false

В этом случае Number.isNaN() не пытается преобразовывать значение, и результаты более соответствуют ожиданиям. ⬆ Наверх

Каковы различия между необъявленными и неопределенными переменными?

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

Необъявленные переменные:

  • Необъявленные переменные - это переменные, которые не были объявлены с помощью ключевых слов var, let или const.

  • Попытка обращения к необъявленной переменной приведет к ошибке ReferenceError.

Неопределенные переменные:

  • Неопределенные переменные - это переменные, которые были объявлены, но им не было присвоено никакое значение.

  • При обращении к неопределенной переменной, ее значение будет undefined.

Примеры:

// Пример необъявленной переменной
try {
  console.log(nonExistentVariable); // ReferenceError: nonExistentVariable is not defined
} catch (error) {
  console.log("Ошибка: " + error.message);
}

// Пример объявления и неопределенной переменной
let x;
console.log(x); // Вывод: undefined

В первом примере nonExistentVariable не объявлена, поэтому обращение к ней вызывает ошибку. Во втором примере переменная x объявлена, но не имеет значения, поэтому выводится undefined.

Заключение:

Помните, что необъявленные переменные - это переменные, которые вообще не были объявлены, а неопределенные переменные - это переменные, которые объявлены, но не имеют значения. ⬆ Наверх

Что такое глобальные переменные?

Глобальные переменные в JavaScript - это переменные, которые объявлены в глобальной области видимости, то есть за пределами любых функций или блоков кода. Они доступны из любого места в вашем коде.

Пример:

// Глобальная переменная
var globalVariable = "Это глобальная переменная";

function printGlobal() {
  console.log(globalVariable); // Можно обратиться к глобальной переменной внутри функции
}

printGlobal(); // Вывод: "Это глобальная переменная"
console.log(globalVariable); // Вывод: "Это глобальная переменная"

В этом примере переменная globalVariable объявлена в глобальной области видимости и, следовательно, доступна как внутри функции printGlobal, так и за её пределами.

Важное замечание:

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

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

Пример без использования глобальных переменных:

function exampleFunction() {
  let localVariable = "Это локальная переменная";
  console.log(localVariable);
}

exampleFunction(); // Вывод: "Это локальная переменная"
console.log(localVariable); // Ошибка: localVariable is not defined

В этом примере localVariable объявлена внутри функции и не доступна за её пределами, что помогает избежать конфликтов и проблем с областью видимости. ⬆ Наверх

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

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

  1. Конфликты имен: Если в разных частях кода используются одинаковые имена глобальных переменных, это может привести к непредсказуемому поведению и ошибкам.

  2. Неявные изменения: Глобальные переменные могут быть изменены из любой части кода, что может сделать отслеживание изменений сложным и привести к неожиданным эффектам.

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

  4. Читаемость и понимание кода: Использование глобальных переменных может затруднить понимание того, какие данные используются и откуда они берутся в различных частях кода.

Пример:

var count = 0;

function increment() {
  count++;
}

function doubleCount() {
  count = count * 2;
}

increment();
console.log(count); // Вывод: 1

doubleCount();
console.log(count); // Вывод: 2 (ожидалось 4 из-за неявного изменения)

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

Предостережение:

Хотя использование глобальных переменных иногда неизбежно, хорошей практикой является минимизация их использования. Лучше ограничивать область видимости переменных, объявляя их внутри функций, блоков кода или модулей, чтобы снизить вероятность конфликтов и неожиданных изменений. ⬆ Наверх

Что такое свойство NaN?

NaN (Not-a-Number) в JavaScript представляет собой специальное значение, которое указывает на то, что результат математической операции не является числом. У NaN есть свойство NaN, которое можно использовать для определения, является ли значение NaN.

Пример:

const result = 0 / 0; // Деление на ноль дает NaN
console.log(result); // Вывод: NaN
console.log(result === NaN); // Вывод: false, так как NaN нельзя сравнить напрямую

console.log(isNaN(result)); // Вывод: true, так как result содержит NaN

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

Для проверки наличия значения NaN удобно использовать функцию isNaN(). Она возвращает true, если переданное значение является NaN, и false, если не является.

Дополнительно:

Заметьте, что использование оператора === для сравнения с NaN может быть некорректным, так как NaN не равно ни одному другому значению, даже себе. Поэтому для проверки на NaN рекомендуется использовать isNaN() или строгое сравнение с Number.isNaN(). ⬆ Наверх

Каково назначение функции isFinite?

В JavaScript функция isFinite используется для определения, является ли переданное значение конечным числом, то есть числом, которое не равно бесконечности (Infinity) или минус бесконечности (-Infinity).

Пример:

console.log(isFinite(42)); // Вывод: true, так как 42 - конечное число
console.log(isFinite(Infinity)); // Вывод: false, так как Infinity - бесконечность
console.log(isFinite(-Infinity)); // Вывод: false, так как -Infinity - минус бесконечность
console.log(isFinite("42")); // Вывод: true, так как "42" будет преобразовано в число
console.log(isFinite("Hello")); // Вывод: false, так как "Hello" не может быть преобразовано в число

В этом примере мы используем isFinite для проверки разных значений. Число 42 является конечным числом, поэтому результат - true. Значения Infinity и -Infinity не являются конечными числами, поэтому результат - false. Строка "42" может быть преобразована в число, поэтому также получается true. Строка "Hello" не может быть преобразована в число, поэтому результат - false.

Замечание:

Обратите внимание, что isFinite преобразует переданное значение в число перед проверкой. Если значение нельзя преобразовать в число (например, строку "Hello"), то результат будет false. Это может быть полезно для фильтрации некорректных или нечисловых значений. ⬆ Наверх

Что такое поток событий (Event Flow)?

Поток событий (Event Flow) в контексте веб-разработки описывает последовательность, в которой браузер обрабатывает события в документе. События могут быть связаны с элементами DOM, например, щелчок мыши, нажатие клавиши, изменение размеров окна и так далее. Поток событий определяет порядок, в котором браузер передает и обрабатывает эти события.

Три этапа потока событий:

  1. Фаза захвата (Capture Phase): Событие проходит вниз по дереву DOM, начиная с самого верхнего родительского элемента и двигаясь к целевому элементу события.

  2. Фаза цели (Target Phase): Событие достигает целевого элемента, на котором оно было сгенерировано.

  3. Фаза всплытия (Bubbling Phase): Событие возвращается вверх по дереву DOM, от целевого элемента к верхнему родительскому элементу.

Пример:

<div id="parent">
  <button id="child">Нажми меня</button>
</div>
const parent = document.getElementById("parent");
const child = document.getElementById("child");

parent.addEventListener(
  "click",
  () => {
    console.log("Событие всплывает: parent");
  },
  false
); // параметр false указывает на использование фазы всплытия

child.addEventListener(
  "click",
  () => {
    console.log("Событие захватывает: child");
  },
  true
); // параметр true указывает на использование фазы захвата

В этом примере при клике на кнопку "Нажми меня" сначала будет выполняться обработчик события на этой кнопке (фаза цели), затем на родительском элементе (фаза всплытия). Результат выполнения будет:

Событие захватывает: child
Событие всплывает: parent

Приемущества понимания потока событий:

Понимание потока событий важно для правильной обработки событий и предотвращения нежелательных поведений. Вы можете выбирать между фазой захвата и фазой всплытия в зависимости от требуемого поведения и цели обработки событий. ⬆ Наверх

Что такое всплытие событий (Event Bubbling)?

Всплытие событий (Event Bubbling) - это механизм в потоке событий браузера, при котором событие, возникающее на вложенном элементе DOM, поочередно передается родительским элементам вверх по иерархии DOM. Это позволяет обработчикам событий, прикрепленным к родительским элементам, также реагировать на событие, которое произошло внутри вложенного элемента.

Пример:

<div id="parent">
  <button id="child">Нажми меня</button>
</div>
const parent = document.getElementById("parent");
const child = document.getElementById("child");

parent.addEventListener("click", () => {
  console.log("Событие всплывает: parent");
});

child.addEventListener("click", () => {
  console.log("Событие всплывает: child");
});

При клике на кнопку "Нажми меня" произойдет всплытие события. Сначала выполнится обработчик события на кнопке (вложенный элемент), а затем обработчик на родительском элементе. Результат выполнения:

Событие всплывает: child
Событие всплывает: parent

Преимущества всплытия событий:

  1. Удобство обработки: Всплытие событий позволяет просто обрабатывать события на родительских элементах, не привязывая обработчики ко всем вложенным элементам.

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

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

Замечание:

Всплытие событий может быть остановлено с помощью метода event.stopPropagation(), если необходимо избежать передачи события выше по иерархии DOM. ⬆ Наверх

Что такое захват событий (Event Capturing)?

Захват событий (Event Capturing) - это механизм в потоке событий браузера, при котором событие сначала передается от родительских элементов к целевому элементу, а затем до него долго до вложенных элементов. Это происходит в фазе захвата (Capture Phase) потока событий.

Пример:

<div id="parent">
  <button id="child">Нажми меня</button>
</div>
const parent = document.getElementById("parent");
const child = document.getElementById("child");

parent.addEventListener(
  "click",
  () => {
    console.log("Событие захватывает: parent");
  },
  true
); // параметр true указывает на использование фазы захвата

child.addEventListener(
  "click",
  () => {
    console.log("Событие захватывает: child");
  },
  true
); // параметр true указывает на использование фазы захвата

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

Событие захватывает: parent
Событие захватывает: child

Преимущества захвата событий:

  1. Управление до событием: Захват событий позволяет обработать событие на родительских элементах до того, как оно достигнет целевого элемента.

  2. Предотвращение всплытия: Можно предотвратить всплытие события, если в фазе захвата будет вызван метод event.stopPropagation().

Замечание:

Захват событий (Capture Phase) не всегда используется на практике так часто, как всплытие событий (Bubbling Phase), но он может быть полезным, когда нужно обработать событие до его целевого элемента. ⬆ Наверх

Как отправить форму с помощью JavaScript?

Для отправки формы с помощью JavaScript вы можете использовать метод .submit() объекта формы. Этот метод вызывается на элементе формы и инициирует отправку данных формы на сервер.

Пример:

<form id="myForm">
  <input type="text" name="username" value="John" />
  <input type="email" name="email" value="john@example.com" />
  <button type="button" onclick="submitForm()">Отправить</button>
</form>

<script>
  function submitForm() {
    const form = document.getElementById("myForm");
    form.submit();
  }
</script>

В этом примере у нас есть форма с идентификатором myForm и кнопка, при нажатии которой вызывается функция submitForm(). Внутри этой функции мы получаем ссылку на форму с помощью document.getElementById("myForm") и затем вызываем метод .submit() для отправки формы.

Заметьте, что обычно кнопки внутри формы имеют атрибут type="submit", чтобы по умолчанию они запускали отправку формы. В данном примере мы использовали type="button", чтобы предотвратить автоматическую отправку и добавили вызов функции submitForm() при нажатии кнопки.

Предостережение:

Если у вас есть элементы формы с атрибутом name, браузер автоматически сгенерирует и отправит данные формы на сервер. Так что, если вам нужно вмешаться в процесс отправки формы, убедитесь, что у вас есть явная причина для этого. ⬆ Наверх

Как получить информацию о операционной системе?

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

Пример:

const osDetails = navigator.userAgent;

console.log("Информация об операционной системе:", osDetails);

Важно отметить, что свойство navigator.userAgent может возвращать довольно сложную строку, содержащую информацию не только об операционной системе, но и о браузере и других аспектах. Чтобы получить точную информацию об операционной системе, вы можете использовать сторонние библиотеки или сервисы, специализирующиеся на определении информации о пользовательском агенте. ⬆ Наверх

В чем разница между событиями загрузки документа и DOMContentLoaded?

Событие load и событие DOMContentLoaded являются двумя разными событиями в жизненном цикле загрузки веб-страницы. Они происходят в разные моменты и служат для разных целей.

Событие load:

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

window.addEventListener("load", () => {
  console.log("Страница и все ресурсы загружены");
});

Событие DOMContentLoaded:

Событие DOMContentLoaded возникает, когда весь DOM (структура страницы) готов к манипуляции с элементами, даже если некоторые внешние ресурсы, такие как изображения и стили, все еще загружаются. Это событие обычно используется для запуска скриптов или других действий, которые не зависят от полной загрузки всех ресурсов.

document.addEventListener("DOMContentLoaded", () => {
  console.log("DOM готов к манипуляции");
});

Различия между ними:

  • Событие load происходит после полной загрузки всех ресурсов, включая изображения и стили.
  • Событие DOMContentLoaded происходит после полной загрузки структуры DOM, но до полной загрузки внешних ресурсов.

В большинстве случаев, если вам нужно выполнить действия, связанные с манипуляцией DOM, рекомендуется использовать событие DOMContentLoaded, так как оно обеспечивает более быструю реакцию страницы. ⬆ Наверх

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

В JavaScript существуют различные типы объектов, которые могут быть классифицированы как встроенные (native), хост-объекты (host) и объекты пользовательского кода (user). Вот как они отличаются друг от друга:

Встроенные (Native) объекты:

Встроенные объекты - это объекты, предоставляемые самим языком JavaScript. Они включают в себя такие объекты, как Object, Array, String, Number, Date и другие. Эти объекты доступны по умолчанию в любом окружении, поддерживающем JavaScript.

Пример:

const myArray = new Array(1, 2, 3);
const myString = new String("Hello");

Хост-объекты (Host Objects):

Хост-объекты - это объекты, предоставляемые средой выполнения JavaScript, такой как браузерное окружение или среда Node.js. Эти объекты зависят от окружения и могут варьироваться в разных средах. Примерами хост-объектов могут быть window и document в браузере или объекты, предоставляемые сервером Node.js.

Пример:

console.log(window.innerWidth); // Свойство окна браузера

Объекты пользовательского кода (User Objects):

Объекты пользовательского кода - это объекты, созданные и определенные пользовательским кодом. Это объекты, которые вы создаете сами в своих скриптах, определяя их свойства и методы в соответствии с вашей логикой.

Пример:

const myCustomObject = {
  name: "John",
  age: 30,
  greet: function () {
    console.log("Hello, " + this.name);
  },
};

Вывод:

Встроенные (native) объекты предоставляются языком JavaScript, хост-объекты предоставляются окружением выполнения (браузером, Node.js и т.д.), а объекты пользовательского кода создаются и определяются самим пользовательским кодом. ⬆ Наверх

Какие инструменты или методы используются для отладки кода на JavaScript?

Отладка кода на JavaScript - это процесс выявления и исправления ошибок в вашем коде. Существует несколько инструментов и методов, которые можно использовать для упрощения этого процесса:

Инструменты браузера:

  1. Консоль разработчика: Практически все современные браузеры предоставляют консоль разработчика, где вы можете выводить сообщения, проверять значения переменных, анализировать ошибки и т.д.
  2. Инспектор элементов: Позволяет просматривать и изменять DOM-структуру страницы, а также применять стили для отладки макета.
  3. Отладчик кода: Позволяет установить точки останова, шагать по коду, анализировать значения переменных и контролировать выполнение кода шаг за шагом.

Инструменты сторонних разработчиков:

  1. Visual Studio Code: Популярный редактор кода с встроенной поддержкой отладки JavaScript.
  2. Chrome DevTools: Мощные инструменты для отладки в Chrome, включая отладчик и профилирование.
  3. Firefox Developer Tools: Инструменты для разработчиков Firefox с аналогичными функциональными возможностями.

Техники отладки:

  1. Использование точек останова: Вы можете установить точки останова в коде, чтобы остановить выполнение программы в определенном месте и анализировать состояние переменных.
  2. Вывод сообщений: Используйте функцию console.log() для вывода значений переменных и сообщений в консоль разработчика.
  3. Использование инструкции debugger: Вставьте ключевое слово debugger в код для активации отладчика в инструментах разработчика браузера.
  4. Анализ ошибок и исключений: При наличии ошибок и исключений в коде, браузер предоставит информацию о месте возникновения проблемы.

Пример:

function calculateSum(a, b) {
  debugger; // Остановка выполнения кода
  const sum = a + b;
  console.log("Сумма:", sum);
  return sum;
}

calculateSum(5, 10);

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

Каковы плюсы и минусы промисов по сравнению с обратными вызовами?

Плюсы использования промисов:

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

  2. Избегание "callback hell": Промисы позволяют избежать так называемой "callback hell" (чрезмерная вложенность обратных вызовов), что упрощает понимание и поддержку кода.

  3. Легкая обработка ошибок: Промисы позволяют централизованно обрабатывать ошибки через метод .catch() или блок catch, делая код более надежным.

  4. Чейнинг: Промисы поддерживают цепочку методов, что упрощает последовательное выполнение асинхронных операций.

Минусы использования промисов:

  1. Сложность для новичков: Новичкам может потребоваться время для понимания промисов и их работы.

  2. Нет поддержки в старых браузерах: Промисы поддерживаются не всеми старыми версиями браузеров, в отличие от обратных вызовов.

  3. Ограниченные возможности: Промисы имеют ограниченный набор функций по сравнению с некоторыми более новыми концепциями, такими как async/await.

Пример:

Использование обратных вызовов:

function fetchData(callback) {
  // Асинхронная операция
  setTimeout(() => {
    const data = { message: "Данные получены" };
    callback(data);
  }, 1000);
}

fetchData((result) => {
  console.log(result.message);
});

Использование промисов:

function fetchData() {
  return new Promise((resolve) => {
    // Асинхронная операция
    setTimeout(() => {
      const data = { message: "Данные получены" };
      resolve(data);
    }, 1000);
  });
}

fetchData().then((result) => {
  console.log(result.message);
});

В данном примере код с использованием промисов выглядит более читаемо и легко понимаемо. ⬆ Наверх

В чем разница между атрибутом и свойством?

В контексте HTML и JavaScript, термины "атрибут" и "свойство" обозначают два разных понятия, связанных с элементами веб-страницы.

Атрибут:

Атрибут - это часть HTML-кода, определяющая начальные значения для элементов. Они указываются в открывающем теге элемента в виде пары "имя=значение". Атрибуты являются частью статической структуры HTML-документа и задают начальные значения, которые могут быть изменены с помощью JavaScript. Атрибуты также могут быть использованы для передачи дополнительной информации, такой как ссылки или стили, браузерам и другим инструментам.

Пример:

<input type="text" value="Hello" id="myInput" />

Свойство:

Свойство - это значение, представляющее текущее состояние элемента, которое может изменяться динамически через JavaScript. Свойства находятся в объектах, представляющих HTML-элементы в DOM. Они предоставляют доступ к информации о состоянии элемента, а также позволяют изменять это состояние.

Пример:

const inputElement = document.getElementById("myInput");
console.log(inputElement.value); // Получение значения свойства "value"
inputElement.value = "New Value"; // Изменение значения свойства "value"

Различие между атрибутами и свойствами:

  • Атрибуты задают начальные значения элементов и часто описываются в HTML-коде.
  • Свойства предоставляют доступ к текущему состоянию элементов и часто изменяются с помощью JavaScript.
  • Изменение атрибутов не всегда влияет на свойства, и наоборот.

Например, изменение атрибута value на элементе <input> не обязательно изменит свойство value этого элемента, и наоборот.

<input type="text" value="Initial Value" id="myInput" />
const inputElement = document.getElementById("myInput");
inputElement.value = "New Value"; // Изменение свойства value
console.log(inputElement.getAttribute("value")); // Получение атрибута value

В данном случае, хотя свойство value изменено, атрибут value остается без изменений.

Что такое политика одного источника (Same Origin Policy)?

Политика одного источника (Same-Origin Policy) - это безопасностная политика, применяемая веб-браузерами для ограничения взаимодействия между веб-страницами или скриптами из разных источников (доменов). Она предотвращает скрипты с одного источника от доступа к данным или взаимодействия с ресурсами на другом источнике без явного разрешения.

Для того чтобы две веб-страницы были в рамках одного источника, они должны иметь одинаковый протокол (http, https), домен (например, www.example.com), и порт (если указан).

Пример:

Допустим, у вас есть веб-страница, загруженная с источника "https://www.example.com". Согласно политике одного источника, скрипты на этой странице не могут безопасно взаимодействовать с ресурсами (например, куки, localStorage) другой веб-страницы на источнике "https://www.anotherdomain.com", даже если обе страницы открыты в одном браузере.

// Это приведет к ошибке политики одного источника
const anotherDomainResponse = fetch("https://www.anotherdomain.com/api/data");

Однако, если сервер на источнике "https://www.anotherdomain.com" поддерживает механизмы, такие как "CORS" (Cross-Origin Resource Sharing), то можно настроить разрешения для взаимодействия между доменами.

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

Какова цель использования void 0 в JavaScript?

В JavaScript void - это оператор, который возвращает значение undefined для выражения, переданного ему. Использование void 0 является приемом, который используется для создания безопасной ссылки на undefined. Это может быть полезно в контексте избегания нежелательного переопределения глобальной переменной undefined.

Пример:

var undefined = "Это не undefined!";
console.log(undefined); // Выведет: "Это не undefined!"

var safeUndefined = void 0;
console.log(safeUndefined); // Выведет: undefined

В этом примере переменная undefined была переопределена. Однако, использование void 0 помогает получить настоящее значение undefined, независимо от переопределения переменной undefined. ⬆ Наверх

Является ли JavaScript компилируемым или интерпретируемым языком?

JavaScript является интерпретируемым языком программирования. Это означает, что код JavaScript выполняется непосредственно во время выполнения программы, без необходимости предварительной компиляции. Когда браузер (или другой исполнитель) встречает JavaScript-код, он интерпретирует его и выполняет соответствующие действия.

Однако с развитием технологий в JavaScript также начали использовать компиляцию. Например, современные движки JavaScript, такие как V8 (используемый в браузере Google Chrome), выполняют оптимизацию и компиляцию в машинный код, чтобы ускорить выполнение программ.

Пример:

function greet(name) {
  console.log("Привет, " + name + "!");
}

greet("Алексей");

В данном примере код JavaScript не компилируется в отдельный бинарный файл перед выполнением. Браузер (или движок JavaScript) интерпретирует этот код и выполняет функцию greet, выводя сообщение в консоль. ⬆ Наверх

Является ли JavaScript языком, чувствительным к регистру символов?

Да, JavaScript является языком, чувствительным к регистру символов. Это означает, что он различает между заглавными и строчными буквами и считает их разными символами.

Пример:

var myVariable = 10;
var MyVariable = 20;

console.log(myVariable); // Выведет: 10
console.log(MyVariable); // Выведет: 20

В этом примере две переменные myVariable и MyVariable считаются разными переменными из-за различия в регистре первой буквы. Если бы JavaScript был нерегистрозависимым, обе переменные были бы считаны как одна и та же переменная. ⬆ Наверх

Что такое события (events)?

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

Пример:

<button id="myButton">Нажми меня</button>

<script>
  const buttonElement = document.getElementById("myButton");

  // Добавляем обработчик события клика
  buttonElement.addEventListener("click", function () {
    alert("Кнопка была нажата!");
  });
</script>

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

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

About

400+ вопросов по JS для собеседования. Собеседование, JavaScript

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published