Вопросы для интервью по JavaScript для начинающих: примеры кода по определению области видимости переменных». — ЧАСТЬ 1

Что такое JavaScript?

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

Фрагменты кода JavaScript с пояснениями:

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

Объяснение и выделенные функции JavaScript:

  • Самозапускающаяся функция. Код начинается с немедленно вызываемого функционального выражения (IIFE), заключенного в круглые скобки (function(){ ... })(). Эта структура допускает инкапсуляцию и предотвращает переменное загрязнение в глобальной области видимости.
  • Асинхронные операции с setTimeout: setTimeout(() => console.log(1), 2000);: Эта строка планирует выполнение функции обратного вызова после задержки в 2000 миллисекунд (2 секунды). Он демонстрирует асинхронное поведение, поскольку не блокирует выполнение остальной части кода.
  • setTimeout(() => console.log(3), 0);: Здесь функция обратного вызова запланирована с задержкой 0 миллисекунд. Это интересно, потому что даже при задержке, равной 0, не гарантируется немедленное выполнение из-за механизма цикла событий JavaScript.
  • Порядок выполнения: console.log(2); и console.log(4); являются синхронными операциями, поэтому они выполняются немедленно при обнаружении в коде.
  • console.log(2) и console.log(4) выводят значения 2 и 4 соответственно, и они регистрируются перед асинхронными операциями.
  • На первый взгляд порядок выполнения может показаться интуитивным, но асинхронность, введенная setTimeout, приводит к другому порядку протоколирования.

Порядок вывода консоли:

  1. 2 регистрируется немедленно, поскольку это синхронная операция.
  2. 4 также немедленно регистрируется по той же причине.
  3. 3 регистрируется раньше 1, хотя у него более короткий тайм-аут, поскольку он запланирован в другой «задаче» внутри цикла событий.
  4. Наконец, после задержки в 2 секунды записывается 1.

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

function ¸() {
  for (var i = 0; i < 3; i++) {
    console.log(i);
  }
  console.log(i);
}
dummy()

Объяснение и выделенные функции JavaScript:

  • Код определяет функцию JavaScript с именем dummy. Функции в JavaScript — это повторно используемые блоки кода.
  • Цикл for:Внутри функции dummy есть цикл for. Этот цикл используется для многократного выполнения блока кода.
  • Область переменной: Переменная цикла i объявлена ​​с использованием var, что означает, что она имеет область действия на уровне функции. Это означает, что i доступен как внутри, так и вне цикла внутри функции dummy.
0
1
2
3
  • Цикл выполняется, пока i меньше 3, поэтому регистрируются 0, 1 и 2.
  • После выхода из цикла строка console.log(i); вне цикла пытается записать значение i. Поскольку i было объявлено с помощью var, оно все еще существует в области действия функции, и его значение остается 3 с последней итерации.

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

function dummy() {
  for (let i = 0; i < 3; i++) {
    console.log(i);
  }
  console.log(i);
}

Выход

0
1
2
Uncaught ReferenceError: i is not defined

Объяснение:

  • Цикл работает как положено, регистрируя 0, 1 и 2 во время трех итераций.
  • После выхода из цикла строка console.log(i); пытается записать значение i. Однако на этот раз результат ReferenceError. Это связано с тем, что i имеет блочную область действия из-за использования let и недоступен за пределами блока цикла.

Ключевой вывод

Использование let в этом коде вводит область действия на уровне блока для переменной цикла i, предотвращая доступ к ней вне цикла. Это существенное отличие от предыдущего фрагмента кода, где var предоставлял область действия на уровне функции. Понимание области видимости переменных имеет решающее значение в JavaScript, особенно при работе с циклами и переменными уровня блока.

function dummy() {
  for (var i = 0; i < 3; i++) {
    setTimeout(function() {
      console.log(i);
    });
  }
  console.log(i);
}

Циклическое выполнение:

Цикл for выполняется три раза, увеличивая i с 0 до 2. Однако важно отметить, что функция setTimeout планирует выполнение анонимной функции, но не выполняет ее немедленно. Вместо этого он переходит к следующей итерации цикла.

Консольный вывод:

Когда вызывается функция dummy, она выдает следующий результат:

3
3
3

Объяснение:

  • Цикл выполняется три раза, каждый раз увеличивая i.
  • Функция setTimeout вызывается в цикле три раза, каждый раз планируя выполнение анонимной функции.
  • После выхода из цикла выполняется строка console.log(i);. Поскольку i объявлен с помощью var, он имеет область действия на уровне функции и сохраняет свое окончательное значение 3 с последней итерации цикла. В результате 3 регистрируется три раза.

Ключевой вывод:

Поведение setTimeout в сочетании с функциональной областью действия var может привести к неожиданным результатам. В этом примере все три запланированных оператора console.log внутри функций setTimeout печатают 3, поскольку они ссылаются на одну и ту же переменную i. Понимание замыканий и области видимости в JavaScript необходимо для эффективной работы с асинхронным кодом.

function dummy(){
 for(let i=0;i<3;i++){
  setTimeout(function()=>{
   console.log(i);
  })  
 }
 console.log(i);
}

Циклическое выполнение:

Цикл for выполняется три раза, увеличивая i с 0 до 2. Каждая итерация планирует функцию setTimeout с анонимной стрелочной функцией.

Консольный вывод:

Когда вызывается функция dummy, она выдает следующий результат:

0
1
2
3

Объяснение:

  • Цикл выполняется три раза, и во время каждой итерации он планирует функцию setTimeout, которая записывает значение i. Поскольку i имеет блочную область действия let, каждая анонимная стрелочная функция «фиксирует» значение i в момент ее создания.
  • После планирования функций setTimeout цикл завершается и выполняется строка console.log(i);. i по-прежнему доступен здесь и имеет значение 3, потому что это значение было i после завершения цикла.

Ключевой вывод:

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

function sayHi() {
  console.log(name);
  console.log(age);
  var name = 'Nick';
  let age = 21;
}

sayHi();

Консольный вывод

undefined
21

Объяснение:

  • Оператор console.log(name); регистрирует undefined для name, поскольку переменная name объявлена ​​с использованием var. Переменные, объявленные с помощью var, поднимаются, что означает, что они перемещаются в начало содержащей их функции или блока на этапе компиляции. Однако поднимается только объявление, а не инициализация. Итак, name объявлен, но ему еще не присвоено значение при выполнении console.log(name);.
  • Оператор console.log(age); регистрирует 21 для age, поскольку объявления let также поднимаются, но не инициализируются до того момента в коде, где они объявлены. В этом случае age объявляется и инициализируется значением 21 в том же операторе, поэтому он доступен и сохраняет правильное значение при выполнении console.log(age);.

Ключевой вывод:

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

(function() {
   var a = b = 5;
})();
console.log(b);

Выражение функции с немедленным вызовом (IIFE):Код начинается с выражения функции с немедленным вызовом (IIFE), заключенного в круглые скобки (function() { ... })();. IIFE — это способ создать функцию и немедленно выполнить ее.

Область действия и назначение переменной:

Когда var a = b = 5; выполняется, происходит следующее:

  • var a правильно объявлен и ему присвоено значение 5 в области действия функции.
  • b = 5 присваивает значение 5 переменной b. Однако, поскольку b объявлено без var или let, оно становится неявной глобальной переменной (т. е. становится свойством глобального объекта, обычно window в браузере).

Выход:

5

Объяснение:

  • Оператор console.log(b); регистрирует 5, поскольку b стала глобальной переменной из-за отсутствия var или let в ее объявлении в IIFE.
  • Значение 5, присвоенное b в IIFE, доступно в глобальной области, поэтому его можно зарегистрировать за пределами IIFE.

Важная заметка:

Хотя этот код работает так, как описано, обычно считается хорошей практикой явно объявлять переменные с использованием var, let или const, чтобы избежать непреднамеренного создания глобальных переменных. В этом случае использование var a = 5; var b = 5; в IIFE не позволило бы b стать глобальной переменной.

(function() {
   'use strict';
   var a = window.b = 5;
})();
console.log(b);

Строгий режим: строка 'use strict'; помещается в начало IIFE. Это активирует строгий режим для кода в IIFE. Строгий режим — это набор правил, которые делают JavaScript менее подверженным ошибкам и более безопасным.

Область действия и назначение переменной:

Когда var a = window.b = 5; выполняется:

  • var a правильно объявлен в области действия функции, и ему присвоено значение 5.
  • window.b = 5 присваивает значение 5 переменной b. Однако на этот раз он явно устанавливает b как свойство объекта window. Это делает b глобальной переменной, доступной как window.b.

Выход

5

Объяснение:

  • Инструкция console.log(b); регистрирует 5, поскольку b была явно назначена как глобальная переменная, прикрепленная к объекту window в IIFE.
  • Благодаря строгому режиму код ведет себя так, как задумано, без создания каких-либо непреднамеренных глобальных переменных.

Важная заметка:

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

function test() {
   console.log(a);
   console.log(foo());
   
   var a = 1;
   function foo() {
      return 2;
   }
}
test();
  • var a = 1;: Эта строка объявляет переменную a с использованием ключевого слова var и присваивает ей значение 1. Переменные, объявленные с помощью var, имеют область действия функции.
  • function foo() { return 2; }: Эта строка объявляет функцию с именем foo с использованием ключевого слова function. Объявления функций также поднимаются, поэтому функция доступна для использования во всей области действия функции.

Выполнение кода:

Теперь давайте посмотрим, как выполняется код:

  • console.log(a);: Эта строка пытается записать значение a на консоль до того, как ему будет присвоено значение. Поскольку объявления var подняты, a объявлен, но на данный момент еще не инициализирован. Итак, a — это undefined.
  • console.log(foo());: Эта строка вызывает функцию foo и пытается зарегистрировать ее возвращаемое значение. Функция foo возвращает 2, поэтому 2 записывается в консоль.
undefined
2

Объяснение:

  • Первый оператор console.log(a); регистрирует undefined, поскольку a объявлен с var и поднят, но еще не инициализирован.
  • Второй оператор console.log(foo()); регистрирует 2, поскольку вызывается функция foo и возвращает 2.

Ключевой вывод:

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

Вывод:

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

  1. Понимание областей действия. JavaScript имеет области действия на уровне функций и на уровне блоков. Переменные, объявленные с помощью var, имеют область действия на уровне функции, а let и const представляют область действия на уровне блока. Помните о том, как область видимости переменных влияет на ваш код.
  2. Подъем. JavaScript поднимает объявления переменных и функций в начало области их содержания. Такое поведение может привести к неожиданностям, если вы не будете осторожны, поэтому очень важно понять, как оно работает.
  3. Глобальные переменные. Избегайте непреднамеренного создания глобальных переменных. Всегда объявляйте переменные с помощью var, let или const, чтобы контролировать их область действия и предотвратить загрязнение глобального пространства имен.
  4. IIFE: выражения функций с немедленным вызовом (IIFE) – это мощный инструмент для создания изолированных областей в JavaScript. Они могут помочь предотвратить конфликты глобальных переменных и сохранить ясность кода.
  5. Строгий режим. Включите строгий режим в ваших скриптах с помощью 'use strict';. Он обеспечивает более эффективные методы кодирования, выявляет распространенные ошибки и делает ваш код более предсказуемым.
  6. Практика ведет к совершенству.Регулярная практика необходима для улучшения ваших навыков программирования. Решайте проблемы с кодированием, изучайте различные концепции JavaScript и пишите чистый и эффективный код.
  7. Ищите обратную связь. Не стесняйтесь обращаться за отзывами к коллегам, наставникам или онлайн-сообществам программистов. Конструктивная обратная связь может помочь вам определить области для улучшения.
  8. Сохраняйте уверенность. Уверенность – ключ к успеху на собеседовании. Сохраняйте спокойствие, четко формулируйте свой мыслительный процесс и не бойтесь задавать уточняющие вопросы, если вы не уверены в проблеме.

Изучая и практикуя примеры кода, представленные в этом руководстве, вы не только получите более глубокое понимание JavaScript, но и приобретете навыки и уверенность, необходимые для того, чтобы преуспеть на следующем техническом собеседовании. Помните, успех на собеседовании приходит с практикой и постоянным обучением. Желаем удачи на вашем пути кодирования!