"this" Palabra reservada

Contexto de ejecucion

Cuando el codigo de JavaScript se ejecuta, el ambiente que rodea al codigo es bien importante. Este ambiente evalua el codigo de la siguiente manera:

  • Codigo es global - por defecto este es el ambiente el cual el codigo se ejecuta por primera vez.
  • Codigo en funciones - cuando por medio del flujo de la aplicacion se entra al bloque o cuerpo de una funcion, aqui se crea un nuevo contexto de ejecucion que pertenece a la propia funcion.

  • Codigo en funcion eval() - texto al ser ejecutado dentro del la funcion eval. eval() es una funcion global en JavaScript que nos permite evaluar y ejecutar cierto codigo por media de cadena de caracteres.

var result;

function Sum(val1, val2) {
  return val1 + val2;
}

eval("result = Sum(5, 5);");

console.log(result); //-> 10

El interpretador de JavaScript en el navegador web es un solo hilo "single thread", secuencia de tareas encadenadas muy pequeña que solo son ejecutadas una a la vez. Mientra una tarea es ejecutada, existen otras acciones o eventos en espera a ser llamadas y ejecutada a esto se le conoce como pila de ejecucion "execution stact".

Cuando el navegador web carga el codigo, este entra al contexto de ejecucion global, luego si llamas alguna funcion, en la siguiente secuencia se desarrolla un nuevo contexto de ejecucion para esa funcion llamada y empuja ese contexto a la parte superior de la pila de ejecucion. Si llamas otra funcion, vuelve a suceder el mismo proceso, el navegador va ejecutado contexto que van apareciendo en la parte superior de la pila y una vez terminada, la elimina pasando a la proxima o volviendo al contexto de ejecucion global.

                         +----------------------------------+  ^  +
                         |                                  |  |  |
Ejecucion activa   +---> |   Actual contexto de ejecucion   |  |  |
                         |                                  |  |  |
                         +----------------------------------+  |  |
                                                               |  |
                         +----------------------------------+  |  |
                         |                                  |  |  |
                         |   Contexto de ejecucion N + 2    |  |  |
                         |                                  |  |  |
                         +----------------------------------+  |  |
                                                               |  |
                         +----------------------------------+  |  |
                         |                                  |  |  |
                         |   Contexto de ejecucion N + 1    |  |  |
                         |                                  |  |  |
                         +----------------------------------+  |  |
                                                               |  |
                         +----------------------------------+  |  |
                         |                                  |  |  |
Siempre en el fondo +--> |   Contexto de ejecucion global   |  |  |
                         |                                  |  |  |
                         +----------------------------------+  +  v

Cada vez que se llama un nuevo contexto de ejecucion, este pasa por dos etapas, Creacion y Ejecucion.

  • Fase Creacion:

    • ThisBinding - en este proceso, solo se define el valor de la palabra reservada this, al contexto de ejecucion actual.
    • Ambiente Lexico "LexicalEnvironment" - basicamente este es el proceso el cual la maquina o sistema busca por las variables definida o declaradas en el codigo. Existen dos definiciones de sub-procesos en este proceso:

      • Asociaciones de identificador - simplemente se enlaza variables y funciones definidas o declaradas.
      • Estructura lexica - es la descripcion actual de donde se encuentra el codigo escrito. Esto ayuda a indicar que variables y funciones definidas o declaradas van con quien y a que ambiente lexico pertenece.

      Con el ambiente lexico se encuentra dos componentes:

      • Registro del ambiente "Enviroment record" - es el lugar donde las variables y funciones son guardadas.
      • Referencia al ambiente externo - es la manera de la maquina encontrar y de identificar alcanze "Scope" fuera de su alcanze local.
    • Ambiente variable "VariableEnviroment" - esto es una copia exacta del ambiente lexico.
  • Fase Ejecucion:
    • Aqui en esta fase solo el interpretador va enlazando la palabra reservada this al ambiente lexico y ambiente de variable y luego el codigo es ejecutado.

Levantamiento "Hoisting"

Es parte del proceso de ejecucion el cual coloca todas las variables o funciones definidas a la parte superior del codigo escrito, esto sucede dentro del interpretador independientemente como este escrito el codigo.

"this"

Es un valor atado al contexto de ejecucion en el momento activa y dependiendo como es llamado ese contexto o funcion el valor de this varia.

  • Contexto global - el valor de this bajo este contexto por defecto es el objeto window, este es global.
  • Construccion de objecto - cuando creas un objeto mediante el uso de la palabra reservada new, el valor de this hace referencia a la instancia.
function Human (age) { 
  this.age = age 
}

let greg = new Human(22) 
let thomas = new Human(24) 

console.log(greg) //-> this.age = 22 
console.log(thomas) //-> this.age = 24
  • Metodo de objeto - este hace referemcia al mismo objeto el cual se encuentra el metodo.
function Human(name) { 
  return { 
    name, 
    getName() { 
      return this.name 
    } 
  } 
}

const zell = new Human('Zell') 
console.log(zell.getName()) //-> Zell
  • Simple funcion - en este caso el valor de this hace referencia a window, contexto global, lo mismo ocurre si llamas a funcion dentro de objeto.
function simpleFunction () { 
  console.log(this) 
} 

const o = { 
  sayThis () { simpleFunction() } 
}

simpleFunction() //-> [object Window] 
o.sayThis() //-> [object Window]

Una manera de atar el valor de this dentro del contexto de la objecto es definiendo y asignando this a una variable dentro del objeto.

function simpleFunction () {
  let self = this;
  console.log(self) 
} 

const o = {
  sayThis () {
    let self = this;
    console.log(self) 
  } 
}

simpleFunction() //-> [object Window] 
o.sayThis() //-> sayThis
  • Eventos del documento - el valor de this en este caso es atado al elemento el cual provoca que el evento ocurra.
// let's assume .elem is <div class="elem">Element</div>
var element = document.querySelector('.elem');

var someMethod = function () {
  console.log(this);
};

element.addEventListener('click', someMethod, false); //-> <div class="elem">Element</div>

Cambio de contexto del this

En JavaScript existen momento que queremos utilizar cierta funciones, pero con diferente contexto. Para estos casos tenemos los siguientes metodos .call, .apply y .bind

.bind

.bind es un metodo que contiene todas las funciones de JavaScript que nos permite cambiar el contexto de this de la funcion a otro contexto.

var human = {
  firstName: 'John',
  lastName: 'Den ',
  getName: function() {
    var fullname = this.firstName + ' ' + this.lastName;
    return fullname;
  }
};

var humanName = function() {
  console.log(this.getName() + 'I choose you!');
};

var logHuman = humanName.bind(human); 
// creates new object and binds human. 'this' of human === human now

logHuman(); //-> John Den I choose you!

mas ejemplos:

var obj = {
  objName: 'John Doe',
  getObjName: function(){
    return this.objName;
  }
} 

var greetObj = function(){
  console.log("Hello " + this.getObjName());
}

var newObj = greetObj.bind(obj);
newObj(); //-> Hello John Doe

.call y .apply

Estos dos metodos nos permite invocar una funciones y cambiar el contexto pasandolo como primer argumento el contexto de ejecucion.

var human = {
  firstName: 'John',
  lastName: 'Den ',
  getName: function() {
    var fullname = this.firstName + ' ' + this.lastName;
    return fullname;
  }
};

var humanName = function(snack, hobby) {
  console.log(this.getName() + 'loves ' + snack + ' and ' + hobby);
};

humanName.call(human, 'suchi', 'video games'); //-> John Den loves suchi and video games
humanName.apply(human, ['burger', 'tv show']); //-> John Den loves burger and tv show

mas ejemplos:

// Example 1:
var sayHi = function(who){
  return "Hello" + (who ? ", " + who : "") + "!";
};

console.log(sayHi()); //-> Hello!
console.log(sayHi('World')); //-> Hello, World!
console.log(sayHi.apply(null,["Jack"])); //-> Hello, Jack!

// On this case first argument is null, this target to global object.
var alien = {
  sayHi: function(who){
    return "Hello" + (who ? ", " + who : "") + "!";
  }
};

console.log(alien.sayHi("Alien")); //-> Hello, Alien!
console.log(sayHi.apply(alien,["John"])); //-> Hello, John!
console.log(sayHi.call(alien,"Peter")); //-> Hello, Peter!

// Example 2:
name = 'Default';
var person1 = {name: 'Marvin'};
var person2 = {name: 'Zaphod'};

var sayHello = function(){
  console.log('Hello, ' + this.name);
};

var sayGoodbye = function(){
  console.log('Goodbye, ' + this.name);
};

sayHello(); //-> Hello, Default
sayGoodbye(); //-> Goodbye, Default

sayHello.call(person1); //-> Hello, Marvin
sayGoodbye.call(person2); //-> Goodbye, Zaphod

sayHello.apply(person1); //-> Hello, Marvin
sayGoodbye.apply(person2); //-> Goodbye, Zaphod

results matching ""

    No results matching ""