var и let могут выполнять почти одну и ту же работу, но под капотом var — это разные хлебцы.
Переменные, объявленные с помощью var, имеют либо функциональную, либо глобальную область видимости. Они видны сквозь блоки =› нет области блока.
и они всегда подняты и допускают повторное объявление «Вот в чем разница в двух словах»

  • область блока означает область в условиях if и циклах
if (true) {
 var test = true; 
 /* if statement is a block and it should have a 
 lexical environment 'modern JS feature'
 But the var break this rule */
}

console.log(test); /*true, the variable lives after if. it should be undefined 
*/

примечание: если блок кода находится внутри функции, то var становится переменной уровня функции:

  • это поднято, но что это на самом деле означает

поднят =› поднят

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

но объявление находится далеко внизу, это обычно должно вызывать ошибку, но не

Итак, этот код:

function anything() {

    variable = "Hello";/* this should give an error => refrence error 
                          cant access before init but it works */

    console.log(variable);

    var variable;

}

anything();

…Технически то же самое, что и это (перемещенная фраза var выше):

function anything() {
 var phrase;

 phrase = "Hello";

 console.log(phrase);
}
anything();

примечание: объявление поднимается, но присваивание не

поэтому, если мы объявим переменную и назначим ее ниже, но сошлемся на нее выше, она будет работать, потому что объявление поднято

но ему не будет присвоено никакого значения, поэтому он будет работать, но переменная будет равна нулю

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

    var user = "Pete";

    var user = "John"; // this "var" does nothing (already declared) 
                       // ...it doesn't trigger an error

    console.log(user); // John

Так как же им удавалось обойти это в старые времена "IIFE"

прежде чем даже сказать, как им удалось избежать вар

почему они действительно хотели избежать этого?

что это вызвало

Глобальное загрязнение пространства имен

  • Сначала мы должны поговорить о том, чего вы даже не знали раньше

JAVASCRIPT ИМЕЕТ СБОРНИК МУСОРА

хотя это может показаться очевидным, но, вероятно, мало кто читает об этом

почему?

потому что управление памятью в JavaScript выполняется автоматически и незаметно для нас

ты когда-нибудь спрашивал

Что происходит, когда что-то больше не нужно? Как движок JavaScript обнаруживает его и очищает?

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

ценности:

- корневые значения:

-Текущая выполняемая функция, ее локальные переменные и параметры.

-Другие функции в текущей цепочке вложенных вызовов «цикл событий», их локальные переменные и параметры.

-Глобальные переменные.

-(есть и другие, внутренние)

- достижимые значения:

Любое другое значение считается достижимым, если оно достижимо из корня по ссылке или по цепочке ссылок.

-недоступно:

удаляется из памяти сборщиком мусора

Пример

let object = {
 value: "hi", /*now the object is in the stack and it references 
              the value stored in the heap*/
};
/*this now is a reachable value 
(some address in the stack that references the value in the heap )*/

но если мы сделаем это в том же коде

object = null;
/*the address in the stack is now deleted and 
the value in the heap has nothing that points to it => unreachable
and here is where our friend Garbage Collector works and junks it 
to free the memory*/

если ссылки взаимосвязаны, подробнее здесь: https://javascript.info/garbage-collection#interlinked-objects и вы удаляете корневой объект, который указывает на все значения, удаленные значения называются недоступный остров

углубление в GC внутреннего алгоритма:

это называется «отметить и развернуть» и работает следующим образом:

— Сборщик мусора берет глобальный объект за корень и «помечает» все ссылки из него.

- далее считает каждую метку новым корнем и помечает все отсылки от него "будут похожи на дерево"

- И так далее, пока не будет посещена каждая достижимая (из корней) ссылка.

- Все объекты, кроме отмеченных, удалены.

движок JS применяет некоторые оптимизации к этому алгоритму:

- Коллекция поколений: объекты разбиты на два набора «новые» и «старые». В типичном коде многие объекты имеют короткую продолжительность жизни: они появляются, выполняют свою работу и быстро умирают, поэтому имеет смысл отслеживать новые объекты и очищать от них память, если это так. Те, что выживают достаточно долго, становятся «старыми» и обследуются реже.

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

- Сбор во время простоя: сборщик мусора пытается работать только тогда, когда ЦП простаивает, чтобы уменьшить возможное влияние на выполнение.

Назад к глобальному загрязнению пространства имен

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

такой код

for (var i = 0; i < 2003000; i++) {
    var arra = [];
    arr.push(i * i + i);
}

добавит около 10 000 КБ использования памяти, которые не будут собраны, и да, мы использовали здесь var

так почему вар неправильный?

вы можете столкнуться с некоторыми случаями, когда вы определяете переменные в области блока «оператор if или цикл», но в старые времена она была ограничена в глобальном пространстве имен.

но если бы это было так

for (let i = 0; i < 2003000; i++) {
    let arra = [];
    arr.push(i * i + i);
}

он был бы собран, как только вышел бы из области цикла for

Всегда помните, что сохранение значений в замыкании гарантирует, что они будут собраны

не знаю, что такое закрытие, не беспокойтесь, мы поговорим об этом в другой раз

Так как же им удалось избежать этого "IIFE"

IIFE =› немедленно вызываемые функциональные выражения

это не то, что вы должны использовать, но вы должны знать, что вы можете это сделать

IIFE - это

(function(){
    var something='idk'
    console.log(something);
})();   /*here it invoked as soon as it was created 
         and we use it in this function context to do all what we need and 
         then it's removed from the memory by the GC */

Вопрос 1: почему это заключено в скобки?

  • Механизм Javascript при встрече с ключевым словом «функция» понимает, что это объявление и, следовательно, ему нужно имя, поэтому наш код выше вызовет ошибку -> SyntaxError: операторы функций требуют имени функции

Вопрос 2: почему бы нам не добавить имя?

  • Javascript не позволяет немедленно вызвать объявление функции

есть и другие способы сделать это в JS, это не обязательно должна быть скобка

наш урок истории теперь сделан :)