Примечание. JavaScript - это синхронный и однопоточный язык, что означает, что он выполняет одну команду за раз в определенном порядке.

1. Выполнение программы на JavaScript.

Каждый раз, когда запускается программа JavaScript, создается контекст выполнения (EC) (визуализируйте его как контейнер), он содержит 2 компонента:
1. Переменная среда (память): состоит из пар ключ-значение (переменная: значение)
2. Поток выполнения (код): в нем происходит выполнение кода.

Давайте рассмотрим выполнение простого кода:

Контекст выполнения создается в 2 этапа:
1. Этап создания памяти: JavaScript просматривает программу и выделяет память для всех переменных и функций в программе. Переменной присваивается значение undefined, а функции присваивается блок операторов, записанных при определении этой функции (только в случае операторов функций, в случае стрелочных функций и функциональных выражений функция присваивается как значение переменной, поэтому, будучи «переменной», ей присваивается значение undefined на этапе создания памяти).

2. Этап выполнения кода: JavaScript выполняет код построчно.

Теперь, когда элемент управления достигает строки 1 программы, глобальный контекст выполнения (GEC) помещается в стек вызовов.

Когда программа встречает команду 'var n = 3', переменной 'n' присваивается значение 3 после выполнения строки 1, и управление перемещается в строку 6, поскольку следующая команда выполнения находится в строке. 6.

В строке 6 вызывается функция квадрата. Вызов функций приводит к созданию нового контекста выполнения. Таким образом, внутри раздела кода GEC создается новый контекст выполнения. На этапе создания памяти в локальном контексте выполнения переменным num и res присваивается значение undefined. В начале фазы выполнения кода аргумент «n» передает значение 3 параметру «num». Управление передается в строку 3, когда начинается выполнение функции.

Команда в строке 3 запускается, и 9 присваивается переменной «res». Когда элемент управления достигает строки 4, оператор return ищет значение «res» в разделе памяти локального контекста выполнения.

Функция возвращает значение переменной «s», когда элемент управления переходит обратно к строке 6. После выполнения оператора return контекст локального выполнения очищается из раздела кода GEC, и квадратная функция извлекается из стека вызовов. Возвращаемое значение функции присваивается переменной «s». Элемент управления переместится в строку 7.

После выполнения строки 7 значение переменной s записывается в консоль. При этом, когда выполняется последняя строка кода, GEC очищается и извлекается из стека вызовов.

2. Let, Const и временная мертвая зона

Поднимаются объявления let и const;
Что такое подъем?
Подъем теперь можно лучше понять, поскольку мы знаем о фазе создания памяти, которая происходит во время создания контекста выполнения.
Память выделяется ко всем переменным и функциям даже до того, как будет выполнена одна строка кода, а инициализации, если таковые имеются, происходят на этапе выполнения кода. Следующая программа объясняет это:

В приведенном выше случае ошибки не возникает, даже если к переменной и функции обращаются до объявления или инициализации.
Однако обратите внимание на следующие случаи:

Если переменные подняты, то почему появляется ошибка ReferenceError?
Это связано с тем, что переменным, объявленным с помощью ключевого слова var, присваивается значение undefined и они прикрепляются к объекту global.
Переменным, объявленным с помощью let или const, также присваивается значение undefined, но они хранятся в отдельной области памяти.

Эти переменные (объявленные с помощью «let» и «const») находятся внутри временной мертвой зоны до их инициализации. Поскольку они находятся во временной мертвой зоне, к ним нельзя получить доступ до их инициализации, поэтому приведенный выше код не выдает ошибку ReferenceError и записывает 10 в консоль, поскольку был получен доступ к 'a' после команды инициализации.

Чтобы избежать «undefined», можно объявить переменные с помощью «const» и «let», а не объявлять их с помощью «var». Однако временная мертвая зона может вызвать непредвиденные ошибки во время кодирования, чтобы избежать этого, убедитесь, что часть объявления и инициализации переменной всегда находится в верхней части вашего кода. Мы можем интерпретировать это как способ уменьшения размера временной мертвой зоны.

Давайте также поймем разницу между ReferenceError, SyntaxError и TypeError, возникающую при использовании «let» и «const»:

1. ReferenceError: возникает, когда кто-то пытается получить доступ к переменной, объявленной с помощью «let» или «const», когда она все еще находится во временной мертвой зоне или когда к ней обращаются за пределами этой области блока.

2. SyntaxError: давайте разберемся с примерами:
i) Повторное объявление / повторное объявление является примером SyntaxError, в то время как переменные, объявленные с помощью 'var', в этом случае не выдадут ошибки, использование let или const приведет к ошибке.

let a = 20
let a = 30
// SyntaxError: Identifier 'a' has already been declared

ii) переменные «const» следует объявлять и инициализировать одновременно, в противном случае возникает ошибка SyntaxError.

const a
a = 1000
console.log(a)
// SyntaxError: Missing initializer in const declaration

3. TypeError: Примером этого может быть повторное присвоение значения переменной, объявленной с ключевым словом «const». Поскольку здесь речь идет о «типе» переменной (здесь «const»), это называется TypeError.

const a = 10
a = 20
// TypeError: Assignment to constant variable.

3. Функции

  1. Заявление функции / объявление функции:

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

console.log(a) 
/* logs ƒ a(){ 
    var v = 10; 
    console.log(v);
} */
a() // logs 10
function a(){
    var v = 10;
    console.log(v);
}

2. Функциональные выражения:

В функциональных выражениях переменная инициализируется функцией, в основном, функция действует как значение.
Операторы функций позволяют получить доступ к функциям до объявления, наоборот, в приведенном ниже примере мы получаем TypeError. Это происходит потому, что «v» здесь действует как любая другая переменная, поэтому перед началом фазы выполнения кода ей присваивается значение «undefined». Только когда элемент управления достигает команды присвоения, функция назначается «v», вызов «v» после этого не вызывает никаких ошибок.

console.log(v) // o/p: undefined 
v() 
// TypeError: v is not a function
var v = function () {
    var a = 10;
    console.log(a)
}
v() // logs 10

Следовательно, важное различие между оператором функции и выражением функции - подъем.

3. Анонимные функции:

Функции, объявленные без названия, называются анонимными функциями.

function(){
    ...
}
/* This code when run will give a SyntaxError, saying that function statements require a function name */

Так в чем же польза анонимных функций?
Во всех случаях, когда функция может использоваться как значение,
1. присвоение ее переменной
2. передача ее другой функции < br /> 3. возвращая его из функции,
можно использовать анонимные функции.

4. Выражения с именованными функциями:

Выражения с именованными функциями - это в основном выражения функций, в которых назначаемая функция является не анонимной функцией, а именованной функцией.

var v = function func(){
    console.log('called')
}
v() // logs 'called'
func() 
// ReferenceError: func is not defined

Ошибка ReferenceError, которую мы получаем в приведенном выше примере, связана с тем, что функция «func» не определена во внешней области видимости. Если мы попытаемся получить доступ к функции "func" во внутренней области видимости, ошибки не возникнет, посмотрите:

var v = function func(){
    console.log(func)
}
v()
/* o/p: ƒ func(){
    console.log(func)
}*/

5. Первоклассные функции.

Мы знаем, что функции могут использоваться как значения, то есть их можно передавать в качестве аргументов другим функциям, можно возвращать из других функций и т. Д. Благодаря этому свойству функции называются функциями первого класса.

function f1(parameter){
    return function(){
        parameter()
        console.log('from returned function')
    }
}
var v = f1(function(){
    console.log('passed as an argument')
})
v()
/* o/p: passed as an argument
        from the returned function */

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

Ссылки:
1) https://www.youtube.com/playlist?list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP