Сегодня я поделюсь с вами некоторыми важными вопросами на собеседовании по JavaScript для младших веб-разработчиков. Давайте начнем.

Какой тип языка - это JavaScript?

Отвечать:

JavasScript - это однопоточный функциональный язык программирования.

Javascript синхронный или асинхронный?

Отвечать:

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

Есть ли разница между окном и документом?

Отвечать:

да. У JavaScript есть глобальный объект, и все работает под ним. window - это тот глобальный объект, который содержит глобальные переменные, глобальные функции, местоположение, историю - все, что находится под ним. Кроме того, setTimeout, вызов ajax (XMLHttpRequest), консоль или localStorage являются частью окна.

документ также находится под окном. документ - это свойство объекта окна. document представляет DOM, а DOM - объектно-ориентированное представление написанной нами разметки html. Все узлы являются частью документа. Следовательно, мы можем использовать getElementById или addEventListener в документе. Эти методы отсутствуют в оконном объекте.

Срабатывают ли одновременно document.onload и window.onload?

Отвечать:

window.onload запускается, когда DOM готов и все содержимое, включая изображения, CSS, скрипты, подкадры и т. Д., Загружено. Значит, все загружено.

document.onload запускается, когда DOM (дерево DOM, построенное из кода разметки в документе) готово, что может быть до загрузки изображений и другого внешнего контента.

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

Отвечать:

undefined означает, что переменная была объявлена, но ей еще не было присвоено значение. С другой стороны, null - это значение присваивания. Его можно присвоить переменной как представление отсутствия значения.

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

Отвечать:

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

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

Атрибут похож на свойство?

Отвечать:

Атрибуты аналогичны атрибутам в нашем теге HTML (атрибут стиля XML) внутри начального тега. Атрибуты html доступны в DOM через свойство. Следовательно, свойство создается, когда DOM анализируется для каждого атрибута в теге html. Если мы изменим атрибут, изменится только значение свойства. Однако значение атрибута останется прежним.

Как бы вы сравнили два объекта в JavaScript?

Отвечать:

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

Как можно использовать Math.max для нахождения максимального значения в массиве?

Отвечать:

Мы можем использовать apply в Math.max и передать массив, поскольку apply принимает массив аргументов. Поскольку мы ничего из этого не читаем и не используем вообще. Мы можем просто передать null в качестве первого параметра.

function getMax(arr){
  return Math.max.apply(null, arr);  
}

Какими способами можно получить элемент из DOM?

Отвечать:

Мы можем использовать следующие методы в document

  • getElementById, чтобы получить элемент с предоставленным идентификатором.
  • getElementsByClassName, чтобы получить список узлов (список узлов не является массивом, это скорее объект, подобный массиву), указав имя класса.
  • getElementsByTagName, чтобы получить список узлов по указанному имени тега.
  • querySelector мы передадим селектор стиля css (стиль jquery), и он вернет первый совпавший элемент в DOM.
  • querySelectorAll вернет неактивный нодлист, используя предварительный обход всех согласованных элементов в глубину. Неактивный означает, что любые изменения после выбора элементов не будут отражены.

Есть еще два варианта, но мы не используем их часто -

  • getElementsByName возвращает список элементов по указанному имени тега html
  • getElementsByTagNameNS возвращает элементы с определенным именем тега в предоставленном пространстве имен

Каков самый быстрый способ выбора элементов с помощью селекторов CSS?

Отвечать:

Это зависит от того, что мы выбираем. Если у нас есть идентификатор элемента, getElmentById - это самый быстрый способ выбрать элемент. Однако у нас не должно быть так много идентификаторов в нашем документе, чтобы избежать повторения стилей. css class getElementsByClassName - второй самый быстрый способ выбрать элемент

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

  • ID (#myID)
  • Класс (.myClass)
  • Тег (div, p)
  • Брат (div + p, div ~ p)
  • ребенок (div ›p)
  • Потомок (div p)
  • Универсальный (*)
  • Атрибут (input [type = ”checkbox”])
  • Псевдо (р: первенец)

Что оценивает typeof a и typeof b в следующем фрагменте:

function foo() {
  let a = b = 0;
  a++;
  return a;
}
foo();
typeof a; // => ???typeof b; // => ???

Отвечать:

В строке 2: let a = b = 0. Этот оператор объявляет локальную переменную a. Однако он объявляет глобальную переменную b.

Переменная b не объявляется ни в foo() области, ни в глобальной области. Таким образом, JavaScript интерпретирует выражение b = 0 как window.b = 0.

Другими словами, b - это глобальная переменная, созданная случайно.

В браузере приведенный выше фрагмент кода эквивалентен:

function foo() {
  let a;  window.b = 0;  a = window.b;  a++;
  return a;
}
foo();
typeof a;        // => 'undefined'
typeof window.b; // => 'number'

typeof a это 'undefined'. Переменная a существует в foo() области и недоступна во внешней области.

Поскольку b - глобальная переменная со значением 0, typeof b оценивается как 'number'.

Какое значение clothes[0]:

const clothes = ['jacket', 't-shirt'];
clothes.length = 0;
clothes[0]; // => ???

Отвечать:

length объекта массива имеет особое поведение:

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

В результате, когда JavaScript выполняет clothes.length = 0, все clothes элементы удаляются.

clothes[0] равно undefined, потому что массив clothes опустошен.

Каково содержимое массива numbers:

const length = 4;
const numbers = [];
for (var i = 0; i < length; i++);{
  numbers.push(i + 1);
}
numbers; // => ???

Отвечать:

Давайте подробнее рассмотрим точку с запятой ;, которая появляется прямо перед открывающей фигурной скобкой {:

Эта точка с запятой, которую легко не заметить, создает нулевой оператор. Нулевой оператор - это пустой оператор, который ничего не делает.

for() 4 раза повторяет нулевой оператор (который ничего не делает), игнорируя блок, который фактически отправляет элементы в массив: { numbers.push(i + 1); }.

Приведенный выше код эквивалентен следующему:

const length = 4;
const numbers = [];
var i;
for (i = 0; i < length; i++) {
  // does nothing
}
{ 
  // a simple block
  numbers.push(i + 1);
}
numbers; // => [5]

for() увеличивает переменную i до 4. Затем JavaScript входит один раз в блок { numbers.push(i + 1); }, помещая 4 + 1 в массив numbers.

Таким образом, numbers это [5].

Какое значение возвращает arrayFromValue()?

function arrayFromValue(item) {
  return
    [item];
}
arrayFromValue(10); // => ???

Отвечать:

Легко пропустить новую строку между return ключевым словом и [item] выражением.

Однако эта новая строка заставляет JavaScript автоматически вставлять точку с запятой между return и [item] выражением.

Вот эквивалентный код с точкой с запятой, вставленной после return:

function arrayFromValue(item) {
  return;  [item];
}
arrayFromValue(10); // => undefined

return; внутри функции заставляет возвращать undefined.

Итак, arrayFromValue(10) оценивается как undefined.

Что будет выводить на консоль следующий код:

let i;
for (i = 0; i < 3; i++) {
  const log = () => {
    console.log(i);  }
  setTimeout(log, 100);
}

Отвечать:

Выполнение этого фрагмента состоит из 2 этапов.

Этап 1

  1. for() повторяется 3 раза. Во время каждой итерации создается новая функция log(), которая захватывает переменную i. Затем setTimout() планирует выполнение log().
  2. Когда цикл for() завершается, переменная i принимает значение 3.

log() - это замыкание, которое захватывает переменную i, которая определена вне области for() цикла. Важно понимать, что замыкание захватывает i переменную лексически.

Этап 2

Вторая фаза происходит через 100 мс:

  1. 3 запланированных log() обратных вызова вызываются setTimeout(). log() считывает текущее значение переменной i, равное 3, и записывает в консоль 3.

Вот почему на консоль выводятся 3, 3 и 3.

Каков результат проверки на равенство?

0.1 + 0.2 === 0.3 // => ???

Отвечать:

Во-первых, давайте посмотрим на значение 0.1 + 0.2:

0.1 + 0.2; // => 0.30000000000000004

Сумма чисел 0.1 и 0.2 не совсем 0.3, но немного больше 0.3.

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

Проще говоря, прямое сравнение поплавков неточно.

Таким образом, 0.1 + 0.2 === 0.3 это false.

В каком порядке числа 1–4 будут записаны в консоль при выполнении приведенного ниже кода? Почему?

(function() {
    console.log(1); 
    setTimeout(function(){console.log(2)}, 1000); 
    setTimeout(function(){console.log(3)}, 0); 
    console.log(4);
})();

Отвечать:

Значения будут регистрироваться в следующем порядке:

1
4
3
2

Давайте сначала объясним части этого, которые, по-видимому, более очевидны:

  • 1 и 4 отображаются первыми, поскольку они регистрируются простыми вызовами console.log() без какой-либо задержки.
  • 2 отображается после 3, потому что 2 регистрируется после задержки в 1000 мс (т. Е. 1 секунда), тогда как 3 регистрируется после задержки в 0 мс.

Хорошо. Но если 3 регистрируется с задержкой в ​​0 мсек, не означает ли это, что запись выполняется сразу же? И если да, то не следует ли это записывать раньше 4, поскольку 4 регистрируется более поздней строкой кода?

Ответ связан с правильным пониманием событий и времени JavaScript.

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

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

Когда нулевое значение передается в качестве второго аргумента setTimeout(), он пытается выполнить указанную функцию «как можно скорее». В частности, выполнение функции помещается в очередь событий для следующего тика таймера. Однако обратите внимание, что это происходит не сразу; функция не выполняется до следующего тика. Вот почему в приведенном выше примере вызов console.log(4) происходит до вызова console.log(3) (поскольку вызов console.log(3) вызывается через setTimeout, поэтому он немного задерживается).

Как бы вы реализовали каррирование для любых функций?

Отвечать:

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

  • Шаг 1. Объедините старые аргументы (предоставленные при создании карри) с новыми аргументами (добавленными после небольшого приготовления) с помощью args.concat(toArray(arguments))
  • Шаг 2. Передайте все аргументы функции с помощью apply.
  • Дополнительно: только будьте осторожны, чтобы сохранить ценность этого.
Function.prototype.curry = function() {
    if (arguments.length<1) {
        return this; //nothing to curry. return function
    }
    var self = this;
    var args = toArray(arguments);
    return function() {
        return self.apply(this, args.concat(toArray(arguments)));
    }
}
function toArray(args) {
    return Array.prototype.slice.call(args);
}

Чтобы использовать его: просто передайте аргумент методу function.curry, и функция будет возвращена. Используйте возвращенную функцию для дальнейшего каррирования

function converter = function(factor, symbol, input){
  return input * factor + symbol;
}
var milesToKm = converter.curry(1.62, 'km');
mileToKm(3); //result here
var kgToLb = converter.curry(2.2, 'lb');
kgToLb(3); //result here

Почему мы не можем использовать forEach или аналогичные методы массива в NodeList?

Отвечать:

И array, и nodeList имеют длину, и мы можем перебирать элементы, но они не являются одним и тем же объектом.

Оба унаследованы от Object. Однако массив имеет другой объект-прототип, чем nodeList. forEach, map и т. д. находятся в array.prototype, которого нет в объекте NodeList.prototype. Следовательно, у нас нет forEach в списке узлов

myArray --> Array.prototype --> Object.prototype --> null
myNodeList --> NodeList.prototype --> Object.prototype --> null

Это все на сегодня. Спасибо.