Scope in JavaScript

How does JavaScript know what variable can be looked up? Scope. If you don't understand how JavaScript running, it's hard to understand scope. In this post, I will take about Execution Context , scope callback, and closure.

How is javascript Running?

Javascript goes through the code line-by-line and runs/ executes each line which is known as the thread of execution. It needs somewhere to save variables like string and array for later use; this place is called memory. Note; thread and memory also called Execution context

Thread

Javascript is single-threaded, can only do one thing simultaneously, only one statement/one line is executed. This thread is synchronous execution, start from the first line of function to the last line. for asynchronous, it has to ask browser API for help(fetch, timeout. etc.)

Memory

Memory is known as variable environment. Declare/register/define, take the label, and save code there.

Call stack

call stack helps javaScript track which function is currently running(the thread is running), and where to it's after return from the current function. When a function is running, add it to calls stack. finish execute a function, removes from call stack, retune to lower stack the top of the call stack is the function we’re currently running. The bottom stack is always global. Global never pop out even if there is no more code to execute, but the application is still running. Image user clicks a button. The application has to show content base on some state, that needs a thread waiting for user operation.

Scope

Scoping answers where can we access a certain variable or function, Javascript scope is lexical scoping. What do you mean by lexical? Well. Lexical is relating to the words or vocabulary of a language. You can think the variable is a word of some language; a dictionary includes all of those words. Lexical is about the position of definition within our code. The position of a word is fixed in dictionary; you always look up a word in same page same line.

Lexical scoping means Where you define your functions determines what data it has access to when you call it. Those data never changed, because scopes/identifiers are determined at compile time.Our lexical scope is what determines our available variables at function execution, not where our function is called .

Compile code

the lexically scoped language, which JavaScript is, mean scopes/identifiers is determined at compile time. (know where and how all identifiers are declared) It is used at run time, but it is determined at compile time. And why that matters is that it allows the engine to much more efficiently optimize because everything is known and it's fixed. Nothing during the run time can determine

let look at this example:
var num = 1;
function calc() {
    var num2 = 2;
    var result = num + num2;
    console.log(result)
}
calc()

JavaScript compiler finds out all declaration/define at compile-time and create scope; each function has its scope. the most outside one are called global scope plan for scope

Run my code

compiler outputs is executable code, is a plan for that scope what variable and function(we create another scope in outer scope) will have. When engine runs is when it all actually comes into existence, value in scope plan became variable in memory, code is running in a thread.

fitst line initializes it num to undefined, then assign value to num identifier 1 function scope It has a reference to function calc, which is attached to another scope, make this scope live: add value in scope to memory, move thread in this function. Fist Javascript engine initializes to undefined and assigns value 2; then engine initializes result to undefined, find out num in global memory; num2 in function memory, assign value 3 to resule. end After function return, there is no code to execute. Our thread is empty

Hoisting

Is javascript moving all declarations to the top of the scope? No. Scopes are created at compile time before Executing code. JavaScript engine knows what variable is available; just look up the memory. If no value is assigned to an identifier, you get back undefined. that behavior as if the variable declaration is move to the top of the scope

Closure

definition from YDKJS:

Observational: closure is a function instance remembering its outer variables even as that function is passed to and invoked in other scopes.

Implementational: closure is a function instance and its scope environment preserved in-place while any references to it are passed around and invoked from other scopes.

what do you mean by remembering or preserved? How can javascript do that? every function has a [[Scope]] property to keep track of reference to outer memory. we call a function it will always look first in its immediate local memory (variable environment), and then in the [[scope]] property

note: function's [[scope]] maintain outer’s live local memory, not include in local memory of function itself example

function out(){
  let count = 0;
  function inf() {
    let width = 1;
    count += 1
  }
  console.dir(inf)
 return inf
}

scopes in dev tool Console.dir() displays a list of the properties of inf function, [[Scopes]] has a list of outer scope.

All articles written with ❤ by apSomething using Gatsby, Emotion, and hosted with cloudflare pages.