Прежде чем мы перейдем к лексической области видимости, давайте прольем свет на область видимости в JavaScript.

Если вы уже использовали JavaScript раньше, наиболее часто используемые слова для области видимости — это глобальная область действия и локальная область действия. Глобальная область действия — это то, что доступно или к чему можно получить доступ во всей программе. Все блоки и вне блоков (блок — часть кода внутри { }, это может быть функция, for, if , while… и т.д.) имеют доступ к глобальной области видимости и название «GLOBAL» ясно указывает на это.

Локальная область действия относится к доступу переменной к определенному блоку кода или блокам в основном блоке, в котором объявлена/определена переменная.

var spaceTime = 'distorted' //Global scope
const func = () => {
 console.log(spaceTime)
}
func() //distorted

В этом контексте можно безопасно использовать ключевые слова «let» и «var», чтобы еще лучше объяснить область действия и то, как соответствующим образом использовать declare/define. Это заблуждение, что «var» можно просто заменить на «let». Давайте приступим прямо к делу.

const spaceTime = () => {
 var gravity = 'distorts spacetime'
 console.log(gravity, "-outside if block")
 if(true){
   console.log(gravity, "-inside if block")
 }
}
spaceTime() //distorts spacetime -outside if block
            //distorts spacetime -inside if block

Основное различие между ключевыми словами «var» и «let» заключается в следующем:

‘var’ доступен вне блока, в котором он объявлен или определен, и во всех внутренних блоках. ‘let’ доступен только для блока, в котором он определен/объявлен.

const space = () => { 
  var outsideIfVar = "outsideIfVar"
  let outsideIfLet ="outsideIfLet"
  console.log(insideIfVar) // undefined (hoisted)
  if(true){
    var insideIfVar = "insideIfVar"
    let insideIfLet ="insideIfLet"
    console.log(outsideIfLet) // outsideIfLet
    console.log(outsideIfVar) // outsideIfVar  
  }
  console.log(insideIfVar) // insideIfVar
  console.log(insideIfLet) // insideIfLet is not defined(throws error)
}
space();

Объявления/определения ‘var’ могут быть подняты наверх области видимости. Объявления/определения let не могут быть подняты. Он доступен только после его объявления.

Example for lexical scoping: 
const mainFunc = () => {
 var spaceTime = 'distorted'
 console.log(gravity) // undefined
 const func = () => {
          //local scope
  var gravity = 'distant spacetime'
  console.log(spaceTime) //distorted
 }
}
mainFunc()

В приведенном выше примере представлена ​​лексическая область видимости. Переменная «spaceTime», определенная в mainFunc, доступна для всех блоков внутри ее области. Но переменная «гравитация», определенная во внутреннем блоке, недоступна для внешнего блока. Он доступен только в пределах области, в которой он определен (func), а не в области над ним (mainFunc).

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