El contexto (o alcance) de una función es por lo general, window. Así que en ciertos casos, cuando intentamos referirnos a this en alguna parte del código, es posible que tengamos un comportamiento inesperado, porque el contexto quizás no sea el que esperamos.
Existen al menos tres maneras de cambiar el contexto de una función.
Usando el método .bind, enviamos la referencia a la función sin ejecutarla, pasando el contexto como parámetro.
Usando el método .call, ejecutamos inmediatamente la función con el contexto indicado
Usando el método .apply, es similar a .call pero los parámetros adicionales se pasan como un arreglo de valores
Resumen de la clase Cambiando el contexto al llamar a una función
El contexto en javascript está definido por el objeto ‘this’ cuando se ejecuta un código.
Es muy común el error: ‘No se puede ejecutar este método porque es indefinido’, esto sucede porque el ‘this’ no es quien esperamos que sea.
Dado el siguiente código:
const pablo ={nombre:'Pablo',apellido:'Andrés',}const mariela ={nombre:'Mariela',apellido:'Riesnik',}functionsaludar(){console.log(`Hola, mi nombre es ${this.nombre}`)}// Si ejecuto:saludar()// Hola, mi nombre es undefined// Ya que tenemos la función definida dentro de un contexto global el 'this' en saludar() refiere al objeto 'window'. Por lo tanto es lo mismo que:window.saludar()// Hola, mi nombre es undefined
Cómo hacemos para cambiar ese ‘this’ de la función?
El método ‘.bind()’ se usa justamente para cambiar en contexto, el ‘this’, en una función.
‘.bind()’ nos devuelve una nueva función atando el parámetro,_ ‘(pablo)’_ en este caso, al ‘this’ dentro de esa función, saludar en este caso.
Este nunca modifica a la función original.
saludarAPablo()// Hola, mi nombre es PablosaludarAMariela()// Hola, mi nombre es Mariela
functionsaludar(saludo ='Hola'){console.log(`${saludo}, mi nombre es ${this.nombre}`)}setTimeout( saludar.bind(pablo,'Hola loco!'),1000)// Hola loco!, mi nombre es Pablo//también se puede agragar en la declaración de la constante.const saludarAPablo = saludar.bind(pablo,'Hola loco!!')// Hola loco!!, mi nombre es Pablo
El primer parámetro es el contexto y luego van los siguientes parámetros en el orden en el que aparezcan.
IMPORTANTE!!!
La función .bind() no ejecuta la función a la que se agrega, sino que simplemente nos retorna una nueva función con ese contexto cambiado.
Usando el método .bind, enviamos la referencia a la función sin ejecutarla, pasando el contexto como parámetro.
Otros dos métodos que nos sirven para cambiar el contexto son: .call y .apply.
Usando el método .call, ejecutamos inmediatamente la función con el contexto indicado.
saludar.call(pablo)// Hola, mi nombre es Pablo - se ejecuta inmediatamentesaludar.bind(pablo)// no produce ningún resultado, no la ejecuta.
Al .call le pasamos los parámetros separados por ‘,’ igual que en el .bind.
saludar.call(pablo,'Hola cheeee!!')// Hola cheeee!!, mi nombre es Pablo
Usando el método .apply, es similar a .call pero los parámetros adicionales se pasan como un arreglo de valores.
saludar.apply(pablo,['Hola mi querido'])// Hola mi querido, mi nombre es Pablo
Manejar a dónde refiere el ‘.this’ es algo que tenemos que tener muy presente, sobretodo cuando escribimos en modo asíncrono, ya que siempre que ejecutemos una función de esta naturaleza el ‘.this’ siempre cambia y es muy importante atarlo a nuestra clase, objeto o función.
Genio!
Genial explicación ya me quedo mas claro como funciona this....
Este tema lo hubieran puesto antes de hacer el juego
Totalmente de acuerdo, el juego fue un quebradero de cabeza y muchas cosas no se entendieron hasta estos videos. De hecho se nota el salto en las clases
si pero bueno,los curiosos tienen la opcion de ir y buscar mas info....
++RESUMEN DE LA CLASE++
Declaramos dos objetos (fernando y yesika) que cada uno tiene dos atributos (nombre y apellido).
const fernando ={nombre:' Fernando',apellido:'Huaman'}const yesika ={nombre:' Yesika',apellido:'Cortés'}
Lo que vamos a aprender hoy es saber indicarle a la función quien es el this a la hora de invocarla.
Para eso declaramos una función Saludar que recibe como parámetro a saludo que es igual a Hola.
functionSaludar(saludo='Hola'){console.log(`${saludo} mi nombre es ${this.nombre}`)}
A pesar de que el parámetro saludo es igual a Hola es posible cambiar su valor desde la invocación de la propia función.
Si en caso no hagas eso , su valor seguirá siendo Hola.
Si invocamos de frente la función Saludar , el this no va a saber quién es , por lo que va a tomar como referencia el objeto window.
Saludar()
Hola mi nombre es undefined
Si queremos indicarle al this quién es, tenemos tres métodos:
++PRIMER METODO:++
Hacemos uso del método bind() que tiene como estructura ---> NombreFuncion.bind( NombreObjeto ).
Si en caso la funcion tuviera parametros, podemos utilizar la siguiente estructura ---> NombreFuncion.bind( NombreObjeto , ValorParametro1 , ValorParametro2 , ...)
Para poder invocar la función:
El método bind() debe estar almacenado en una variable , ya sea var , const o let, y luego debe ser invocado dicha variable como una función ---> NombreVariable()
++SEGUNDO MÉTODO:++
Hacemos uso del método call() que tiene como estructura ---> NombreFuncion.call( NombreObjeto ).
Si en caso la funcion tuviera parametros, podemos utilizar la siguiente estructura ---> NombreFuncion.call( NombreObjeto , valorParametro1 , valorParametro2, ...)
Este método call() es mas dinámico pues no hay que ser tanto proceso como el método bind() y solo con una de las estructuras que pongas en el código ya estarías invocando de frente la función e indicándole al this que objeto va a tomar como referencia.
Saludar.call(fernando,'Hola che,')
++TERCER MÉTODO:++
Hacemos uso del método appy() que tiene como estructura ---> NombreFuncion.apply( NombreObjeto ).
Si en caso la función tuviera parámetros, podemos utilizar la siguiente estructura ---> NombreFuncion.apply( NombreObjeto , [valorParametro1 , valorParametro2, ...])
Es muy parecido con el metodo call() , en lo que cambia es cuando vayas a indicar valores de los parámetros pues estos tienes que ponerlos en orden y dentro de un array.
Saludar.apply(fernando,['Hola che'])
#Bien
perfecto gracias
.bind(objeto, parámetros)
No ejecuta la función, solo retorna la función atada al objeto indicado
.call(objeto, parámetros)
Ejecuta la función y también ata la función al objeto indicado. De igual manera recibe los parámetros separados por comas
.apply(objeto, [parámetros])
Funciona casi de la misma manera que .call(), con la diferencia que recibe los parámetros en un array.
Buen aporte, gracias
Gracias equipo Platzi por tan excelente curso.
Les dejo lo que aprendí en esta clase
const lis ={nombre:'Lissette',apellido:'Garzon'}const anton ={nombre:'Antonio',apellido:'Cortes'}functionsaludar(saludo ='Hola'){console.log(`${saludo}, mi nombre es ${this.nombre}`)}// saludar(lis) //esto da Hola, mi nombre es undefined// const saludoLis = saludar.bind(lis) //no se ejecuta saludar hasta que llame a saludoLis que la refernciaconstsaludando=(persona,saludo)=> saludar.bind(persona,saludo)saludando(lis)()saludando(anton,'Hola che')()setTimeout(()=>saludando(anton,'che')(),1000) saludar.call(lis,'Hola wey')//parametros separados por coma saludar.apply(anton,['Hola amigo'])//parametros dentro de un arreglo separados por coma
Muy claro el código y tus apuntes, me encanta!
Está muy bueno el curso, pero yo que vengo de casi nada de conocimientos de programación, me cuesta entender aún varias de estas lógicas. Me recomiendan libros para estudiar, para acompañar estas clases prácticas?
Hola Ariel
La verdad de libros sobre el tema no sé mucho, pero si te puedo recomendar unos cursos que te pueden servir muchísimo, los puedes tomar en Platzi o en cualquier otro lugar de internet.
Curso de Programación Estructurada
Curso de Programación orientada a Objetos (POO)
Con esos conocimietos vas a tener unas bases muy sólidas para aprender a programar en cualquier lenguaje de programación.
Dale Gracias!
.bind: Enviamos la referencia a la función, pasando el contexto como parámetro.
.call : Ejecutamos inmediatamente la función con el contexto indicado.
.apply : similar a .call pero los parámetros adicionales se pasan como un arreglo de valores
Útil para debuggear y acabar con los dolores de cabeza
Preguntarte siempre ¿Quien es el this de la función? para evitar bugs
bind, call y apply son propios de ES6?
Siento que debe de haber una mejor conducción de este curso, se pasan muchas cosas por encima y no al detalle antes de realizar el proyecto del curso
Creo que se debe a que el curso es "Fundamentos de JavaScript" y es como básico, hay otro "Curso Profesional de JavaScript" que deben abordar los temas más a fondo supongo (cuando lo curse lo sabré).
Es cierto, hay un salto a la hora de hacer el juego.
Para mí, además de las cosas nuevas que aparecen de golpe ahí y que casi ni se explican, esta toda **la lógica **la cual vi como un espectador, sin poder involucrarme a fondo con ella. Aunque hice el juego y hasta por mi cuenta le agregué efectos de sonido, creo que voy a tener que ver nuevamente esos videos varias veces para profundizar toda la lógica desarrollada.
Yo concuerdo, me gustó mucho el .call()
Estoy usando apply, pero a la hora de meter más parámetros, no los "acepta" y solo me ejecuta el primero.
Los parámetros los estas incluyendo dentro de un arreglo?
quizás sea por eso.
¿La diferencia entre call y apply solo es de sintaxis? o hay una alguna diferencia mas
Es correcto.
Solo la forma como se pasan los argumentos, pero hacen lo mismo.
No sé por que siento que es algo medio forzado para algo que se podria solucionar incluyendo la function en una clase y crear el objeto a partir de ella, o pasando el objeto a usar como parametro a la misma.
Creo que es sobre todo para cuando se llama a funciones asincronas, porque se pierde el contexto.
Hola @pablopelaez92,
Es evidente que este es un ejemplo básico para ver el funcionamiento de cada uno de los elementos con los que podemos trabajar el contexto de una función.
Y sí, tal cual dice Jochimin muy probablemente uses más este tipo de métodos con funciones asíncronas, es decir dónde no puedas incluir la función en las clases.
Espero haber podido ayudar a poner un poco más de pensamiento.
Saludos.
Ya estoy entendiendo mucho mas el this
Creo que lo mejor es el uso de call o apply de acuerdo a las necesidades. Pero todo dependera.
const fran ={nombre:'Francisco',apelli:'Garcia',edad:52}const juanda ={nombre:'Juan David',apelli:'Garcia',edad:19}functionsaludar(saludo ='Hola'){console.log(`${saludo}, mi nombres es: ${this.nombre}`)}//cuando se ejecuta asi, el this hace referencia a window, ya que es window quien esta ejecutando la funcion//pero esto no es lo mejor,const saludarAFran = saludar.bind(fran)const saludarAJuanda = saludar.bind(juanda)//es una alternativasetTimeout(saludar.bind(fran,'Hola Che'),2000)setTimeout(saludar.bind(juanda,'Hola parce'),3000)//pero me parece optimo asi saludar.call(fran) saludar.call(juanda) saludar.call(juanda,'Hola che') saludar.call(fran,'Hola parce')//pero claro todo depende de lo que se necesite, como es el caso de apply saludar.apply(fran,['Hola che']) saludar.apply(juanda,['Hola parce'])
Existen al menos tres maneras de cambiar el contexto de una función.
Usando el método .bind, enviamos la referencia a la función sin ejecutarla, pasando el contexto como parámetro.
Usando el método .call, ejecutamos inmediatamente la función con el contexto indicado
Usando el método .apply, es similar a .call pero los parámetros adicionales se pasan como un arreglo de valores
entendí el bind con el call y el apply :D genial
estaba un poco perdida cuándo lo vimos en clase.
.bind() => solo devuelve el contexto cambiando el this, esté no ejecuta la función,
.call(functionName, params) => cambia el contexto y ejecuta la función, está recibe los parámetros de forma normal
.apply(functionName, [params]) => cambia el contexto y ejecuta la función, está recibe los parámetros en forma de arreglo