I'm just a painter who studied computer science.

Alcance

Scope "Alcance"

El alcance(scope) decide a que variables tienes acceso en cada parte del codigo para ser utilizadas. Existen dos tipos de alcance, el alcance(scope) global y el alcance(scope) local.

Alcance(Scope) Local

Cuando puedes acceder a una variable únicamente en cierta parte del código, se dice que esa variable está declarada en el alcance local. Estas también son conocidas como variables locales. Un ejemplo de esto es cuando una variable está declarada dentro de un bloque o una función. Si tratas de acceder a esta variable fuera de esta función o bloque, tendrás un error que dirá que la variable no está definida.

  
  // Global Scope
  function greeting() {
    // Local Scope
    let name = "John";
    return "Hello " + name;
  }

  let fullGreeting = greeting();

  console.log(name);
  console.log(fullGreeting);
  //-> undefined
  //-> Hello John
  

Alcance(Scope) Global

Se dice que una variable está en el alcance global cuando está declarada fuera de una función o de un bloque. También son conocidas como variables globales. Puedes acceder a este tipo de variables desde cualquier parte de tu código, ya sea dentro o fuera de una función.

  
  // Global Scope
  let name = "John";

  function greeting(name) {
    // Local Scope
    return "Hello " + name;
  }

  let fullGreeting = greeting(name);

  console.log(fullGreeting);
  //-> Hello John
  

Alcance(Scope) de bloque

Un alcance de bloque es la sección dentro de las condiciones if, switch, o dentro de métodos de iteración como while. El concepto de bloque significa simplemente un conjunto de llaves de apertura y cierre {}. Estas palabras clave soportan la declaración de alcances locales dentro de bloque de instrucciones y tu como desarrollador puedes declarar variables que existen solamente dentro de un bloque específico.

Es importante entender que las variables var tiene alcance de función (global o local), y las variables let y const tienen alcance de bloque.

  
  var age = 2;

  if(age == 2) {
    var toddleAge = age * 2;
    console.log(`My son age is: ${toddleAge}`)
  }

  console.log(toddleAge); 
  //-> My son age is: 4
  //-> 4
  
  
  var age = 2;

  if(age == 2) {
    let toddleAge = age * 2;
    console.log(`My son age is: ${toddleAge}`)
  }

  console.log(toddleAge); 
  //-> My son age is: 4
  //-> Uncaught ReferenceError: toddleAge is not defined
  

Cadena de alcance(Scope chain)

Para que entendamos el concepto vamos al siguien ejemplo, cuando invocamos una funcion, dentro de esta funcion se forma un contexto de ejecucion, en donde parte de sus fases esta colocar en memoria y leer variables que esten en dicho contexto. Digamos que en esta fase de ejecucion de contexto no encuentra una variable dentro de su propio alcance(Scope), pues automaticamente buscara en su outter enviroment las variable que necesite. a esto se le llama cadena de alcance (Scope chain).

Palabra reservada this

Esta palabra reservada dentro del codigo, su valor hace referencia al propietario de la funcion que la estas invocando o en su defecto, al objeto donde dicha funcion es un metodo. Para entender de donde toma this su valor, hay que saber que su valor dependera de como es ejecutada la funcion en donde se encuentra.

Dentro de una funcion

Cuando la funcion no es parte del prototipo de una funcion constructora, el valor de this sera igual al objeto window, importante que esto es asi aunque sea un Closure "Clausura"

  
  function a() {
    var c = function c() {
      console.log(this === window); //-> true
    }

    setTimeout(function b() {
      console.log(this === window); //-> true
    });

    c();
    console.log(this === window);
  }

  a();
  

Dentro de un metodo

Cuando se usa this dentro de un metodo, el valor de this sera equivalente al elemento en el que se ejecuta al metodo.

  
  const Person = {
    sayHi() {
      console.log(this === Person); //-> true
    }
  }

  Person.sayHi();
  

Dentro de un constructor o metodo

En este caso, this siempre hara referencia a la instancia.

  
  function Person() {}

  Person.prototype.sayHi = function() {
    console.log(this === Person); //-> false
    console.log(this instanceof Person); //-> true
  }

  const person = new Person();
  person.sayHi();
  

Usando bind, call o apply

Para sobreescribir el valor de this, podemos hacerlo de manera dinamica utilizando las funciones bind, call y apply

  
  function greeting(age) {
    console.log(`Hello, i'm ${this.name} and I have ${age} years old.`)
  }

  const john = { name: "John Doe" }
  const jane = { name: "Jane Doe" }
  const josh = { name: "Josh Smith" }

  greeting.bind(john)(24) //-> Hello, i'm John Doe and I have 24 years old.
  greeting.call(jane, 23) //-> Hello, i'm Jane Doe and I have 23 years old.
  greeting.apply(josh, [25]) //-> Hello, i'm Josh Smith and I have 25 years old.