Всем привет! В этой статье хотел бы поделиться вопросами и ответами, которые я задаю на собеседованиях фронтенд-разработчикам и которые попадались мне, когда я сам искал работу. Здесь собраны вопросы именно по JavaScript. В дальнейшем планирую рассмотреть TypeScript отдельно, а также React и связанные с ним технологии.
Советую не заучивать их, а разобраться в каждом примере, так как все вопросы являются типовыми и могут встретиться только в другой формулировке. Если что-то не понятно, лучше посмотреть в документации, а не прочитать и забыть. Также рекомендую подписаться на мой канал, где я стараюсь выкладывать интересный материал, который также поможет вам при прохождении собеседования.
Стартуем! ????
1. Что такое цикл событий (event loop) и как он работает?
Цикл событий (event loop) - это механизм, используемый в JavaScript и других языках программирования для обработки событий и выполнения асинхронного кода. Он позволяет программе эффективно обрабатывать события, такие как пользовательские действия, таймеры, сетевые запросы и другие асинхронные операции.
Работа цикла событий в JavaScript обычно выглядит следующим образом:
Ожидание событий: Цикл событий начинает свою работу, ожидая возникновения событий. Это могут быть пользовательские действия (например, щелчки мыши или нажатия клавиш), таймеры, сетевые запросы или другие асинхронные операции.
Обработка событий: Когда событие происходит, оно помещается в очередь событий (event queue). Цикл событий извлекает событие из очереди и передает его на обработку.
Выполнение обработчиков событий: Цикл событий вызывает соответствующий обработчик события, который содержит код, который должен быть выполнен в ответ на событие. Обработчик выполняется синхронно, то есть блокирует выполнение других событий до завершения.
Обработка асинхронного кода: Если в обработчике события есть асинхронный код, такой как таймеры или сетевые запросы, он не блокирует выполнение других событий. Вместо этого асинхронный код помещается в очередь задач (task queue) для выполнения в будущем.
Возврат к ожиданию событий: После выполнения всех обработчиков событий и обработки асинхронного кода, цикл событий возвращается к ожиданию новых событий. Процесс повторяется, пока не будет завершена работа программы.
Цикл событий позволяет JavaScript выполнять асинхронный код без блокировки основного потока выполнения. Это позволяет создавать отзывчивые веб-приложения, которые могут обрабатывать пользовательские действия и одновременно выполнять другие задачи, такие как загрузка данных или анимации.
Еще можно почитать здесь.
2. Какие типы данных есть в JS?
Часто кандидаты ошибаются, когда отвечают на этот вопрос, почему так происходит не понятно.
Всего в JS 8 типов данных:
Число (number)
Строка (string)
Булевый (логический) тип (boolean)
BigInt
Symbol
null
undefiend
Object
3. Что такое NaN? Какого типа это значение? Как можно узнать, равно ли значение переменной NaN?
NaN расшифровывается как "Not A Number", это "false" (ложное) значение. Будьте аккуратны, выражение typeof NaN возвращает тип Number. Чтобы проверить значение переменной на соответствие NaN можно, воспользовавшись встроенным методом isNaN() или используя оператор тройного равенства ===.
let x = NaN;
console.log(isNaN(x)); // true
let y = 5 / "hello";
console.log(Number.isNaN(y)); // true
let z = 10;
console.log(isNaN(z)); // false
4. В чем разница между let, const и var?
Начнем с var
:
Переменные, объявленные с помощью
var
, имеют функциональную область видимости или область видимости внутри целого файла.Переменные
var
могут быть переопределены и переобъявлены в той же области видимости.-
Переменные
var
поднимаются (hoisted) в начало своей области видимости, что означает, что их можно использовать до их фактического объявления.Пример:
console.log(x); // undefined
var x = 5;
console.log(x); // 5
let
:
Переменные, объявленные с помощью
let
, имеют блочную область видимости, ограниченную фигурными скобками{}
.Переменные
let
не могут быть переобъявлены в той же области видимости, но могут быть переопределены.-
Переменные
let
не поднимаются (не hoisted) и не могут быть использованы до их объявления.Пример:
console.log(x); // ReferenceError: x is not defined
let x = 5;
console.log(x); // 5
const
:
Переменные, объявленные с помощью
const
, также имеют блочную область видимости.Переменные
const
должны быть инициализированы при объявлении и их значение не может быть изменено после этого.Переменные
const
не могут быть переобъявлены или переопределены.-
const
также создает неизменяемую ссылку на объект, поэтому значения внутри объекта могут быть изменены, но сама ссылка остается неизменной.Примеры:
const x = 5;
console.log(x); // 5
x = 10; // TypeError: Assignment to constant variable.
const a = [];
a.push(1); // Так можно
const b = {};
b['a'] = 1; // Так тоже можно
5. Что такое this? Отличие this в function declaration и стрелочных функциях
this
- это специальное ключевое слово в JavaScript, которое ссылается на объект, в контексте которого выполняется текущий код. Значение this
зависит от контекста вызова функции и может быть разным в различных ситуациях.
Функции (function declaration):
В функциях объявления значение
this
определяется во время выполнения функции, в зависимости от способа вызова функции.Если функция вызывается как метод объекта, то
this
ссылается на сам объект, на котором вызывается метод.-
Если функция вызывается как обычная функция, то
this
ссылается на глобальный объект (в браузере это объектwindow
).Пример:
function sayHello() {
console.log(this.name);
}
const person = {
name: 'John',
sayHello: sayHello
};
person.sayHello(); // Выводит 'John'
const greet = person.sayHello;
greet(); // Выводит undefined (или ошибку, если 'use strict' включен)
Стрелочные функции (arrow functions):
В стрелочных функциях значение
this
определяется лексически, оно берется из окружающего контекста, в котором функция была определена.Стрелочные функции не имеют своего собственного
this
, поэтому они не создают новый контекстthis
и не зависят от способа вызова.-
Вместо этого,
this
в стрелочных функциях ссылается наthis
окружающего контекста.Пример:
const person = {
name: 'John',
sayHello: function() {
const greet = () => {
console.log(this.name);
};
greet();
}
};
person.sayHello(); // Выводит 'John'
6. С помощью чего в JS реализуются наследование?
В JavaScript наследование реализуется с помощью прототипов. Прототипное наследование - это механизм, который позволяет объектам наследовать свойства и методы других объектов. Еще появился новый в ECMAScript 2015 с помощью ключевого слова class.
Каждый объект в JavaScript имеет внутреннюю ссылку на прототип (prototype), которая указывает на другой объект.
Существует несколько способов реализации наследования в JavaScript, рассмотрим их все.
Прототипное наследование с использованием prototype
:
Создается конструктор (функция-класс), у которого есть свойство
prototype
.Создаются новые объекты с помощью этого конструктора с помощью ключевого слова
new
.-
Прототип нового объекта устанавливается равным прототипу конструктора.
Пример:
function Animal(name) {
this.name = name;
}
Animal.prototype.sayHello = function() {
console.log('Hello, my name is ' + this.name);
};
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log('Woof!');
};
const myDog = new Dog('Buddy', 'Labrador');
myDog.sayHello(); // Выводит 'Hello, my name is Buddy'
myDog.bark(); // Выводит 'Woof!'
Наследование с использованием class
(введено в ECMAScript 2015):
Используется ключевое слово
class
для определения класса.Используется ключевое слово
extends
для указания родительского класса.-
Методы родительского класса могут быть переопределены или расширены в дочернем классе с помощью ключевого слова
super
.Пример
class Animal {
constructor(name) {
this.name = name;
}
sayHello() {
console.log('Hello, my name is ' + this.name);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
console.log('Woof!');
}
}
const myDog = new Dog('Buddy', 'Labrador');
myDog.sayHello(); // Выводит 'Hello, my name is Buddy'
myDog.bark(); // Выводит 'Woof!'
7. Что такое IIFE (Immediately Invoked Function Expression)?
IIFE (Immediately Invoked Function Expression) - это выражение функции, которое вызывается немедленно после его определения. Оно позволяет создавать локальную область видимости для переменных и функций, чтобы избежать конфликтов имен и сохранить приватность данных.
IIFE обычно используется для создания модулей, эмуляции блока кода с областью видимости или для выполнения некоторых инициализаций при загрузке страницы.
Пример IIFE:
(function() {
// Код, который будет выполнен немедленно
var x = 5;
console.log(x); // Выводит 5
})();
// Переменные и функции, определенные внутри IIFE, не видны в глобальной области видимости
console.log(x); // ReferenceError: x is not definedВ приведенном примере, функция обернута в круглые скобки (function() { ... }), чтобы превратить ее в выражение. Затем, после закрывающей скобки, добавляются еще одни круглые скобки () для вызова функции немедленно.
В приведенном примере, функция обернута в круглые скобки (function() { ... })
, чтобы превратить ее в выражение. Затем, после закрывающей скобки, добавляются еще одни круглые скобки ()
для вызова функции немедленно.
IIFE может принимать аргументы, например:
(function(name) {
console.log('Hello, ' + name);
})('John'); // Выводит 'Hello, John'
IIFE также может возвращать значение, которое может быть присвоено переменной:
var result = (function() {
return 5 + 3;
})();
console.log(result); // Выводит 8
Использование IIFE помогает изолировать код и предотвращает его влияние на глобальную область видимости, что способствует более безопасному и организованному коду.
8. В чем разница между == и ===?
В JavaScript операторы сравнения ==
(двойное равенство) и ===
(тройное равенство) используются для сравнения значений. Они имеют следующие различия:
==
(двойное равенство):
Оператор
==
выполняет нестрогое сравнение, сравнивая значения с приведением типов, если это необходимо.Если типы операндов различаются, JavaScript пытается привести их к одному типу перед сравнением.
-
Например, при сравнении числа и строки, строка будет преобразована в число перед сравнением.
Пример
console.log(5 == '5'); // true
console.log(true == 1); // true
console.log(null == undefined); // true
===
(тройное равенство):
Оператор
===
выполняет строгое сравнение, сравнивая значения без приведения типов.-
Он сравнивает значения и типы операндов, и возвращает
true
только если они идентичны.Пример:
console.log(5 === '5'); // false
console.log(true === 1); // false
console.log(null === undefined); // false
9. Что такое замыкание в JavaScript?
В JavaScript замыкание (closure) - это комбинация функции и лексического окружения, в котором эта функция была объявлена. Замыкание позволяет функции сохранять доступ к переменным из своего внешнего лексического окружения, даже после того, как это окружение было удалено.
Небольшие примеры:
function outerFunction() {
var outerVariable = 'Hello';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
var closure = outerFunction();
closure(); // Вывод: Hello
function createCounter() {
var count = 0;
return {
increment: function() {
count++;
console.log(count);
},
decrement: function() {
count--;
console.log(count);
}
};
}
var counter = createCounter();
counter.increment(); // Вывод: 1
counter.increment(); // Вывод: 2
counter.decrement(); // Вывод: 1
10. Что такое Promise, и какие бывают состояния
Promise - это объект в JavaScript, который представляет результат асинхронной операции. Промис позволяет обрабатывать результат операции, когда он станет доступным, вместо того, чтобы блокировать выполнение кода и ожидать завершения операции.
Промис может находиться в одном из трех состояний:
Pending: Исходное состояние промиса. Он находится в ожидании выполнения или отклонения операции.
Fulfilled: Промис переходит в это состояние, когда операция успешно завершается. В этом случае промис возвращает результат операции.
Rejected: Промис переходит в это состояние, когда операция завершается с ошибкой. В этом случае промис возвращает причину ошибки.
Пример использования промиса:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Some data';
// Имитация успешного выполнения операции
resolve(data);
// Имитация ошибки
// reject('Error occurred');
}, 2000);
});
}
fetchData()
.then(result => {
console.log('Результат:', result);
})
.catch(error => {
console.log('Ошибка:', error);
});
11. В чем разница и схожесть между null и undefined?
Null и undefined - это два различных значения в JavaScript, которые указывают на отсутствие значения.
Различия:
null
- это явное значение, которое указывает на отсутствие или намеренное присвоение пустого значения.undefined
- это значение, которое указывает на отсутствие присвоенного значения.null
- это объектный тип данных, который представляет отсутствие объекта.undefined
- это примитивный тип данных.null
может быть присвоен явно, чтобы указать на отсутствие значения.undefined
- это значение, которое присваивается переменной по умолчанию, когда она объявлена, но не инициализирована.
Сходства:
Осутствие значения: Оба значения,
null
иundefined
, указывают на отсутствие значения.Истинность: Оба значения рассматриваются как ложные (falsy) в логическом контексте. Это означает, что они преобразуются в
false
, когда используются в условных выражениях.Присваивание: Оба значения могут быть присвоены переменным или свойствам объекта.
Тип данных: Оба значения являются уникальными значениями и не имеют своих собственных типов данных.
В целом, null
используется, когда явно указывается отсутствие значения, в то время как undefined
указывает на отсутствие присвоенного значения.
12. Почему результатом сравнения двух похожих объектов является false?
Результатом сравнения двух похожих объектов в JavaScript может быть false
, потому что сравнение объектов происходит по ссылке, а не по содержимому.
Когда мы сравниваем два объекта, JavaScript проверяет, указывают ли оба операнда на один и тот же объект в памяти. Если это так, то результатом будет true
. Однако, если операнды указывают на разные объекты, даже если они имеют одинаковую структуру и значения свойств, результатом будет false
.
Пример:
const obj1 = { name: 'John', age: 25 };
const obj2 = { name: 'John', age: 25 };
console.log(obj1 === obj2); // Вывод: false
В этом примере obj1
и obj2
содержат одинаковые свойства и значения, но они являются разными объектами в памяти. Поэтому результатом сравнения obj1 === obj2
будет false
.
Если вам нужно сравнить содержимое двух объектов, вам придется реализовать собственную логику сравнения, перебирая свойства объектов и сравнивая их значения.
13. Для чего используется директива «use strict»?
Директива "use strict" используется в JavaScript для включения строгого режима выполнения кода. Когда эта директива указана в начале скрипта или функции, JavaScript выполняет код в строгом режиме, что означает, что некоторые неявные или устаревшие функции и конструкции языка будут запрещены или изменены, а некоторые ошибки будут вызывать исключения.
В основном используется для:
Предотвращение ошибок
Устранение неявных глобальных переменных
Запрет использования некоторых устаревших функций и конструкций
Улучшение безопасности
Примеры:
"use strict";
x = 10; // Ошибка: переменная "x" не была объявлена, если бы не было use strict создалась бы глобальная переменная
"use strict";
function sum(a, a, c) { // Ошибка: Повторное объявление параметра функции запрещено в строгом режиме
return a + a + c;
}
console.log(sum(1, 2, 3));
"use strict";
delete Object.prototype; // Ошибка: Удаление свойства объекта запрещено в строгом режиме
14. В чем разница между методами call, apply, bind?
Методы call
, apply
и bind
являются частью языка JavaScript и используются для управления контекстом выполнения функций. Вот их основные различия:
call
: Этот метод вызывает функцию с указанным контекстом и аргументами, переданными в виде отдельных аргументов. Синтаксис метода call
выглядит следующим образом: function.call(context, arg1, arg2, ...)
. При использовании call
аргументы передаются в виде списка, разделенного запятыми.
apply
: Этот метод вызывает функцию с указанным контекстом и аргументами, переданными в виде массива. Синтаксис метода apply
выглядит следующим образом: function.apply(context, [arg1, arg2, ...])
. При использовании apply
аргументы передаются в виде массива.
bind
: Этот метод создает новую функцию, привязанную к указанному контексту. Он не вызывает функцию немедленно, а возвращает новую функцию, которую можно вызвать позже. Синтаксис метода bind
выглядит следующим образом: function.bind(context)
. При использовании bind
контекст функции фиксируется, и при вызове новой функции этот контекст будет сохраняться.
Примеры:
const obj = {
name: 'John',
greet: function(message) {
console.log(`${message}, ${this.name}!`);
}
};
const otherObj = {
name: 'Jane'
};
// Использование метода call
obj.greet.call(otherObj, 'Hello'); // Вывод: Hello, Jane!
// Использование метода apply
obj.greet.apply(otherObj, ['Hi']); // Вывод: Hi, Jane!
// Использование метода bind
const boundGreet = obj.greet.bind(otherObj);
boundGreet('Hey'); // Вывод: Hey, Jane!
function sum(a, b) {
return a + b;
}
const numbers = [1, 2];
// Использование метода call с массивом аргументов
const result1 = sum.call(null, ...numbers);
console.log(result1); // Вывод: 3
// Использование метода apply с массивом аргументов
const result2 = sum.apply(null, numbers);
console.log(result2); // Вывод: 3
// Использование метода bind для создания каррированной функции
const addFive = sum.bind(null, 5);
const result3 = addFive(3);
console.log(result3); // Вывод: 8
15. Что такое функции высшего порядка?
Функции высшего порядка - это функции, которые могут принимать другие функции в качестве аргументов или возвращать функции в качестве результата. В JavaScript функции высшего порядка являются мощным инструментом, позволяющим создавать более гибкий и модульный код. Вот несколько примеров функций высшего порядка:
Функция обратного вызова (Callback): Функция, которая передается в качестве аргумента в другую функцию и вызывается внутри нее. Это позволяет передавать логику выполнения внутрь другой функции.
Пример:
function calculate(num1, num2, operation) {
return operation(num1, num2);
}
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
const result1 = calculate(5, 3, add); // Вызов функции calculate с функцией add
console.log(result1); // Вывод: 8
const result2 = calculate(5, 3, multiply); // Вызов функции calculate с функцией multiply
console.log(result2); // Вывод: 15
Функция обертка (Wrapper): Функция, которая принимает другую функцию и возвращает новую функцию, добавляя дополнительную логику или изменяя поведение оригинальной функции.
Пример:
function withLogging(func) {
return function(...args) {
console.log('Calling function:', func.name);
const result = func(...args);
console.log('Result:', result);
return result;
};
}
function multiply(a, b) {
return a * b;
}
const wrappedMultiply = withLogging(multiply);
const result = wrappedMultiply(5, 3);
console.log(result); // Вывод: 15
16. Как создать объект, не имеющий прототипа?
В JavaScript объекты обычно наследуют свойства и методы от своих прототипов. Однако, существует несколько способов создания объекта без прототипа:
Использование Object.create(null)
: Метод Object.create(null)
создает новый объект с указанным прототипом null
, что означает, что объект не будет наследовать свойства и методы от какого-либо прототипа.
Пример:
const obj = Object.create(null);
console.log(obj.toString); // Вывод: undefined
Использование литерала объекта и null
в качестве прототипа: Можно создать объект, используя литерал объекта и установив его прототип в null
.
Пример:
const obj = Object.setPrototypeOf({}, null);
console.log(obj.toString); // Вывод: undefined
Использование функции-конструктора без прототипа: Можно создать функцию-конструктор, которая не имеет прототипа, и создать объект с помощью этой функции.
Пример:
function NoPrototype() {
// Пустая функция-конструктор без прототипа
}
const obj = new NoPrototype();
console.log(obj.toString); // Вывод: undefined
Обратите внимание, что объекты без прототипа могут быть полезны в определенных случаях, но они также могут ограничивать функциональность и использование стандартных методов и свойств. Поэтому рекомендуется использовать объекты без прототипа с осторожностью и только в случаях, когда это действительно необходимо.
17. Что такое async/await?
async/await
- это синтаксический сахар в языке программирования, который позволяет писать асинхронный код в более понятном и линейном стиле. Он используется в языках, поддерживающих асинхронное программирование, таких как JavaScript, C#, Python и других.
Преимущества использования async/await
включают более простой и понятный синтаксис, отсутствие необходимости в явном использовании колбэков или цепочек промисов, а также возможность использования блоков try/catch
для обработки ошибок.
Примеры:
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.log('Ошибка:', error);
}
}
fetchData();
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function delayedFunction() {
console.log('Начало выполнения');
await delay(2000);
console.log('Задержка окончена');
}
delayedFunction();
const axios = require('axios');
async function fetchData() {
try {
const response = await axios.get('https://api.example.com/data');
const data = response.data;
console.log(data);
} catch (error) {
console.log('Ошибка:', error);
}
}
fetchData();
18. В чем разница между spread-оператором и rest-оператором?
Spread-оператор и rest-оператор - это два разных оператора, которые используются в JavaScript для работы с массивами и объектами.
Spread-оператор (...
):
Распространяет элементы массива или свойства объекта.
Используется для создания нового массива или объекта, содержащего элементы или свойства исходного массива или объекта.
-
Распаковывает элементы массива или свойства объекта, позволяя передавать их в другие функции или объединять с другими массивами или объектами.
Пример:
const numbers = [1, 2, 3];
const newArray = [...numbers, 4, 5]; // [1, 2, 3, 4, 5]
const person = { name: 'John', age: 30 };
const newPerson = { ...person, city: 'New York' }; // { name: 'John', age: 30, city: 'New York' }
Rest-оператор (...
):
Собирает оставшиеся аргументы функции в массив.
-
Используется для объявления параметра функции, который будет содержать все оставшиеся аргументы, переданные при вызове функции.
Пример:
function sum(...numbers) {
let total = 0;
for (let number of numbers) {
total += number;
}
return total;
}
console.log(sum(1, 2, 3, 4, 5)); // 15
function printNames(first, last, ...middle) {
console.log('First name:', first);
console.log('Last name:', last);
console.log('Middle names:', middle);
}
printNames('John', 'Doe', 'Smith', 'Johnson', 'Williams');
// First name: John
// Last name: Doe
// Middle names: ['Smith', 'Johnson', 'Williams']
19. Как определить наличие свойства в объекте?
В JavaScript есть несколько способов определить наличие свойства в объекте.
Оператор in
: Можно использовать оператор in
, чтобы проверить наличие свойства в объекте или его прототипе.
const obj = { name: 'John', age: 30 };
console.log('name' in obj); // true
console.log('city' in obj); // false
Метод hasOwnProperty()
: Метод hasOwnProperty()
проверяет, содержит ли объект указанное свойство и не учитывает свойства в прототипе объекта.
const obj = { name: 'John', age: 30 };
console.log(obj.hasOwnProperty('name')); // true
console.log(obj.hasOwnProperty('city')); // false
Сравнение со значением undefined
: Можно сравнить значение свойства с undefined
, чтобы определить его наличие.
const obj = { name: 'John', age: 30 };
console.log(obj.name !== undefined); // true
console.log(obj.city !== undefined); // false
Использование Object.keys()
: Можно использовать метод Object.keys()
для получения массива всех свойств объекта и затем проверить наличие свойства в этом массиве.
const obj = { name: 'John', age: 30 };
console.log(Object.keys(obj).includes('name')); // true
console.log(Object.keys(obj).includes('city')); // false
20. Чем отличается Map от WeakMap?
Map и WeakMap - это две разные структуры данных в JavaScript, которые предоставляют ассоциативное отображение ключей на значения.
Вот основные отличия между Map и WeakMap:
Сильные ссылки и сборка мусора: В Map используются сильные ссылки на ключи, что означает, что если объект, используемый в качестве ключа, больше не используется, он не будет удален из памяти, пока есть ссылка на него. В WeakMap используются слабые ссылки на ключи, что означает, что если объект, используемый в качестве ключа, больше не имеет других ссылок, кроме ссылки из WeakMap, он может быть удален сборщиком мусора.
Ключи: В Map ключами могут быть любые значения, включая примитивы и объекты. В WeakMap ключами могут быть только объекты.
Итерация: Map поддерживает итерацию с помощью методов
keys()
,values()
иentries()
, которые возвращают итераторы для перебора ключей, значений и пар ключ-значение соответственно. WeakMap не поддерживает эти методы, поскольку слабые ссылки могут быть непредсказуемыми и не гарантируют порядок итерации.Размер: Map имеет свойство
size
, которое возвращает количество элементов в Map. WeakMap не имеет свойстваsize
, поскольку слабые ссылки не позволяют точно определить количество элементов.Методы: Map предоставляет различные методы для работы с элементами, такие как
set()
,get()
,has()
,delete()
и другие. WeakMap предоставляет только методыget()
,set()
,has()
иdelete()
.В целом, Map обычно используется для обычных случаев ассоциативного отображения, когда ключи и значения должны оставаться в памяти, пока есть ссылки на них. WeakMap полезен, когда вам нужно ассоциативное отображение с объектами в качестве ключей, и вы хотите, чтобы объекты могли быть автоматически удалены из WeakMap, когда больше нет ссылок на них.
Еще можно почитать здесь и здесь.
21. Чем отличается Set от WeakSet?
Основное отличие между Set и WeakSet заключается в типе значений, которые они могут содержать, и в поведении при сборке мусора. Set может содержать любые значения и не удаляет их автоматически, а WeakSet может содержать только объекты и может быть автоматически очищен сборщиком мусора, если на объект больше нет ссылок.
Еще можно почитать здесь и здесь.
22. Как работает сборщик мусора в JS?
Сборщик мусора в JavaScript является встроенной функцией, которая автоматически освобождает память, занятую объектами, которые больше не используются в программе. Он следит за объектами, которые были созданы во время выполнения программы, и определяет, когда они больше не доступны для использования.
Сборщик мусора в JS использует алгоритм под названием "Mark and Sweep" (Пометка и Очистка). Вот как это работает:
Пометка (Mark): Сборщик мусора начинает с корневых объектов, таких как глобальный объект (window в браузере) и все объекты, на которые есть ссылки из корневых объектов. Он помечает эти объекты как активные.
Распространение (Propagation): Сборщик мусора рекурсивно проходит через все активные объекты и помечает объекты, на которые они ссылаются, как активные. Этот процесс продолжается до тех пор, пока все достижимые объекты не будут помечены.
Очистка (Sweep): После завершения пометки и распространения, сборщик мусора проходит по всей памяти и освобождает память, занятую не помеченными объектами. Он удаляет эти объекты и восстанавливает память для будущего использования.
Еще можно почитать здесь и здесь.
Также есть вопросы, которые не относятся напрямую к JavaScript, но я всегда задаю их, чтобы проверить кандидата на common knowledge.
1. Расскажите как работает браузер?
Браузер - это программное обеспечение, которое позволяет пользователям просматривать и взаимодействовать с веб-страницами. Вот основные шаги, которые браузер выполняет для отображения веб-страницы:
Ввод URL: Пользователь вводит URL (Uniform Resource Locator) в адресную строку браузера. URL указывает на веб-страницы, которую пользователь хочет посетить.
DNS-запрос: Браузер отправляет DNS-запрос (Domain Name System) на DNS-сервер, чтобы получить IP-адрес сервера, на котором хранится веб-страница. DNS-сервер преобразует доменное имя (например, www.example.com) в соответствующий IP-адрес.
Установка соединения: Браузер устанавливает TCP-соединение с сервером, используя полученный IP-адрес. Это позволяет браузеру отправлять и получать данные от сервера.
Запрос страницы: Браузер отправляет HTTP-запрос (Hypertext Transfer Protocol) на сервер, запрашивая веб-страницу. Запрос может содержать различные параметры, такие как метод запроса (GET, POST и т. д.), заголовки и тело запроса.
Получение ответа: Сервер обрабатывает запрос и отправляет обратно HTTP-ответ, содержащий запрошенную веб-страницу. Ответ может также содержать различные заголовки, статус ответа и тело ответа.
Рендеринг страницы: Браузер получает ответ от сервера и начинает обрабатывать его. Он анализирует HTML-код страницы, строит DOM (Document Object Model) - внутреннее представление страницы, и создает дерево элементов.
Загрузка ресурсов: Браузер загружает все связанные ресурсы, такие как изображения, стили CSS, скрипты JavaScript и другие файлы, указанные в HTML-коде страницы.
Отображение страницы: Браузер использует полученные ресурсы и информацию о стилях для отображения страницы на экране. Он располагает элементы в соответствии с их CSS-свойствами, применяет шрифты, цвета и другие стили, и отображает содержимое страницы.
2. Что такое DOM
DOM (Document Object Model) - это программное представление веб-страницы или XML-документа в виде древовидной структуры. DOM представляет каждый элемент документа (такие как теги, текстовые блоки, атрибуты) в виде объектов, которые можно манипулировать с помощью языков программирования, таких как JavaScript.
В JS DOM представлен объектом Document. DOM предоставляет стандартизированый способ доступа и изменения содержимого, структуры и стилей веб-страницы. Он позволяет программистам создавать динамические и интерактивные веб-приложения, изменять содержимое страницы, добавлять или удалять элементы, изменять атрибуты и стили, а также реагировать на события, такие как щелчки мыши или нажатия клавиш.
3. Из чего состоит HTTP запрос
На этот вопрос можно ответить так:
Метод запроса (Request Method): Определяет тип операции, которую клиент хочет выполнить на сервере. Некоторые распространенные методы запроса включают GET, POST, PUT, DELETE и HEAD.
Заголовки (Headers): Представляют собой метаданные, которые передаются вместе с запросом и содержат дополнительную информацию о запросе, такую как тип содержимого, аутентификация, кеширование и другие параметры.
Тело запроса (Request Body): Используется только в некоторых методах запроса, таких как POST или PUT. Оно содержит данные, которые клиент отправляет на сервер, например, форму для отправки или JSON-объект.
4. Что такое специфичность в CSS
Специфичность в CSS определяет, какой стиль будет применен к элементу, когда есть несколько правил, которые могут быть применены к нему. Это позволяет браузеру определить, какое правило имеет больший приоритет и должно быть применено.
Приоритет такой: инлайн стили, селектор ид, селектор класса, селектор тега.
Если два правила имеют одинаковую специфичность, то последнее правило в таблице стилей будет применено.
5. Разница между cookie, sessionStorage и localStorage
Веб-браузеры предоставляют несколько способов хранения данных на стороне клиента, таких как cookie, sessionStorage и localStorage.
Cookie:
Cookie - это небольшие текстовые файлы, которые хранятся на компьютере пользователя.
Cookie создаются сервером и отправляются в браузер, где они хранятся и отправляются обратно на сервер при каждом запросе.
Cookie имеют ограничение по размеру (обычно до 4 КБ) и количество (обычно до 20).
Cookie могут иметь срок годности, после которого они автоматически удаляются.
Cookie могут быть доступны как на сервере, так и на клиенте.
Cookie могут использоваться для хранения информации, такой как предпочтения пользователя, данные аутентификации и отслеживание состояния сеанса.
sessionStorage:
sessionStorage - это механизм хранения данных, доступный только в рамках одной вкладки браузера.
Данные, сохраненные в sessionStorage, остаются доступными только во время сеанса работы с текущей вкладкой браузера. При закрытии вкладки данные удаляются.
sessionStorage имеет ограничение по размеру (обычно до 5 МБ).
sessionStorage может использоваться для временного хранения данных, таких как состояние формы или временные настройки.
localStorage:
localStorage - это механизм хранения данных, доступный в рамках одного домена.
Данные, сохраненные в localStorage, остаются доступными даже после закрытия браузера и перезапуска компьютера.
localStorage имеет ограничение по размеру (обычно до 5 МБ).
localStorage может использоваться для хранения постоянных данных, таких как настройки пользователя или кэшированные данные.
Конечно, это не все вопросы, которые могут быть заданы на реальном собеседовании, но они покрывают около 70% технической части. Желаю удачи!
Комментарии (21)
yudeek
04.01.2024 07:23+2Интересная подборка, но есть одно но. Что мы видим:
Общие вопросы, которые тупо заучиваешь перед собеседованием. React разрабы прям сидят и call, apply, bind применяют с утра до вечера, или думают о том, как создать объект без прототипа. Ну и про GC прям самое насущное, куда без этого для формочек.
Хорошие теоретические вопросы на понимание работы WEB-платформы. Специфичность CSS, critical rendering path и т.д. Чтобы внятно на них ответить, надо прилично покапаться в спеках. При всем уважении к ответам автора, но у меня ответ на то, как работает браузер от запроса до отображения, занял 6 часов обзорной лекции от OSI модели до Resource Timing API.
А где вопросы про опыт? Или вдруг опыт в таком ремесле как разработка стал не важен? Про то, какие frontend-разработчик применял WEB API, какие проблемы есть в используемых им либах, как он организует архитектуру взаимодействия между компонентами. Про новинки того же HTML или CSS, которые он пробовал в коде (привет всем, кто модалки в 2024 пилит дивами, а для стилей использует SASS/SCSS).
Делаю вывод о том, что найм за последние 5-7 лет нисколько не изменился. Наивно полагать, что предложенная схема позволит понять реальный опыт соискателя и его способность к закрытию именно ваших задачек.
feverus
04.01.2024 07:23+1Это не подборка, а ответ чатгпт на промт "у меня собеседование через 5 минут, накидай мне вопросов для вротендера" ))
Ответ на знание ивентлупа проверяет только способность соискателя в стрессовой обстановке рассказать зазубренный текст. Интервьюер же сам работает, так пусть спросит свою последнюю рабочую задачу и посмотрит, как соискатель её решит. Нет, мы продолжим задавать одни и те же бесполезные вопросы.
8. В чем разница между == и ===?
В том, что == мне линтер подчеркнет и я заменю на === ?
altrapeznikov Автор
04.01.2024 07:23-1Нет, это не ответ чатгпт, а GigaChat знаете такой?) Если нет, вот ссылочка https://developers.sber.ru/gigachat/login
feverus
04.01.2024 07:23+1Чатгпт уже стало именем нарицательным, как ксерокс. Вот лучше бы спросили соискателя, пробовал ли он использовать ии в работе, чем типы данных.
yudeek
04.01.2024 07:23Сам спрашиваю про три примера задач в текущем спринте на собесах со стороны соискателя и рассказываю о них со стороны нанимателя. Очень проясняет картину.
Tarasov-Front-Dev
04.01.2024 07:23+3А в чем проблема с SASS/SCSS?
yudeek
04.01.2024 07:23А зачем он сейчас?
IgorAlentyev
04.01.2024 07:23Затем что та же вложенность в нативном не везде работает
yudeek
04.01.2024 07:23-1Да и нативная вложенность не сильно нужна, сколько там проблем с синтаксисом было на стадии обсуждения. По мне, препроцессоры свое отжили, современным CSS можно без магии и дополнительных зависимостей решать все задачи. Сахарок, конечно, приятно, но сильно ли нужно?
kirillbelash93
04.01.2024 07:23+2А вопрос про типы данных это для джуна? А то на собесах на мидла нет нет да и попадаются додики которые спрашивают этот вопрос, нажуя? нет ответа..
yudeek
04.01.2024 07:23+1а вдруг ты читал спеку и ответил, что в JS есть типы значений, а не переменных. и что при const a = 10, у а есть метод .toString()
ivaniksanov
04.01.2024 07:23Очень хорошая подборка вопросов. Спасибо автору! Не хватало такой шпаргалки для подготовки к собесу :)
n0ne
04.01.2024 07:23+1Ну вообще-то let и const тоже поднимаются (hoisted), только вот TDZ. Зачем Вы вводите людей в заблуждение?!
Arty_gvozd
04.01.2024 07:23+1Технически, TDZ такого понятия в спеках EcmaScript нет. Как и hoisted. Есть Hoistable declaration, но это относится только к функциям и генераторам. Let и const относятся к lexical declaration и для их обработки перед стартом выполнения кода сначала проходит целая пачка проверок на стадии Static semantics, где как раз проверяется, нет ли дублирования декларирования внутри одного блока.
А хостинг/всплытие (так называемые) это всего лишь документированный алгоритм выполнения кода. Когда перед стартом собираются все объявленные идентификаторы для всех окружений и проверяется let/const на стадии Static semantics, var никак не проверяется, регулярные функции как раз типа всплывают, что значит, что их идентификаторы собраны до старта кода и они могут быть использованы до того, как они технически определены в коде
dopusteam
Вы уверены, что === сработает для сравнения с NaN?
Alexandroppolus
Наверно, имелось в виду, что x===x вернёт false, если NaN
altrapeznikov Автор
Именно!
HomoHikka