Как эти старшие/старшие интерфейсщики отвечают на вопросы интервью по JavaScript (1)

JavaScript
Как эти старшие/старшие интерфейсщики отвечают на вопросы интервью по JavaScript (1)

предисловие

Начните серию вопросов для интервью.ОпытСо всех основных рынков небольшая частьпосмотри на меня,наиболеея встречаюсь с другими.

Добро пожаловать в бар, будет очень интересно. Сразу к делу.

Question 1:Замыкания JS, как много вы знаете? `

Интервьюер должен был спросить вас:

  1. Что такое закрытие?
  2. Каковы практические сценарии применения замыканий?
  3. Как создаются замыкания?
  4. Как перерабатываются переменные, сгенерированные замыканиями?

Все эти вопросы можно рассматривать как один и тот же вопрос, то есть интервьюер спрашивает вас:你对JS闭包了解多少?

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

答案1:только одинfunctionвreturnСоздается подфункция, и подфункция обращается к переменным внешней функции.

答案2:Замыкания могут использоваться для решения проблем в циклах for.

for(var i = 0; i < 10; i++){
    setTimeout(()=>console.log(i),0)
}
// 控制台输出10遍10.
for(var i = 0; i < 10; i++){
    (function(a){
    setTimeout(()=>console.log(a),0)
    })(i)
}
 // 控制台输出0-9

答案3:Текущая область создает ссылку на родительскую область.

答案4:не знаю. Связано ли это с механизмом сборки мусора в браузере?

Откройте бар. Простите, насколько ваши ответы похожи на вышеприведенные?

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

Основной принцип реализации замыканий

1. JS执行上下文

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

// 栗子:
var d = 'abc';
function a(){
    console.log("函数a");
};
console.log(a);   // ƒ a(){ console.log("函数a"); }
a();		      // '函数a'
var a = "变量a";  
console.log(a);   // '变量a'
a();			  // a is not a function
var c = 123;
 
// 输出结果及顺序:
// ƒ a(){ console.log("函数a"); }
// '函数a'
// '变量a'
// a is not a function

// 栗子预编后相当于:
function a(){
    console.log("函数a");
};
var d;
console.log(a);  // ƒ a(){ console.log("函数a"); }
a(); 			 // '函数a'

a = "变量a";     // 此时变量a赋值,函数声明被覆盖

console.log(a); // "变量a"
a(); 		// a is not a function

Итак, вот в чем проблема.Кто будет выполнять операцию предварительной компиляции? Итак, кто сделал эту предварительную компиляцию и где?

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

js контекст выполнения делится на три типа:

  • 全局执行上下文: Среда, в которую код входит впервые, когда начинает выполняться.
  • 函数执行上下文: при вызове функции код в функции будет выполнен.
  • eval执行上下文: Не рекомендуется, можно игнорировать.

Затем цикл выполнения контекста разбивается на два этапа:

  • 创建阶段
    • Создайте лексическую среду
    • создать переменный объект (VO),Учреждатьцепочка прицелов,цепочка прицелов,цепочка прицелов(Важные вещи говорятся три раза)
    • подтверждатьthisуказать и привязатьthis
  • 执行阶段. На этом этапе выполняется назначение переменных, ссылка на функцию и выполнение кода.

Посмотрите на картинку, чтобы понять.

image.png

Угадайте, когда происходит предварительная компиляция?

О, я забыл упомянуть, на самом деле есть еще одно имя, связанное с компиляцией:执行期上下文.

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

  1. СоздайтеAOобъект
  2. Найдите объявление формального параметра и переменной, используйте переменную и формальный параметр в качестве имени атрибута AO, и значениеundefined
  3. Унифицировать фактические и формальные параметры
  4. Объявление функции находится в теле функции, а значение присваивается телу функции. Наконец, когда программа выводит значение переменной, оно изAOобъект.

Итак, реальный результат предварительной компиляции:


var AO = {
    a = function a(){console.log("函数a");};
    d = 'abc'
}

Давайте сделаем это снова.

1. Что такое переменный объект?

Переменный объектjsКогда код входит в контекст выполнения,jsОбъект, созданный движком в памяти для хранения переменных в текущей среде выполнения.

2. Процесс создания переменного объекта (ВО)

Создание объекта переменных находится на этапе создания контекста выполнения, который, в свою очередь, проходит следующие три процесса:

  • Создайтеargumentsобъект.

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

//举个栗子 
function bar(a, b, c) {
    console.log(arguments);  // [1, 2]
    console.log(arguments[2]); // undefined
}
bar(1,2)
  • Когда встречается функция с таким же именем, последняя перезаписывает первую.
console.log(a); // function a() {console.log('Is a ?') }
function a() {
    console.log('Is a');
}
function a() {
  console.log('Is a ?')
}

/**
ps: 在执行第一行代码之前,函数声明已经创建完成.
后面的对之前的声明进行了覆盖。
**/
  • Проверьте объявление переменной в текущей среде и присвойте значение какundefined. Встречая объявление функции с тем же именем,Чтобы функция не была назначена какundefined, это утверждение игнорируется
console.log(a); // function a() {console.log('Is a ?') }
console.log(b); // undefined
function a() {
  console.log('Is a ');
}
function a() {
console.log('Is a ?');
}
var b = 'Is b';
var a = 10086;

/**
这段代码执行一下,你会发现 a 打印结果仍旧是一个函数,而 b 则是 undefined。
**/

Согласно вышеперечисленным трем шагам, вы будете знать, что происходит с переменным продвижением.

3. Переменный объект становится активным объектом

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

Возьмем пример выше:

console.log(a); // function a() {console.log('fjdsfs') }
console.log(b); // undefined
function a() {
   console.log('Is a');
}
function a() {
 console.log('Is a?');
}
var b = 'Is b';
console.log(b); // 'Is b'
var a = 10086; 
console.log(a);  // 10086
var b = 'Is b?';
console.log(b); // 'Is b?'

В приведенном выше коде фактическое выполнение кода начинается с первой строки console.log() , С тех пор контекст выполнения выглядит следующим образом:

// 创建过程
EC= {
  VO: {}; // 创建变量对象
  scopeChain: {}; // 作用域链
}
VO = {
  argument: {...}; // 当前为全局上下文,所以这个属性值是空的
  a: <a reference> // 函数 a  的引用地址
  b: undefiend  // 见上文创建变量对象的第三步
}

лексический объем (Lexical scope)

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

Вот еще каштан:

 1: let top = 0; // 
 2: function createWarp() {
 3:   function add(a, b) {
 4:     let ret = a + b
 5:     return ret
 6:   }
 7:   return add
 8: }
 9: let sum = createWarp()
10: let result = sum(top, 8)
11: console.log('result:',result)


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

  • Объявить переменные в глобальном контекстеtopи присвойте ему 0.
  • 2 - 8 строк. объявил в глобальном контексте выполнения метод с именемcreateWarpпеременную и присвойте ей определение функции. где строки 3-7 описывают определение его функции и сохраняют определение функции в этой переменной (createWarp)середина.
  • Строка 9. Мы объявили в глобальном контексте выполнения файл с именемsumНовая переменная временно имеет значениеundefined.
  • Строка 9. встретить(), указывая на то, что функция должна быть выполнена или вызвана.затем найдите память глобального контекста выполнения и найдите файл с именемcreateWarpПеременные.Очевидно, он был создан на шаге 2. Далее звоните.
  • При вызове функции вернитесь к строке 2. создать новыйcreateWarpконтекст исполнения. мы можемcreateWarpСоздайте собственные переменные в контексте выполнения .jsдвигательcreateWarpдобавить контекст в стек вызовов (call stack). Поскольку эта функция не имеет параметров, сразу переходите к ее телу.
  • 3 - 6 строк. У нас есть новое объявление функции,существуетcreateWarpСоздать переменную в контексте выполненияadd.addсуществует только вcreateWarpВ контексте выполнения определение его функции хранится в файле с именемaddв собственной переменной.
  • Строка 7, мы возвращаем переменнуюaddСодержание. Движок js ищет файл с именемaddпеременную и найдите ее.Содержимое в скобках в строках 4 и 5 представляет собой определение функции.
  • createWarpвызов завершен,createWarpКонтекст выполнения будет уничтожен. Переменная добавления также уничтожается.ноaddОпределение функции по-прежнему существует, потому что оно возвращает и присваиваетsumПеременная.(пс:这才是闭包产生的变量存于内存当中的真相)
  • Ниже приведен простой процесс выполнения, который не будет повторяться. .
  • ...
  • При выполнении кода глобальный контекст выполнения уничтожается. сумма и результат также уничтожаются.

Резюме

Теперь, если вы позволите вам ответить, какое закрытие, сколько вы можете ответить?

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

Итак, что такое замыкания?

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

Также, если спросятEvent loop、执行栈(EC Stack)、调用栈(Call Stack),Обязательно уточните одну вещь: стек выполнения и стек вызовов — это не одно и то же.Во многих статьях четко не указывается разница между ними или просто говорится, что это одно и то же. Позже, когда будет время, я напишу для них статью, чтобы разъяснить всем их сомнения.

Я желаю тебе всего самого лучшего.

Далее процесс компиляции веб-пакета. Абсолютная галантерея, выглядит просто. Может справиться со всеми вопросами интервью, подобными веб-пакету.