Variables, Scope and Memory

Variables

A variable in javaScript is loosely typed, and is literally just a name for a particular value at a particular time. Because there are no rules defining the type of data that a variable must hold, a variable’s value and data type can change during the lifetime of a script.

Variables may contain two different types of data: primitive values and reference values. Primitive values are simple atomic pieces of data, while reference values are objects that may be made up of multiple values.

Primitive types are accessed by value, and reference types are accessed by reference.

In ES6 we have 3 different ways of declaring variables.

  • var - has function scope, which means that if you declare it in a function it will be available everywhere inside that function. If you declare it on the global scope it will be available the variable will be accessible anywhere in the code.
  • let - has block scope, it will only be accessible in that code block.
  • const - Constants are block-scoped, much like variables defined using the let statement. The value of a constant cannot change through reassignment, and it can't be redeclared. You can still change the contents of the object if its a reference type.
const a = { 
    name = "Pedro"
}

a.name = "Nuno";
console.log(a.name) //Nuno

Copying Values

When a primitive value is assigned from one variable to another, the value stored on the variable object is created and copied into the location for the new variable.

var num1 = 5;

var num2 = num1;

Here, num1 contains the value of 5. When num2 is initialized to num1, it also gets the value of 5. This value is completely separate from the one that is stored in num1, because it’s a copy of that value.

When a reference value is assigned from one variable to another, the value stored on the variable object is also copied into the location for the new variable. The difference is that this value is actually a pointer to an object stored on the heap.

That makes the two variables point to exactly the same object, so changes to one are reflected on the other.

Scope and Context

Every function invocation has both a scope and a context associated with it. In javaScript, scope is function based.

  • Scope is related to the visibility of variables.
  • Context means

Execution Context

The execution context of a variable or function defines what other data it has access to, as well as how it should behave. Each execution context has an associated variable object upon which all of its defied variables and functions exist. This object is not accessible by code but is used behind the scenes to handle data.

When an execution context has executed all of its code, it is destroyed, taking with it all of the variables and functions defined within it (the global context isn’t destroyed until the application exits, such as when a web page is closed or a web browser is shut down).

When javaScript code runs its executed in one of 3 environment:

  • Global code - The default environment where the code is executed for the first time.
  • Function code - When the flow of execution enters a function.
  • Eval - Code to be executed inside an internal eval function.

You can have any number of function contexts, and each function call creates a new context, which creates a private scope where anything declared inside of the function can not be directly accessed from outside the current function scope. In the example above, a function can access a variable declared outside of its current context, but an outside context can not access the variables / functions declared inside.

  • Execution Context Stack

The JavaScript interpreter in a browser is implemented as a single thread. What this actually means is that only 1 thing can ever happen at one time in the browser, with other actions or events being queued in what is called the Execution Stack.

When the browser loads the script, it enters the global execution scope by default. When you call a function, a new execution context is created and pushed to the top of the Execution Stack. Once the function completes executing the current execution context, it will be popped off the top of the stack, returning control to the context below in the current stack.

  • Execution Context Detail

Everytime a function is called, a new execution context is created. However, inside the JavaScript interpreter, every call to an execution context has 2 stages:

  • Creation Stage - a) Creates the score chain, b) variables, functions and arguments c) Determines the value of this.
  • Activation / Code Execution - Assings values, references to functions and executes code.

It is possible to represent each execution context conceptually as an object with 3 properties:

executionContextObj = {
    'scopeChain' : { // variableObject + all parent execution context's variableObjects },
    'variableObject' : {// function arguments / parameters, variables and function declaration },
    'this' : {}
}

The javaScript interpreter evaluates the code as follows when a function is invoked :

Activation / Variable Object
  1. Creates the execution context.
  2. Create the variableObject
    1. Create the arguments objects, checks for parameters.
    2. Scan for function declarations, creates a property with the function name and pointer to the function in memory, if the function already exists its overwritten.
    3. Scan for variable declaration, creates a property with the name of the variable and the value of undefined.
  3. Determine the value of this.
Code Execution
  1. Run / interpret the function code in the context and assign variable values as the code is executed line by line.

If we have the following function :

function foo(i) {
    var a = 'hello';
    var b = function privateB() {

    };
    function c() {

    }
}

foo(22);

At creation stage the execution context looks the following, the way the interpreter works is the reason behind Hoisting :

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: undefined,
        b: undefined
    },
    this: { ... }
}

At execution stage :

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: 'hello',
        b: pointer to function privateB()
    },
    this: { ... }
}

results matching ""

    No results matching ""