В настоящее время большинство фронтенд-интервью будут задавать вопросы о цикле событий, стеке выполнения и т. д. Эта статья объяснит вам эти концепции в виде кейсов, рисунков и т. д. Если вы внимательно прочитаете ее, я полагаю, что 90% студентов могут полностью понять это.
Механизм памяти JS
JavaScriptОн имеет механизм автоматической сборки мусора, который периодически проверяет неиспользуемые переменные на предмет утилизации и освобождения. Поэтому в замыкании, если есть ссылка на внешнюю переменную, она не может быть освобождена и повторно использована, а параметры обычно передаются.
Сборка мусора: найдите те переменные, которые больше не используются, а затем освободите занимаемую ими память.Сборщик мусора выполняет эту операцию периодически через равные промежутки времени.
существуетJSДля каждых данных требуется место в памяти, а пространство памяти делится на стековую память (stack) и динамическую память (heap).
Память стека обычно хранит основные типы данных
Number String Null Undefined Boolean Symbol
См. пример:
var num = 1
мы определяем переменнуюnum, система автоматически выделяет место для хранения. Мы можем напрямую манипулировать значениями, хранящимися в пространстве памяти стека, поэтому доступ к базовым типам данных осуществляется по значению.
Хранение и использование данных в памяти стека аналогично структуре данных стека в структуре данных.последний пришел первый вышелправила.
Куча памяти обычно хранит ссылочные типы данных
var user = { name:'jack' }
var arr = [1,3,5]
JSссылочные типы данных, такие как массивыArray, размер их значений не фиксирован. Значения ссылочных типов данных — это объекты, которые хранятся в куче памяти.JavaScriptПрямой доступ к местам в куче памяти не разрешен, поэтому мы не можем напрямую манипулировать пространством кучи памяти объекта.
Благодаря следующей картинке мы можем интуитивно понять.
var num = 1; // 栈
var name = '前端未来'; // 栈
// 变量user存在于栈中,{name:'河畔'}存在于堆内存中
var user = { name: '河畔' };
// 变量arr存在于栈中,[1, 2, 3] 作为对象存在于堆内存中
var arr = [1, 3, 5];
Поэтому, когда мы хотим получить доступ к ссылочному типу данных в памяти кучи, мы фактически сначала получаем указатель объекта из стека, а затем получаем нужные нам данные из памяти кучи.
Итак, мы часто говорим: основные типы присвоения не влияют друг на друга, присвоение ссылочного типа будет влиять на исходный объект.
Пример прояснит:
var a = 20;
var b = a;
b = 30;
// a为20,b为30,值类型不影响
console.log(a)
var user = { name: '河畔' };
var info = user;
info.name = 'Jack'
// 打印为jack,指向同一个内存地址
console.log(user.name)
Суммировать:
- JavaScript имеет автоматический механизм сборки мусора
- Память JS делится на память кучи и память стека.
- Ссылочные типы содержат указатели в стеке и значения объектов в куче
- Данные памяти стека следуютпервый вышел последним
EventLoop
Сейчас на фронтенд-интервью все любят спрашивать EventLoop, но, честно говоря, многие прочитали бесчисленное количество статей и до сих пор в замешательстве, сегодня они до сих пор демонстрируют эффект через код + картинки.
Чтобы лучше понять механизм событий, нам нужно сначала представить стек выполнения. Все прогоны JS-кода запускаются и выполняются после push и pop до тех пор, пока стек не опустеет.
стек выполнения
Код JS создаст контекст выполнения перед запуском, который также можно понимать как среду выполнения.В JS есть три контекста выполнения:
- Глобальным контекстом выполнения по умолчанию является объект окна в браузерах.
- Контекст выполнения функции, JS-функции создают контекст при каждом вызове.
- Eval выполняет контекст, а функция eval генерирует свой собственный контекст.
Обычно в нашем коде имеется более одного контекста, так каким же должен быть порядок выполнения этих контекстов? Выполнять сверху вниз?
Стек — это структура данных, которая следует принципу «первым пришел — последним вышел». Стек выполнения в JS имеет такую структуру: когда движок впервые сталкивается с JS-кодом, он генерирует глобальный контекст выполнения и заталкивает его в стек выполнения, каждый раз, когда встречается вызов функции, будет заталкиваться новый в стек контекст. Механизм выполняет функцию на вершине стека, и когда выполнение завершается, текущий контекст выполнения извлекается.
Далее рассмотрим пример:
function foo() {
console.log('1');
bar();
console.log('3');
}
function bar() {
console.log('2');
}
foo();
В этом нет никаких сомнений, ответ знают все, как называется стек выполнения?
Сначала выполните этот файл JS, создайте глобальный контекст и поместите его в стек выполнения.Когда вызывается функция foo(), поместите контекст выполнения функции foo в стек выполнения, а затем выполните вывод «1»; когда функция bar() вызывается Called, поместите контекст выполнения функции bar в стек выполнения, а затем выполните вывод '2'; после выполнения bar() он извлекается из стека выполнения, а foo () продолжает выполняться, выводя '3'; выполнение функции foo() завершено, она выталкивается из стека выполнения, и, наконец, весь стек выполнения очищается.Это первый вход последним, Foo сначала помещается в стек выполнения и, наконец, выталкивается из стека выполнения
EC — это контекст выполнения Execute Context.
Суммировать:
- Весь код JS должен быть помещен в стек выполнения для запуска.
- Существует три контекста выполнения (глобальный, функциональный, eval)
- Стек — это структура данных, которая следуетпервый вышел последним
Затем посмотрите на классический вопрос интервью
console.log(1)
new Promise(function(resolve){
console.log(3)
resolve(100)
}).then(function(data){
console.log(data)
})
setTimeout(function(){
console.log(4);
})
console.log(2)
Приведенный выше результат печати вопроса интервью: 1 3 2 100 4
Можете ли вы назвать конкретные шаги его реализации?
Мы все знаем, что JS сам по себе является однопоточным и может делать только одну вещь за раз, так как же он справляется с таймерами и промисами? На самом деле, мы представимqueneОчередь.
Основной поток выполняет синхронные блоки кода, и когда он сталкивается с асинхронными задачами, такими как таймеры и промисы, он создает очередь событий и бросает их в очередь, а после завершения основного потока возвращается в очередь выполнения.task.
Поэтому наше выполнение JS в основном включает в себя синхронные задачи и асинхронные задачи.Вся синхронная задача войдет в основной поток и, наконец, поместит ее в стек выполнения для выполнения, что мы объяснили вам выше.стек выполнения, а затем сосредоточьтесь на асинхронных задачах.
В JS браузера асинхронные задачи делятся на макрозадачи и микрозадачи, причем как макрозадачи, так и микрозадачи принадлежат очереди, а не помещаются в стек. Микрозадача создаст очередь, макрозадача создаст очередь, и после выполнения основного потока она сначала выполнит микрозадачу, поместит все микрозадачи в стек выполнения для выполнения и, наконец, возьмет одну из них. задачу макроса и положить ее в стек выполнения Выполнить, после выполнения взять еще одну, пока не будут выполнены все задачи макроса.
Далее посмотрите на картинку:
Диаграмма JS слева содержит кучу и стек, и весь код будет помещен в стек для выполнения, мы называем этостек выполнения, Стек выполнения является основным потоком. Сначала он выполняет синхронные задачи. Когда асинхронные задачи, такие как ajax и setTimeout, встречаются в середине, он будет помещен в очередь. Наконец, события в очереди будут извлечены и помещены в исполнение для выполнения, и процесс будет циклически повторяться.
Тогда давайте снова посмотрим на приведенный выше пример:
console.log(1)
new Promise(function(resolve){
console.log(3)
resolve(100)
}).then(function(data){
console.log(data)
})
setTimeout(function(){
console.log(4);
})
console.log(2)
- Создайте глобальный контекст и поместите его в стек выполнения.
- Нажмите синхронный код Console.log в стек выполнения для выполнения, печать
1, и извлеките стек - Поместите синхронный код new Promise в стек выполнения для выполнения, распечатайте
3, и извлеките стек
Примечание. Процесс нового промиса на самом деле синхронный, только после того, как разрешение и отклонение являются асинхронными.
- затем — асинхронная задача, поместите ее в очередь микрозадач и создайте событие
- setTimeout — это асинхронная задача, поместите ее в очередь задач макроса и создайте событие.
Примечание: задача очереди макро- и микрозадач состоит из двух
- Поместите синхронный код console.log в стек выполнения для выполнения, распечатайте
2, и извлеките стек
На данный момент во всем стеке выполнения остается только глобальный контекст, а исполняемый код отсутствует.
- Микрозадачи выполняются первыми, поэтому все события в очереди микрозадач извлекаются и помещаются в стек выполнения для выполнения. Распечатать
100, и извлеките стек - Из очереди задач макроса взять только одно событие и поместить его в стек выполнения для выполнения, вывести
4
Итак, давайте изменим приведенный выше пример:
console.log(1)
new Promise(function(resolve){
console.log(3)
resolve(100)
}).then(function(data){
console.log(data)
}).then(function(){
console.log(200)
})
setTimeout(function(){
console.log(4);
})
setTimeout(function(){
console.log(5);
})
console.log(2)
Есть 2 then и 2 setTimeouts.После обучения, как вы думаете, сколько должно быть напечатано? Ответ: 1 3 2 100 200 4 5
Это конец всей статьи, надеюсь, вы ее поняли!
Суммировать:
- JavaScript имеет автоматический механизм сборки мусора
- Память JS делится на память кучи и память стека.
- Ссылочные типы содержат указатели в стеке и значения объектов в куче
- Весь код JS должен быть помещен в стек выполнения для запуска.
- Перед выполнением кода создается контекст выполнения
- Существует три контекста выполнения (глобальный, функциональный, eval)
- Синхронные задачи выполняются первыми, а асинхронные ставятся в очередь.
- Сначала выполняются микрозадачи, а затем макрозадачи.
- Все микрозадачи загружаются в стек выполнения, а макрозадачи загружаются по одной.
- Стек приходит первым, уходит последним, а очередь поступает первым
Сколько людей может понять жирный текст, вышесказанное фактически демонстрируется всем через картинки и коды.
Вышеупомянутые концепции кучи, стека, механизма событий и т. Д. Организованы для всех. Я надеюсь, что каждый может сказать «Чжан Сан» и «Ли Силай» во время интервью и не будет отвергнут другой стороной.
Официальный аккаунт WeChat: Будущее интерфейсов
Личный WeChat:
В этой статье используетсяmdniceнабор текста