Estoy mirando un código JavaScript y he notado el siguiente patrón en varias funciones
function getValues() { var values = ['a', 'b', 'c']; return (getValues = function () { return values; })(); }por lo que sé, la siguiente función tiene el mismo efecto de
function getValues() { return ['a', 'b', 'c']; } ¿Envolverlo en un IIFE aquí tiene un efecto especial? especialmente la siguiente sección return (fnName = function() {...})() Notando que una variable siempre se asigna con el mismo nombre de la función.
Nota: estoy muy familiarizado con el concepto IIFE y cuando es útil, y no confundir con el siguiente patrón
var fn = (function() { function fn() { } fn.prototype.function1 = function () { /* ... */ } return fn; })();En mi pregunta, la variable se asigna dentro de la función y no al revés.
Bueno, en este caso es parte de una extraña técnica de memorización.
El punto clave a tener en cuenta es que la función se reasigna a sí misma:
return (getValues = function () { ^^^^^^^^^^^^ Entonces, lo que sucede cuando se llama a getValues por primera vez es que getValues crea una nueva función que tiene values como cierre, luego se reemplaza con esa nueva función.
Por eso, las llamadas posteriores a getValues llamarán a la misma función interna, que devuelve el valor del cierre sin crear un objeto diferente cada vez.
Puede comprobar este comportamiento comprobando los valores de retorno:
console.log(getValues() === getValues()); //trueSi bien, con su implementación, eso no funcionaría:
function getValues() { return ['a', 'b', 'c']; } console.log(getValues() === getValues()); //false Reasignar la función significa que el valor de getValues cambiará entre la primera y la segunda llamada. Asi que:
var gv0 = getValues; getValues(); console.log(gv0 === getValues); // falseEse comportamiento tiene sus propios riesgos si se crean múltiples referencias a la función:
var gv0 = getValues; console.log(getValues() === gv0()); // false!Por cierto, la forma habitual (y más legible) de escribir memoization es hacer que la función externa sea un IIFE, que devuelve la función interna. También elimina la necesidad de reasignación.
var getValues = (function () { var values = ['a', 'b', 'c']; return function () { return values; }; })();Sin embargo, eso creará el objeto inmediatamente, mientras que el código en cuestión solo lo creará en la primera llamada.
Esta diferencia es importante si la creación del objeto es costosa.