Javascript - The Bits

Javascript has many many “bits”. This page tries to gather the important together and make sense of them.

 

Global Object and “this”

When you load javascript into your page, the browser always does the same thing. It creates what is called the Global Object. In terms of the browser the global object represents the window which will run your code. Your own code, in turn, is included into the global object.

All the code running within this window will have access to the global object. The global object is its connection to the outside world. The handle to the global object is either ‘this’ or ‘window’.

So this is what happens …..

you open your file in your browser (the file where your JS code is obviously). The JS engine then ‘translates’ your code and starts working on the translation. It starts the first of two processes. Creation and execution.

Process 1: CREATION

  1. Create the global object, the ‘this’ handle and the Outer Environment handle.
  2. Setup the memory space for your own code. In this way your code is essentially attached to the global abject. The JS engine works through the translated code and starts setting up the memory space for variables and functions. Thanks to this phase, unlike other programming languages, JS variables and functions do not have to be declared before they are used. The memory allocation and usage are distinct from each other. In the creation phase, variables are created in memory space and given the value of ‘undefined’. The processes behind this approach is called hoisting. However, it is not good practise to rely on hoisting alone, best practise is to declare variables and functions high up and use them lower down

Process 2: CODE EXECUTION

At this point we have:

Global Object
this variable
Outer Environment

Armed with these three, your code is run! NOTE: javascript is single threaded. Everything is run asynchronously, one operation at a time and in a particular order.

 

Function Invocation and the Execution Stack

function b(){}

function a(){b();}

a(); 

So what happens:

  1. Create the base execution context
  2. Create the Global Object (if in a browser this is the WINDOW object)
  3. Attach the above functions to the global object
  4. Execute functions line by line
  5. To run a(); a new execution context is created and placed in the execution stack
    • Every time a function is invoked in JS, a new execution context is created and put on the execution stack (same creation and execution processes talked about above)
  6. when a(); is run, there is another function called b(); Same procedure as with a(); – Another execution context put on the stack

 

THE STACK IS EXECUTED FROM TOP TO BOTTOM. NEW EXECUTION CONTEXTS ARE ADDED TO THE TOP OF THE STACK. ON COMPLETION OF FUNCTION (AND CORRESPONDING EXECUTION CONTEXT, THE FUNCTION/CONTEXT IS “POPPED” OFF THE STACK AND THE NEXT IN LINE IS PROCESSED.

Variable Environment

Every Execution context has its own variable environment. For example:

function b(){ var myVar; }

function a(){
  var myVar = 2;
  b();
}

var myVar = 1;

a(); 

Look at myVar ….

  1. Global execution context created
    • creation phase – myVar = undefined
    • execution phase – myVar = 1
  2. New execution context created a();
  3. New execution context created for b();

 

The Scope Chain

Within a function execution context, any variables used which are not defined within THAT execution context, JS will look for these variables in the currently running execution contexts outer environment (in essence this means one step down the execution stack). The last place checked will be the global execution context.

function b(){ var myVar; }

function a(){
  var myVar = 2;
  b();
}

var myVar = 1;

a(); 

In the above axample, the outer environment of function b(); is the global execution context and not function a(), as might be expected. This is because function b(); lives in the global execution context. It does not live in function a();, it is only called from function a();

The outer environment of any javascript function depends on where the function sits in the code from a lexical perspective  – where it is declared.

The scope chain is composed of the links to outer environments. If a variable is not found in the currently executing context environment, JS looks down the scope chain for that variable. Scope chain is not to be confused with execution stack.

If I put function b(); inside function a(); then the Outer Environment of b(); would be the execution context of a(); – the lexical order has changed. In this case, if myVar is not declared in b(); JS will look down the scope chain and find myVar in the execution context of a();

Note: in ES6 you are not allowed to use a variable until it is assigned a value. This will make some of this confusion go away.

 

Asynchronous Callbacks

These are possible in JS, BUT the asynchronous part is really about what is happening outside the JS engine. JS itself executes in a synchronous manner.

The JS engine does not exist alone. There are many “engines” running at the same time within an application or a browser.

Rendering Engine (prints to screen)
JS Engine
HTTP Request

 

Inside the browser, things are handled asynchronously. Basically there are 2 lists inside the JS Engine

  1. The execution stack
  2. Event Queue

The event queue is for events that are happening in the browser outside of the JS engine but which may effect the JS engine or the JS engine may want to be notified about. Things like mouse actions. We may or may not a function set up to deal with an event but in any case the JS engine will be made aware that the event happened. We can LISTEN for that event – mouse click or HTTP request.

THE EVENT QUEUE IS PROCESSED ONLY WHEN THE EXECUTION STACK IS EMPTY. PROCESSING AN EVENT MAY CAUSE ANOTHER STACK TO BE CREATED. IN THAT CASE, THAT STACK IS PROCESSED IN ITS ENTIRETY BEFORE THE NEXT EVENT IS PICKED UP FROM THE EVENT QUEUE

 


So if a JS is processing something, and you have a click listener (document.addEventListener(‘click’, clickHandler);) – while the stack is being executed, you can click all around the page and nothing will happen. The code in place to deal with that click will not run until the entire currently running stack is processed – only then will the JS engine look for all the events on the event queue.

AVOID LONG RUNNING FUNCTIONS