Foros del Web » Programando para Internet » Javascript »

closures

Estas en el tema de closures en el foro de Javascript en Foros del Web. Hola, estoy leyendo sobre closures, y he dado con un blog donde una amable muchacha parece saber explicar las cosas, y me estaba enterando bien ...
  #1 (permalink)  
Antiguo 08/12/2009, 11:47
Avatar de PacoRuiz  
Fecha de Ingreso: abril-2009
Mensajes: 254
Antigüedad: 15 años
Puntos: 3
closures

Hola, estoy leyendo sobre closures, y he dado con un blog donde una amable muchacha parece saber explicar las cosas, y me estaba enterando bien del tema pero hay algo que no entiendo, dice esta chica:


Cita:
Pero hay otra característica especial que tienen los closures (que los diferencian de cualquier otra función o bloque de código). Como ya sabemos, cuando una función finaliza su ejecución, todas las variables locales (dentro de su scope) se liberan. Sin embargo, miren esto:

function unaFuncionCualquiera() {

var variableExterna = "soy una linda variable local de unaFuncionCualquiera()";

var unLindoClosure = function() {

alert("Hola soy un lindo closure y puedo acceder a variables fuera de mi scope, miren: " + variableExterna);

}

return unLindoClosure;

}

var test = unaFuncionCualquiera();

test();

La variable test guarda el valor de retorno de la llamada a unaFuncionCualquiera(), es decir un puntero al closure unLindoClosure. Cuando se llama a test() se llama al closure. Sin embargo, para este entonces la función unaFuncionCualquiera() ya terminó su ejecución, y todas sus variables locales (como variableExterna) deberían haber sido liberadas (como pasa con todas las variables locales a una función después de que esta finaliza). Sin embargo, si prueban el código, verán que esto no pasó, y el closure ejecuta un alert mostrando el contenido de la variable variableExterna que se supone que debería haber sido liberada al terminar la ejecución de unaFuncionCualquiera().
Lo que no entiendo es cuando dice que para este entonces la función unaFuncionCualquiera() ya terminó su ejecución. Se supone que unLindoClosure está dentro de unaFuncionCualquiera(), por lo tanto unaFuncionCualquiera() no puede terminar su ejecución mientras no termine todo su código, incluído unLindoClosure. O sea que según yo lo veo unLindoClosure no podría jamás ejecutarse habiéndose terminado la ejecución de unaFuncionCualquiera().
  #2 (permalink)  
Antiguo 08/12/2009, 11:56
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: closures

lo que sucede es que unLindoClosure() no se esta ejecutando dentro unaFuncionCualquiera() solo se esta devolviendo con return, y bien... tampoco se devuelve la ejecución del closure, solo su implementación...

cuando asignamos una función closure a una variable, esto no quiere decir que se ejecute.... eso es propio de Javascript, y similares... no se que tiene que ver con PHP, pero...

Código:
var foo = function() {alert('bar');};

alert(foo); // var foo = function() {alert('bar');};
alert(foo()); // aqui si se ejecuta la funcion
ya que lo que se hace, primero es una copia de las variables del scope de unaFuncionCualquiera() dentro del scope de unLindoClosure() y solo se devuelve la implementación, el código... no la ejecución del código

simplemente deberías leer referencias oficiales, al respecto de PHP también existen... pero se manejan de forma distinta...

por favor, lee un manual...

suerte!!
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #3 (permalink)  
Antiguo 08/12/2009, 12:14
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Tema movido desde PHP orientado a objetos a Javascript
  #4 (permalink)  
Antiguo 08/12/2009, 12:22
Avatar de PacoRuiz  
Fecha de Ingreso: abril-2009
Mensajes: 254
Antigüedad: 15 años
Puntos: 3
Respuesta: closures

Quiero entender el concepto de closure en general, y he dado con ese tutorial que era con javascript. No me he dado cuenta de ese detalle al meter el tema y lo he metido en php. Imagino que lo que estoy planteando es general y no importa el lenguaje.

No entiendo bien eso de que devuelve la implementación no la ejecución. Devuelve el resultado de la función, ¿No? El valor de la variable. ¿A eso se le llama implementación? Pero para calcularlo debe ejecutarse la función. No se devuelve la ejecución pero se ejecuta.

No entiendo cómo puede devolverse una función (un resultado de una función) con return sin ejecutarse.
  #5 (permalink)  
Antiguo 08/12/2009, 12:56
Avatar de PacoRuiz  
Fecha de Ingreso: abril-2009
Mensajes: 254
Antigüedad: 15 años
Puntos: 3
closures

Hola,

Sé que he puesto hace poco un tema similar, pero me da la sensación de que lo que no entiendo se debe a algún error de concepto que tengo, y que quizás no quede muy claro en el otro tema.

He leido esto:

Cita:
Closures
Es decir, tomemos un ejemplo como este (un clásico xD):

function crearContador() {
var c = 0;
function f() {
c = c + 1;
return c;
}
return f;
}
var contador1 = crearContador();
alert(contador1()); // 1
alert(contador1()); // 2
alert(contador1()); // 3

crearContador es una función que nos va a devolver otra función. Hasta aquí nada nuevo. Pero observemos qué pasa con la variable c. c está definida con un alcance local dentro de crearContador. Es decir, que una vez que hemos salido de crearContador, y tal como vimos en el primer artículo, c ya no es accesible, no es visible. Está, decimos, fuera del alcance.

Sin embargo, hay dos detalles a tener en cuenta:

Cuando definimos la función f, la variable c sí que está dentro del alcance. Está en su mismo contexto de definición. Luego esa referencia a c dentro de f debería ser válida.
Cuando finalmente ejecutamos la función contenida en contador1 observamos por el resultado que la referencia está efectivamente siendo válida.
¿Qué es lo que ocurre? Lo que ocurre es (redoble de tambor) .....
No entiendo qué tiene de raro que la referencia siga siendo válida. Yo lo veo así:

la instrucción alert(contador1()); ejecuta la función CrearContador(), y ésta.. ah, creo que ahora lo veo, ésta devuelve el código de la función f() pero no la ejecuta dentro de CrearContador() sino fuera, y esto es lo que hace raro que c siga siendo válida ¿no?

O sea que no devuelve el valor del resultado de f() sino el propio código de la función. ¿Eso es?

Última edición por PacoRuiz; 08/12/2009 a las 13:02
  #6 (permalink)  
Antiguo 08/12/2009, 14:45
Avatar de caricatos
Moderador
 
Fecha de Ingreso: abril-2002
Ubicación: Torremolinos (Málaga)
Mensajes: 19.607
Antigüedad: 22 años
Puntos: 1284
Respuesta: closures

Temas unidos

PacoRuiz: No está bien que abras nuevos temas sobre el mismo problema... puedes intentar expresarte mejor respondiendo en el mismo...

Saludos
__________________
Por favor:
No hagan preguntas de temas de foros en mensajes privados... no las respondo
  #7 (permalink)  
Antiguo 08/12/2009, 15:53
Avatar de Panino5001
Me alejo de Omelas
 
Fecha de Ingreso: mayo-2004
Ubicación: -34.637167,-58.462984
Mensajes: 5.148
Antigüedad: 20 años
Puntos: 834
Respuesta: closures

Siempre es este un tema difícil de entender, pero se lo puede simplificar viendo cómo funciona el contexto global del objeto window. Por ejemplo, si tenemos esto, el resultado es predecible ya que estamos más acostumbrados a que las cosas sucedan así y por lo tanto todo es más intuitivo:
Código PHP:
var n=0;
function 
contador2(){
    
alert(++n);
}
contador2();
contador2();
contador2(); 
Como n está definida fuera de la función y es global, cada vez que invoquemos a la función estaremos modificando el valor de n. A eso estamos acostumbrados normalmente.
En cambio, si tenemos esto:
Código PHP:
alerta=function(){
    var 
contador=0;
    return function(
m){
        
alert('mensaje '+(++contador)+':'+m);
    }
}();
alerta('algo');
alerta('algo');
alerta('algo');
alerta('algo'); 
Ya la cosa puede ser más difícil de predecir. Pero, si asimilamos a la función anónima que envuelve a la segunda función como un contexto semejante a window, seguramente entenderemos que cada vez que se invoque a la función interna estaremos modificando el valor de la variable contador, ya que esa variable, para la función interna, es global. Cada vez que llamamos a la función alerta en realidad estamos llamando a la función interna, pero en su propio contexto: un contexto cerrado, donde las variables conservan valores que sólo pueden modificarse desde ese mismo contexto. Y aquí, la clave para entender el funcionamiento consiste en comparar ese contexto con el contexto global de window.
El intérprete está obligado a guardar en memoria ese nuevo contexto, con todos sus valores, y en los navegadores antiguos existían bugs que impedían que se borraran esos datos incluso al producirse el evento onunload.
En realidad no sé si aclaré u oscurecí. Realmente es un tema siempre difícil de explicar y de entender.
  #8 (permalink)  
Antiguo 09/12/2009, 15:49
Avatar de PacoRuiz  
Fecha de Ingreso: abril-2009
Mensajes: 254
Antigüedad: 15 años
Puntos: 3
Respuesta: closures

Más bien has oscurecido algo que creía entender, pero quizás es que no lo entendí del todo y por eso no entiendo lo que me dices. Te digo lo que no entiendo:

1. Si has definido alerta como una función que no lleva ningún parámetro, cómo es que la llamas pasándole el parámetro 'algo'.

2. "Cada vez que llamamos a la función alerta en realidad estamos llamando a la función interna, pero en su propio contexto" ¿Cuando dices su propio contexto te refieres a que se ejecuta externamente a la función alerta? O sea que la función alerta ha devuelto el código de la función interna, y ese código se ejecuta fuera de la función alerta. Tampoco veo bien cuál es el límite de ese contexto, dónde se puede modificar la variable y donde no. ¿En cualquier sitio externo a alerta? ¿Cuél es el alcance de ese contexto?


3. "Pero, si asimilamos a la función anónima que envuelve a la segunda función como un contexto semejante a window" No sé a qué te refieres al hablar aquí de window.
  #9 (permalink)  
Antiguo 09/12/2009, 21:01
Avatar de Panino5001
Me alejo de Omelas
 
Fecha de Ingreso: mayo-2004
Ubicación: -34.637167,-58.462984
Mensajes: 5.148
Antigüedad: 20 años
Puntos: 834
Respuesta: closures

1 - No llamo a la función alerta. Simplemente refiero a la variable alerta. Pero si te fijás bien, a esa variable
le había asignado el valor de retorno de la función anónima externa (notá los paréntsis al final de la asignación). Y esa
función, cuando es ejecutada, retorna la función interna. Con lo cual, invocar la variable alerta es en realidad invocar
la función interna, que sí requiere argumentos. Si no hubiera colocado los paréntesis al final de la asignación
del valor de la variable alerta, en cambio, las llamadas tendrían que usar un doble juego de paréntesis:
Código PHP:
alerta=function(){
    var 
contador=0;
    return function(
m){
        
alert('mensaje '+(++contador)+':'+m);
    }
};
//aquí saco los paréntesis, entonces ya no llamo de manera directa a la función interna usando la variable alerta
alerta()('algo');
alerta()('algo');
alerta()('algo');
alerta()('algo'); 
2-Cuando digo su propio contexto me refiero a que el ámbito global de la función interna, además de window, es la función externa que la envuelve.
Y lo es de la misma manera que, en el ejemplo de contador2 (el primero), el ámbito global de la función contador2 es window,
ya que la variable n en ese primer ejemplo (que en realidad es window.n o window['n'], y eso explica el porqué de window...)
tiene significado dentro de la
función contador2 tal como la variable contador, que es local a la función externa del segundo ejemplo, tiene significado (alcance)
global dentro de la función
anónima interna.
El paralelismo que trataba de trazar es: la función externa es a la función interna lo que window es a la función contador2
3-Bueno, una vez que entendemos que cualquier variable global equivale a window.variable, ya que todas las variables globales
"cuelgan" del objeto window, creo que sobran las explicaciones.

Última edición por Panino5001; 09/12/2009 a las 21:15
  #10 (permalink)  
Antiguo 11/12/2009, 10:03
Avatar de PacoRuiz  
Fecha de Ingreso: abril-2009
Mensajes: 254
Antigüedad: 15 años
Puntos: 3
Respuesta: closures

Estoy busando tutoriales para tratar de entender conceptos de los que hablas pero no los encuentro. Por otro lado, quiero aprender a manejar el zend a un nivel básico, y he entrado a intentar entender ciertas cosas porque han ido saliendo a partir de cosas que no he entendido en los tutoriales de zend, y ahora estoy en una situación en la cual las dudas originales han desaparecido, pero las que han ido surgiendo a partir de las respuestas no.

No sé hasta qué punto necesito entender esto para aprender algo de zend. Pregunté aquí algunas dudas sobre zend y me dirigieron a algunos tutoriales que me aclararon bastantes cosas. Quizás aquí también habría que mandarme a leer ciertas cosas, pero yo ahora mismo no consigo encontrar las adecuadas. Encuentro tutoriales básicos o bien otros que dan cosas por sabidas que no entiendo.

De todos modos comento lo que no entiendo, y te agradezco tu paciencia, porque me da la sensación de que ando algo "espesito".


Me choca eso de invocar una variable. Por ejemplo, yo digo

a=3;

Y luego pongo

a;

¿Eso qué es? Una linea es una instrucción ¿no? ¿Qué es eso de poner ahí una variable? ¿Qué es eso de invocar?

No entiendo el significado de los paréntesis al final de la.... ¿Asignación? ?¿Definición? Me choca la palabra asignación ahí.

¿Qué es el objeto window? ¿La ventana donde se ejecuta la aplicación? Para mi window es un sistema operativo, y ventana en inglés, nunca he oído hablar del objeto window. Ni veo la relación con esta cuestión.
  #11 (permalink)  
Antiguo 11/12/2009, 11:48
Avatar de Panino5001
Me alejo de Omelas
 
Fecha de Ingreso: mayo-2004
Ubicación: -34.637167,-58.462984
Mensajes: 5.148
Antigüedad: 20 años
Puntos: 834
Respuesta: closures

Bueno, Zend no tiene nada que ver aquí, o mejor dicho, no está relacionado con javascript. Y en realidad, si el objetivo es sólo entender closures en php, este no es el foro adecuado. Quizá te convenga leer la explicación de Venkman (la tercera) en este enlace, para ver cómo se relaciona con php:
http://php.apsique.com/contenido/nov..._closures_phar
Esa explicación es una de las mejores que he leído al respecto.
En javascript existe una jerarquía de objetos y el principal es window: http://www.desarrolloweb.com/articulos/808.php
  #12 (permalink)  
Antiguo 11/12/2009, 12:05
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años
Puntos: 1485
Respuesta: closures

@PacoRuiz,
una vez tengas en claro la jerarquia de objetos, los contextos de ejecuccion, y otros detalles basicos como la invocacion de funciones, te invito a que leas el siguiente documento http://www.jibbering.com/faq/faq_notes/closures.html. de hecho, ha sido el documento que mas me ha ayudado a comprender el concepto de closures en javascript, aunque esta un poco demasiado tecnico. lastima que esta en ingles.
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.
  #13 (permalink)  
Antiguo 11/12/2009, 16:51
Avatar de PacoRuiz  
Fecha de Ingreso: abril-2009
Mensajes: 254
Antigüedad: 15 años
Puntos: 3
Respuesta: closures

Gracias a los dos. Intentaré sacar partido a todos los enlaces que habéis puesto aquí. Lo de php y javascript es que yo he buscado información sobre closures en general, y todo me ha dirijido a javascript, y me han redirijido este tema aquí, pero mis dudas no son de javascript sino sobre conceptos generales, pero para aplicarlos a php.
  #14 (permalink)  
Antiguo 11/12/2009, 17:13
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años
Puntos: 1485
Respuesta: closures

o sea, conceptos generales para todos los lenguajes, ahora entiendo porque tanto rodeo. yo lo que pienso es no todos los lenguajes implementan un concepto de la misma forma. es decir, en cada lenguaje cada conceptos tiene sus caracterisiticas particulares aunque se trate de lo mismo. por ejemplo, los Arrays son un tipo de datos que aparecen en muchos lenguajes pero si comparamos php y javascript, algunas caracterisiticas son similares y otras no. por mencionar una, php tiene el concepto de array asociativos pero en cambio javascript solo permite array indexado. mas o menos de esa misma manera puede suceder con el concepto de closure. es cuestion de leer los detalles tecnicos en los lenguajes a emplear y compararlos entre cada lenguaje.
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.

Última edición por zerokilled; 11/12/2009 a las 17:21
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:17.