Execution Contexts


    Execution Context
    • A box, container, which stores variables and in which a piece of our code is evaluated and executed.

    Global Execution Context
    • Code that is not inside any function.
    • Tudo o que é escrito dentro desse Global Execution Context, é referênciado para o object window.
    • Tudo o que está presente no object window é aplicado ao browser.

      Exemplo: lastName === window.lastName
      Nesse caso, seria a mesma coisa declarar o lastName direto porque ele seria declarado no escopo global, ou seja, no window object, assim como window.lastName.

    Execution Stack
    • Começamos com as variáveis que estão no Global Execution Context.
      Dentro das funções, pode-se haver códigos.
      Quando se executa um desses códigos, um novo Execution Context é criado e os códigos dessa função são reproduzidos ali.
      Quando a função der um retorno, esse Execution Context é excluído.
      Caso dentro de uma função, chame-se outra função, será criado um novo Execution Context para essa função, e permanecerá até que haja o return de informações (finalização dos códigos dentro da função).
    • Exemplo:
      var name = 'John'; Global Execution Context

      function first() { Global Execution Context
        var a = 'Hello!'; 1st Execution Context Created (1st Function)
        second(); 2nd Execution Context Created (2nd Function)
        var x = a + name; Quando chegar aqui, encerra-se o 1st Execution Context
      ...
      ...
      first();

    Execution Context in Detail
      Etapas
      img-fluid
      Possibilidades
    • Function Hoisting - Only works for function declarations

      // Function Declaration
      É possível colocar o calculateAge antes da function pois:
      1)JS irá escanear todo o código e ver que existe essa function.
      2)O calc age e o function serão armazenados no escopo global, portando, quando chamar a function antes da sua declaração, o JS irá buscar essa function no Global Execution Context, portanto ela estará visível e acessível de qualquer lugar do código.

      calculateAge(1990);

      function calculateAge(year) {
      console.log(2018 - year);
      }

      // Function Expression
      Hosting não funciona

      retirement(1990);

      var retirement = function(year) {
      console.log(65 - (2018 - year));
      }

    • Variables Hoisting
      The code is scanned for variables declarations and then they are set to undefined.

      console.log(age); //nessa linha ela aparece undefined, pois ele vai escanear e saber que ela existe, porém ainda não analisou o valor. Caso ela não existisse, daria erro.
      var age = 23; Global Execution Context

      function foo() { Global Execution Context
      var age = 65; Execution Context
      console.log(age); Execution Context
      }

      foo(); Retorno do Execution Context
      console.log(age); Valor da variável global do Global Execution Context
      //Resultados:
      //undefined
      //65
      //23

      1) Será exibida a var age de 65, pois foi chamada antes. Essa será analisada dentro de um Context Execution e então o valor final dessa funcão será retornado com o 65.
      2) A variable 23 é armazenada no Global Execution Context, então ela será acessível diretamente no escopo global.

    Lexical Scoping - Como funciona os scope
      img-fluid
      * VO = Variable Object

    • A função first() possui dois escopos, o primeiro com a var b e o segundo, da function second(), contendo a var c e etc.
    • Os escopos possuem acesso a todos os elementos externos de onde ele está até chegar no Global.
    • Portanto, nesse caso, quando chegar em console.log(a + b + c), somente teremos a variável C nesse escopo, e com isso o JS irá buscar no elemento parent, encontrando B e depois no parent novamente, encontrando A.
    • O Global Scope não tem acesso aos escopos internos, como por exemplo, variáveis definidas dentro de uma função, a não ser que retornemos os valores das funções.

    Diferença entre Execution Context e Scoping
      img-fluid
    • A função first() possui acesso as variáveis: B (definida nela) e A (global).
    • A função second() possui acesso as variáveis: C (definida nela), B (parent element), e A (global).
    • A função third() possui acesso as variáveis: D (definida nela) e A (global).
    • *** Veja que dentro da function second() é possível se chamar a function third(), visto que o JS vai procurar nos parents, chegando no Global e encontrando a function third().

    The "this" keyword
    • Regular function call: the "this" keyword aponta para o global object, ou seja, the window object, no browser.
      Exemplo: se colocar console.log(this) no começo do código, ele irá mostrar o conteúdo do object window, pois esse é o default.
      ** Caso escreva uma função que não seja um método (que não tenha um objeto), e inserir o console.log(this) dentro dela, ainda será utilizado o window object, como no caso abaixo:
      calculateAge(1969);
      function calculateAge(year){
        console.log(2018 - year);
        console.log(this);
      }
      Será exibido o calculo da idade e o object window (Window {speechSynthesis...}).

    • Method call: the this variable points to the object that is calling the method.
      Nesse caso, o "this" aponta para o objeto que está chamando o método.
      Exemplo:
      Object: jessica, chamando o método function.
      var jessica = {
        name: 'Jessica',
        lastName: 'Pearson',
        yearOfBirth: 1969,
        calculateAge: function() {
          console.log(this); exibe todos os dados do objeto Jessica (Object {name: "Jessica", lastName: "Person"...}).
          console.log(2016 - this.yearOfBirth); exibe o cálculo da idade.
          function innerFunction(){
           console.log(this); exibe o object window, pois está dentro de uma Function Declaration e não um Method (objeto).
          }
          innerFunction();
        }
      }
      john.calculateAge();

    • The this keyword is not assigned a value until a function where it is defined is actually called.
      Exemplo:
      var mile = {
        name: 'Mike',
        yearOfBirth: 1990,
      };

      mike.calculateAge = jessica.calculateAge; This is called Method Borring, onde queremos que o mike.calculateAge seja igual ao da Jessica.
      mike.calculateAge();
      Resultado: aqui teremos exibido o Object {name: "Mike", yearOfBirth: 1990} e então a idade de Mike.
      Isso ocorre porque dentro da function calculateAge do objeto Jessica, temos o console.log(this).
      Visto que o value de this somente é atribuido quando um método o chama, ele exibira os dados do objeto Mike, visto ter sido chamado por ele, mesmo estando dentro de uma função no objeto Jessica.