предисловие
этот разwhy what or how
тема:JavaScript
переменное хранилище.
Вне зависимости от языка переменные — основа всего, число — переменная, предмет — тоже переменная, вJavaScript
Даже функция in является переменной.
Тогда такая важная переменная, вJavaScript
Как именно хранится?
Стек и куча?
куча (
Stack
), также известный как стек, представляет собой линейную таблицу с ограниченным числом операций. Линейный список, который ограничивает вставки и удаления только концом списка.
Поиск на БайдуJavaScript
Хранилище переменных, можно посмотреть много статей, не более чем вывод:
Для примитивных типов в стеке хранятся сами данные, для объектных типов в стеке хранится только ссылка на адрес в куче.
Однако я вдруг подумал о проблеме: если примитивный тип существует в стеке, тоJavaScript
Как замыкания реализованы в ?
Конечно, если вы хотите вникнуть в эту проблему, то надо сначала поставить стек (Stack
) и куча (Heap
), чтобы было понятно.
Ну, давайте сначала поговорим о стеке.
куча
Стек — это линейная структура в памяти, используемая для хранения локальных переменных и параметров функций в соответствии с принципом «первым пришел — последним вышел». Данные могут быть помещены в стек только последовательно и последовательно извлечены из стека. Конечно, стек — это просто формальное описание непрерывной области памяти, а операции добавления и извлечения данных в стек и из него просто перемещают указатель стека вверх и вниз по адресу памяти. Как показано на следующем рисунке (в качестве примера возьмем язык C):
Как показано на рисунке, указатель стека только начинает указывать на память.0x001
положение, тоsum
Начинает вызываться функция, так как объявляются две переменные, в стеке сохраняются два значения, и указатель стека тоже начинает двигаться соответственно.sum
В конце вызова функции он просто перемещает указатель стека вниз, а не всплывающее окно с реальными данными, данные все еще там, но они будут перезаписаны при выполнении следующего присваивания.
Это довольно просто, не так ли, но нужно отметить, что данные в области стека в памяти будут автоматически извлекаться из стека после завершения вызова функции, и операционная система будет выполняться автоматически без необходимости программа для работы, другими словами: переменные в стеке исчезают после завершения вызова функции.
Поэтому характеристики стека таковы: легковесность, не требуется ручное управление, функция создается при вызове функции и исчезает при завершении вызова.
куча
О куче можно просто думать как о большом куске памяти, вроде корзины, неважно, что вы в нее кладете, но корзина — это личный предмет, и операционной системе все равно, что в вашей корзине. , и он не проявляет инициативу. очистить вашу корзину, так что вC
В языке содержимое кучи нужно очищать вручную программисту, иначе будет переполнение памяти.
Чтобы в определенной степени решить проблему с кучей, некоторые языки высокого уровня (такие какJAVA
) представляет концепцию:GC
,Garbage Collection
, сборка мусора, используемая для помощи программам в управлении памятью и активной очистке неиспользуемых данных в куче.
Поскольку куча — это большая корзина, данные, которые нельзя хранить в стеке (например, объект), будут храниться в куче, а стек сохранит только ссылку на данные (то есть первый адрес блока данных).
вопрос!
OK
Стек и кучу содержимого как указано выше, теперь давайте посмотрим на вывод каждого:
Для примитивных типов в стеке хранятся сами данные, для объектных типов в стеке хранится только ссылка на адрес в куче.
Это кажется очень логичным.Согласно определению, базовый тип существует в стеке, а объект существует в куче.В этом нет ничего плохого!
Тем не менее, пожалуйста, подумайте над вопросом:
Так как данные в стеке будут уничтожены после завершения выполнения функции, тоJavaScript
Как реализовать замыкание функции посередине, сначала просто подойдите к замыканию:
function count () {
let num = -1;
return function () {
num++;
return num;
}
}
let numCount = count();
numCount();
// 0
numCount();
// 1
Согласно заключению,num
Переменная называетсяcount
создается функция, вreturn
выскочил из стека.
Поскольку это логика, вызовитеnumCount
как выводится функция0
Шерстяная ткань?num
в функцииreturn
время было уничтожено в памяти!
Поэтому в этом примереJavaScript
Базовый тип не хранится в стеке, но должен храниться в куче дляnumCount
использование функции.
Значит, все в Интернете ошибаются? Не слишком! Далее поговорим о моемJavaScript
Понимание хранения переменных.
покинуть стек
так как вJavaScript
Есть проблема с замыканиями, уходом из стека(Stack
), можно ли реализовать хранилище переменных, используя только кучу? Рассмотрим частный пример:
function test () {
let num = 1;
let string = 'string';
let bool = true;
let obj = {
attr1: 1,
attr2: 'string',
attr3: true,
attr4: 'other'
}
return function log() {
console.log(num, string, bool, obj);
}
}
сопровождаемыйtest
Вызов, чтобы убедиться, что переменная не уничтожена, сначала генерирует объект в куче и вызывает егоScope
Ну, поместите переменную какScope
свойства сохраняются. Структура данных в куче выглядит примерно так:
Итак, это еще не решит проблему замыканий?
Конечно можно, потому чтоScope
Объекты хранятся в куче, поэтому возвращаемыйlog
функция может иметьScope
доступ к объектам. На картинке ниже код вChrome
Эффект исполнения в:
Часть красного прямоугольника, которая согласуется с вышеизложенным, также отражает проблемы, упомянутые ранее: в примереJavaScript
Переменная существует не в стеке, а в куче, используя специальный объект (Scope
)спасти.
затем вJavaScript
Как именно переменные хранятся в процессе? Это напрямую связано с типом переменной, далее мы поговорим оJavaScript
Тип переменной в .
три типа
существуетJavaScript
, существует три типа переменных:
- Локальные переменные
- захваченная переменная
- глобальная переменная
локальная переменная
Локальные переменные хорошо понятны: объекты, объявленные в функции и не используемые другими областями видимости после возврата из функции. в коде нижеlocal*
являются локальными переменными.
function test () {
let local1 = 1;
var local2 = 'str';
const local3 = true;
let local4 = {a: 1};
return;
}
захваченная переменная
Захваченная переменная является противоположностью локальной переменной: если она объявлена в функции, но все еще используется невыполненной областью (функция или класс) после возврата функции, то эта переменная является захваченной переменной. в коде нижеcatch*
все захваченные переменные.
function test1 () {
let catch1 = 1;
var catch2 = 'str';
const catch3 = true;
let catch4 = {a: 1};
return function () {
console.log(catch1, catch2, catch3, catch4)
}
}
function test2 () {
let catch1 = 1;
let catch2 = 'str';
let catch3 = true;
var catch4 = {a: 1};
return class {
constructor(){
console.log(catch1, catch2, catch3, catch4)
}
}
}
console.dir(test1())
console.dir(test2())
скопировать код вChrome
Вы можете просмотреть объект вывода в разделе[[Scopes]]
соответствующий нижеScope
.
глобальная переменная
Глобальная переменнаяglobal
, в браузерах какwindow
существуетnode
Ливэйglobal
. Глобальные переменные по умолчанию добавляются к нижнему концу цепочки областей действия функций, которой является функция выше.[[Scopes]]
последний из .
Глобальные переменные требуют особого внимания:var
а такжеlet/const
разница.
var
Глобальныйvar
переменные простоglobal
Объект имеет добавленное свойство.
var testVar = 1;
// 与下述代码一致
windows.testVar = 1;
let / const
Глобальныйlet/const
переменные не изменяютсяwindows
объект, объявление переменной помещается под специальный объект (сScope
аналогичный).
let testLet = 1;
console.dir(() => {})
скопировать вChrome
со следующими результатами:
два пути
Затем определяется тип переменной, как ее сохранить? Есть два вида:
- куча (
Stack
) - куча(
Heap
)
Я считаю, что когда вы видите это, всем должно быть ясно: кроме локальных переменных, все остальное хранится в куче! По типу данных переменной она делится на следующие два случая:
- Если это базовый тип, сами данные хранятся в стеке.
- Если это тип объекта, стек хранит ссылку на объект в куче.
Но это идеальная ситуация, поэтому позвольте задать вам еще один вопрос:JavaScript
Как синтаксический анализатор узнает, что переменная является локальной?
Определите, ссылается ли на него внутренняя функция!
что еслиJavaScript
Парсер не оценивает? Он может существовать только в куче!
Тогда вы должны спросить,Chrome
изV8
О том, можно ли судить, следует судить по результатам.
Только переменные в красном полеa
, а переменнаяb
исчез. из-заFireFox
не могу печатать[[Scopes]]
свойства, следовательно, автор не может судить. Конечно, если найдутся большие ребята, которые смогут понять и добавить еще, буду очень благодарен.
Хорошо, теперь, когда мы знаем, как хранить, давайте посмотрим, как присваивать значения.
присвоение переменной
На самом деле, независимо от того, находится ли переменная в стеке или в куче (во всяком случае, в памяти), ее структура аналогична способу хранения значения и имеет следующую структуру:
Ну а теперь давайте посмотрим на присвоение, согласно=
В правой части числа есть два типа переменных:
назначить как константу
Что такое константа? Константа — это значение, которое можно определить, как только оно будет объявлено, например1
,"string"
,true
,{a: 1}
, являются константами. После объявления этих значений их нельзя изменить. Некоторые люди могут быть упрямыми. Тип объекта может быть константой, и его можно изменить. Я пока оставлю этот вопрос и объясню его позже.
Предположим, у вас сейчас есть следующий код:
let foo = 1;
JavaScript
объявил переменнуюfoo
, и пусть его значение будет1
, в памяти произойдут следующие изменения
Если теперь объявитьbar
Переменная:
let bar = 2;
Тогда в памяти это будет выглядеть так:
Теперь вернемся к только что заданному вопросу: считаются ли типы объектов константами?
Например, следующий код:
let obj = {
foo: 1,
bar: 2
}
Модель памяти выглядит следующим образом:
Из этого рисунка мы можем узнать, что на самом делеobj
Указанный адрес памяти также содержит значение адреса, и это хорошо, если мы позволимobj.foo = 'foo'
На самом деле модифицированный0x1021
в области памяти, ноobj
Адрес памяти, на который указывает, не изменяется, следовательно, объект является константой!
Назначено переменным
Что такое переменная? в вышеописанном процессеfoo
,bar
,obj
, являются переменными, переменные представляют собой ссылочное отношение, и их собственные значения не являются определенными.
Итак, что произойдет, если я присвою значение одной переменной другой переменной?
let x = foo;
Как показано на рисунке выше, толькоx
ссылается сfoo
Только одно и то же значение адреса, и новое пространство памяти использоваться не будет.
OK
На этом назначение заканчивается, и следующим шагом будет изменение.
переменная модификация
Как и присваивание переменных, модификация переменных также должна основываться на=
В правой части числа есть два типа переменных:
изменить на постоянный
foo = 'foo';
Как показано на рисунке выше, память сохраняется'foo'
и воляfoo
Справочный адрес изменен на0x0204
.
изменить на переменную
foo = bar;
Как показано на рисунке выше, толькоfoo
Указанный адрес был изменен.
Как работает константа
const
дляES6
Способ для новых объявлений переменных бытьconst
Модифицированные переменные не могут быть изменены.
на самом деле соответствуетJavaScript
В карте хранения переменных адрес памяти, на который указывает переменная, не может быть изменен. То есть стрелку изменить нельзя.
Например следующий код:
const foo = 'foo';
foo = 'bar'; // Error
Как показано на диаграмме отношений выше,foo
Нельзя ссылаться на другое значение адреса.
Что ж, теперь вы можете решить свою путаницу со следующим кодом:
const obj = {
foo: 1,
bar: 2
};
obj.foo = 2;
Этоobj
Указанный адрес не изменился, а измененная часть представляет собой другую область. Как показано ниже
модификация объекта
OK
Очень простые вопросы, которые можно задать при входе на собеседование:
let obj1 = {
foo: 'foo',
bar: 'bar'
}
let obj2 = obj1;
let obj3 = {
foo: 'foo',
bar: 'bar'
}
console.log(obj1 === obj2);
console.log(obj1 === obj3);
obj2.foo = 'foofoo';
console.log(obj1.foo === 'foofoo');
пожалуйста скажиconsole
результат.
Мы не будем обсуждать результаты, а сначала посмотрим на структуру в памяти.
Итак, теперь вы знаете ответ?
Суммировать
существуетJavaScript
Переменная в середине не полностью существует в стеке, ранняяJavaScript
Компилятор даже хранит все переменные в объекте, который называется замыканием.JavaScript
Это язык, основанный на функциях, а функции в нем бесконечно вариативны, поэтому использование стеков не может решить языковые проблемы, надеюсь, каждый сможет это увидеть и понять.JavaScript
Смоделируйте его в памяти.
Как обычно, задайте несколько вопросов:
-
JavaScript
Какие бывают типы переменных? -
JavaScript
Как хранятся примитивные типы и типы объектов?
Ссылаться на
- Memory : Stack vs Heap
- Variables and Memory
- Does JavaScript use stack or heap for memory allocation or both?
- StackOverflow - garbage-collection-with-node-js
- StackOverflow - How variables are allocated memory in Javascript?
- Энциклопедия Baidu - стек
последний из последних
Все выпуски этой серииminimo
Предложи, я люблю тебя~~~