2011-11-14 11 views
10

He estado leyendo algunos libros de JavaScript y siempre escucho sobre cierres y efectos secundarios. Por alguna razón, no puedo entender lo que realmente son. ¿Alguien puede explicarme qué son en inglés sencillo más ejemplos? (como se lo explicaba a alguien con el nivel de programación de un diseñador gráfico).cierres de Javascript y efectos secundarios en inglés sencillo? (por separado)

+0

Por favor, aclare: ¿Está pidiendo una explicación para los cierres y, por separado, para obtener una explicación de los efectos secundarios? ¿O sobre ambos combinados? – delnan

+0

@delnan lo siento modifiqué el título. – alexchenco

+1

Luego vea http://stackoverflow.com/questions/111102/how-do-javascript-closures-work y elimine la parte de los cierres, sería un duplicado. Los efectos secundarios tampoco son exactamente nuevos, pero no estoy al tanto de nada específico en SO, por lo que no voy a votar para cerrar por el momento. – delnan

Respuesta

12

Los efectos secundarios son el concepto más fácil. Una "función pura" es una función que mapea sus valores de entrada en un valor de salida def plus(x, y){ return x + y; }. Un "efecto secundario" es cualquier efecto que no sea ese valor de retorno. Entonces, por ejemplo:

def plusWithSideEffects(x, y) { alert("This is a side effect"); return x + y; } 

tiene el efecto secundario de generar un cuadro de diálogo de alerta (y que requiere la interacción del usuario). Cada función de código tiene algunos efectos secundarios (todos consumen memoria y toman tiempo, nada más), pero cuando las personas hablan de los efectos secundarios, a menudo se preocupan más por IO (como el cuadro de diálogo de alerta anterior) o la escritura de estado que vive más allá del período de ejecución de la función.

El desafío con los efectos secundarios es que hacen que las funciones sean más difíciles de razonar y volver a utilizar. (Es mucho más fácil de razonar y funciones de reutilización que son lo más cercano a "funciones puras" como sea posible, ya que tienden a "hacer una cosa bien.")

+1

Para "nivel de programación de un diseñador gráfico" es una respuesta real. –

+0

No estoy abajo votando porque la respuesta responde la pregunta, pero no me gusta la palabra clave def utilizada en el ejemplo, ya que no es una palabra reservada de JavaScript, es algo de pitón, ¿no? – zappa

0

Exemple

function outer() { 
    var outerVar; 

    var func = function() { 
     var innerVar 
     ... 
     x = innerVar + outerVar 
    } 
    return func 
} 

Cuando externo() mueren, la función func() continuará livе y este uso práctico

2

Efecto secundario:

Piense en un lado- efecto como algo que hace dos cosas a la vez. Por ejemplo:

ejemplo clásico de un efecto secundario:

var i = 1; 
var j = i++; 

El efecto secundario sucede en i++. Lo que sucede aquí es j se convierte en 1 y luegoi consigue incrementa y se convierte en 2. En otras palabras, dos cosas sucedieron y el efecto secundario fue que se convirtió en i 2.

Cierre:

Visualícense una cadena de enlaces como este: <> <> <> <> <> <> <>. Imagine que el nombre de esta cadena de enlaces se llama cadena de alcance . Luego imagina que todos estos enlaces conectan objetos juntos así: <> objeto <> objeto <> objeto <>. Ahora, tenga en cuenta lo siguiente:

(1) Todas las cadenas de alcance comienzan con el objeto global.

(2) Cuando se define una función, se almacena una cadena de alcance para esa función.

(3) Cuando se invoca una función, crea un nuevo objeto y lo agrega a la cadena de alcance.

Ahora, por favor, mira el siguiente ejemplo:

function counter() { // define counter 
        var count = 0; 
        return function() { return count + 1;}; // define anonymous function 
        }; 
var count = counter(); // invoke counter 

En este ejemplo, cuando se define counter(), la cadena de ámbito para el contador se ve así: <> objeto global <>. Luego, cuando se invoca counter(), la cadena del alcance se ve así: <> objeto global <> contador objeto <>. Después de eso, la función sin nombre (llamada función anónima) dentro del contador se define e invoca. La cadena de ámbito de la función anónima vez invoca el siguiente aspecto:. <> objeto global <> objeto de contador <> objeto función anónima <>

Heres fueron la pieza de cierre viene en Si te fijas, la función anónima está utilizando el variable count que se definió fuera de ella. La razón es porque la función anónima puede acceder a cualquier variable definida en su cadena de alcance. Esto es lo que es un cierre, una función junto con referencias a cualquier variable en su cadena de alcance almacenada.

Sin embargo, en el ejemplo anterior, una vez que las funciones regresan, los objetos creados en la invocación se descartan por lo que realmente no tiene sentido. Ahora mira el siguiente:

function counter() { // define counter 
        var count = 0; 
        function f() { return count + 1;}; // define f 
        return f; // return f 
        }; 
var count = counter(); // invoke counter 

En este ejemplo, voy a volver a una función denominada f y asignar a la variable que count. Ahora la variable count contiene una referencia a toda la cadena de alcance y no se descarta. En otras palabras, el conteo de variables almacena la cadena del alcance de la siguiente manera: <> objeto global <> objeto contador <> objeto de función anónima <>. Este es el poder de los cierres, puede mantener una referencia a una cadena de alcance y llamarlo así: count().

+1

** La parte de cierre de esta respuesta es incorrecta **. JavaScript tiene * scope * estático, lo que significa que la cadena de alcance de una función se define en función * definición *, ** no ** función * invocación *. El ejemplo funciona porque la función anónima se define cada vez que se invoca 'contador', lo que significa que cada función devuelta tendrá una cadena de alcance con un * objeto de activación * diferente para 'contador ', y por lo tanto un conjunto diferente de variables locales (como 'count'). [Vea esta respuesta para más información.] (Http://stackoverflow.com/questions/7721200/using-javascript-closures-in-settimeout/7722057#7722057) – josh3736

+0

@ josh3736: Gracias por el comentario. Cambié mi respuesta, por favor avíseme si algo está mal. Además, quería comentar que, para una declaración de función global, la función solo tendrá una referencia a una cadena de ámbito que contenga el objeto global. No hasta que lo invoque tendrá una referencia al objeto de activación. –

4

Las funciones con efectos secundarios hacen algo más que devolver un valor (aunque también pueden hacerlo). Si puede reemplazar todas las llamadas a función por argumentos dados con el valor para esos argumentos y el programa tiene el mismo comportamiento, no hay efectos secundarios. Esto requiere que la función siempre devuelva el mismo valor para los argumentos dados.

Es decir, supongamos f(1,2) == 12. Si siempre puede reemplazar f(1,2) con 12 y el programa se comporta de la misma manera, entonces f no tiene efectos secundarios para esos argumentos. Por otro lado, si en un lugar f(1,2) == 12 y otro f(1,2) == 13, entonces f tiene efectos secundarios. Del mismo modo, si el programa dejó de enviar un correo electrónico después de reemplazar f(1,2) con 12, entonces f tiene efectos secundarios. Generalmente, si f(x,y) == z (donde z depende de xey) siempre puede reemplazar cada llamada f(x,y) con , entonces f no tiene efectos secundarios.

Algunas funciones simples con efectos secundarios:

// doesn't always return the same value 
function counter() { 
    // globals are bad 
    return ++x; 
} 
// omitting calls to `say` change logging behavior 
function say(x) { 
    console.log(x); 
    return x; 
} 
0

Soy nuevo en JavaScript, y no a tratar de hablar de cierres. Sin embargo, mi novedad en JavaScript me hace bastante consciente del uso de efectos secundarios que son imposibles en mi lenguaje de programación habitual (Erlang).

Los efectos secundarios parecen ser una forma habitual de cambiar el estado en JavaScript. Tomemos por ejemplo este ejemplo desde el sitio web w3cschools.com:

<script> 
function myFunction() { 
    document.getElementById("demo").innerHTML = "Paragraph changed."; 
} 
</script> 

Aquí no hay parámetros de entrada o valor de retorno, en lugar de los contenidos del documento se cambian a medida que son de alcance mundial a la función. Si tuviera que escribir esto en Erlang, por ejemplo, el documento se pasaría como un parámetro y se devolvería el nuevo estado del documento. Una persona que lee el programa de llamadas verá un documento enviado y se devolverá un documento modificado.

Ver funciones llamadas así para no devolver el nuevo estado explícito debe alertar al programador sobre el uso probable de efectos secundarios.

Cuestiones relacionadas