On Wed, 26 Dec 2012 15:10:58 +0100
Txemanu unamexT <
txe...@gmail.com> wrote:
> El 26 de diciembre de 2012 14:12, Iñaki Baz Castillo
> <
i...@aliax.net>escribió:
>
> > El día 26 de diciembre de 2012 14:02, Pablo Garaizar Sagarminaga
> > <
gara...@deusto.es> escribió:
> > > Hola,
> > >
> > > El Wed, 26 Dec 2012 13:50:21 +0100
> > > Txemanu unamexT <
txe...@gmail.com> comentaba:
> > >
> > >> Realmente la función que se asigna al onload es la función que
> > >> está en el return. La primera se ejecuta automáticamente, es una
> > >> función anónima autoejecutable.
> >
> > ¿Es autoejecutable por el hecho de estar entre paréntesis? ¿o no
> > tiene nada que ver? (lo digo porque me suena haberlo visto/leído,
> > pero no estoy seguro...).
> >
>
> Es autoejecutable por los paréntesis que hay a continuación de ella,
> que hace que se declare y ejecute seguido. También podría tener este
> formato: f(){....}() aunque se suele poner entre paréntesis para
> verlo más claro: (f(){...})()
Sí, eso es. Es una convención (usada entre otros por jQuery). En otros
sitios te puedes encontrar con lo mismo indicado de otras maneras:
( function ... {...}(f) ) // paréntesis afuera
!function ... {...} (f)
etc.
> > Y sobre todo, ¿por qué hace falta esa función autoejecutable? ¿no se
> > puede setear directamente la function que viene dentro? ¿o acaso si
> > se asigna una function ésta se ejecutaría inmediatamente al
> > interpretarse el código al principio? Obviamente interesa que esa
> > función se ejecute más tarde (cuando se produzca el evento) y no
> > antes, ¿es por ello ese "hack" con una función que retorna otra?
> >
> La función autoejecutable lo que hace es crear un "closure"
> alrededor de la variable theFile, para que ésta esté disponible
> cuando se ejecuta la función que se asigna en el return
> al evento onload. Este closure es un "objeto de activación" que no se
> ha destruido por que quedan referencias a él. Estos "objetos de
> activación" se crean y destruyen cada vez que se ejecuta una función
> en JS, y contiene los objetos disponibles en el contexto de la
> función. Cuando estos "objetos de activación" no se destruyen por que
> quedan referencias a ellos, hablamos que se ha creado una "closure".
Exacto. Crea un una función auto ejecutada para mantener la referencia
a "f".
Yo creo que el código podría quedar más claro quizá utilizando OOP y
el Proxy Pattern (que en cierto modo es lo que usa), por si quieres
investigarlo.
En realidad la variable "f" (aka "theFile") no se destruye, porque se
usa dentro del closure precisamente. Es decir, algo como esto podría
funcionar:
reader.onload = function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(
f.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null); };
};
Pero hay un problema, y es que el valor de "f" dentro del bucle va
cambiando y, además, al final acaba siendo "undefined". Cuando onload
se llame, "f" seguramente tendrá ese valor que se le ha asignado al
final.
for (var i = 0, f; f = files[i]; i++) {
En la última vuelta "files[i]" será "undefined", se asignará ese valor
a "f" y luego dará por terminado el bucle. Cuando se llame a "onload",
aunque a simple vista parezca raro, "f" seguramente valdrá undefined.
> > > Fíjate que avisa con un comentario para los no-javascripters: ojo
> > > que aquí viene una clausura (o cierre, o closure, o como demonios
> > > quiera que se diga). Las clausuras son una de las frikadas que ha
> > > heredado JavaScript de Scheme y trae por la calle de la amargura
> > > a todos los que llegan de otros lenguajes pero causa admiración
> > > una vez se entiende su potencial O:-D (yo estoy todavía en esa
> > > transición, lo confieso).
> >
> > Vaya, pues el caso es que yo de JS como véis poco, pero sí toco
> > Ruby, y en Ruby los blocks (que al final son precisamente un
> > closure) se usan para todo y no podría vivir sin ellos. Tendré que
> > asimilar la "sintaxis" de JS... :)
Son parecidos pero tienen sus diferencias. Digamos que, mientras ruby
tiene sus blocks, procs y lambads, cada uno para cada cosa, Javascript
sólo tiene sus function para todo.
Esto hace que ruby sea más fácil de leer, pero quizá también hace que
en javascript sea más fácil de aprender (una vez entendido bien cómo
funciona una function).
Un saludo,
--
Xabier de Zuazo