8

Estaba viendo un código para evitar el uso de variables y funciones globales:

myNameSpace = function() {
 var current = null;
 function init() {
  …
 }
 function change() {
  …
 }
 function verify() {
  …
 }
 return{
  init:init,
  set:change
 }
}();

Llamar myNameSpace.set() ahora invocará el método change().

Tengo muchas dudas sobre el propósito de los últimos par de paréntesis, ¿para qué se usan?

fedorqui
  • 15,850
  • 17
  • 58
  • 112
Frnk
  • 424
  • 1
  • 3
  • 10
  • 1
    Recomendadísimos: https://developer.mozilla.org/es/docs/Web/JavaScript y http://freecodecamp.com :D – fredyfx Jun 18 '18 at 16:16

4 Answers4

14

Lo que hacen los dos paréntesis del final es ejecutar la función que le precede. Es decir, imagina lo siguiente:

myFunc = function(){ /* codigo */ }

lo que hace es asignar una función (la implementación) a una función, de manera que si hacemos

myFunc();

se ejecutará la función ya que se está invocando (o dicho de una manera muy informal, se le han añadido los paréntesis para ejecutarla).

Si ahora volvemos al código de tu pregunta, tenemos:

myNamespace = function(){ /* codigo */ }();

lo que ocurre es que se está definiendo la función e inmediatamente se está ejecutando. Este concepto se conoce como funciones autoejecutables (IIFE, "Immediately-invoked function expressions"), ya que como el propio nombre indica, se ejecutan inmediatamente después de ser definidas.

Otra forma muy común de verlas es de la forma:

(function() {})() ó (function() {}())

Pero ambas hacen lo mismo, ejecutar la función.

Sabiendo eso, si vuelves al código original, lo que harán esos paréntesis es ejecutar inmediatamente la función y asignará a myNamespace el objeto devuelto por el return.

Sema
  • 800
  • 6
  • 8
  • Lo estoy entendiendo de esta manera: al ejecutar la funcion , lo estoy volviendo un objeto y esto hace que su contenido sea global. Es correcto ?. – Frnk Jun 18 '18 at 11:11
  • Sí, siempre que ese fragmento se ejecute fuera de cualquier función. Las variables en JavaScript tienen el ámbito de la función en la que fueron declaradas: local si están dentro de una función o global en caso contrario. – Sema Jun 18 '18 at 12:29
  • Para ver un ejemplo rapido de esto , solo mira como hace jQuery generalmente colocamos un `$().ready` todo lo que este dentro de alli se ejecutara alli y no puedes usar una variable en otra funcion a menos que lo especifiques pero ya hay una respuesta para eso – JackNavaRow Jun 18 '18 at 13:08
10

Repuesta Corta

Al realizar myNameSpace().set(); estas creando un objeto y ejecutando el metodo set que previamente definistes

Respueta Larga

Para entender que hace esos parentesis separemos la funcion y preguntemos que tipo de dato es myNameSpace y que tipo de dato es myNameSpace()

myNameSpace = function() {
 function init() {
  console.log('init')
 }
 function change() {
  console.log('change')
 }
        return{
            init:init,
            set:change
        }
    };
console.log(typeof(myNameSpace))
console.log(typeof(myNameSpace()));

myNameSpace()es un Objeto!!! , existen muchas formas de definir Clases en JavaScript, esta es una de ellas, pero que tal si colocamos un ejemplo donde sea mas facil entender que pasa cuando ejecutas myNameSpace().set()

Personas = function(nombre, apellido) {
        this.nombre = nombre ;
        this.apellido = apellido;
        function nombreCompleto() {
            console.log(`${nombre} ${apellido}`)
        }
        function change(apellidoNuevo) {
            apellido = apellidoNuevo
        }
        return{
            nombreCompleto:nombreCompleto,
            set:change
        }
    };

var jax = Personas('Jax', 'Navarrow'); 

jax.nombreCompleto()
jax.set('Chispas');
jax.nombreCompleto()

Personas('Frnk', 'Frnk').nombreCompleto()

Debes tener en cuenta

JackNavaRow
  • 6,836
  • 5
  • 22
  • 49
2

@Sema lo ha descrito muy bien, aunque por legibilidad para crear una variable como función se suele utilizar myFunc = function(){ /* codigo */ }, aunque son las dos totalmente válidas. Si quiere ajustarte POO, y quieres crear un objeto con métodos y atributos, entonces la manera actual que has comentado sería la idónea myNamespace = function(){ /* codigo */ }();.

myNameSpace = function() {
        function init() {
            alert("init");
        }
        function change() {
            alert("change");
        }
        return{
            init:init,
            set:change
        }
    };

myNameSpace().set();
UHDante
  • 838
  • 1
  • 8
  • 19
1

Cuando haces set:change, esto lo que quiere decir es que set tendra la referencia de la función change, o en otras palabras, set apuntara a change. De ahi que myNameSpace.set() ejecuta change(), por lo que como el valor contenido el set es una función entonces es necesario los parentesis () para ejecutar la funcion referenciada.

El siguiente ejemplo es lo mismo:

var vecesEjecutadas = 0;

function fn1(){ 
 console.log("fn1" ,++vecesEjecutadas)
}

var fn2 = fn1; // le asignamos  la referencia de la funcion fn1 a la variable fn2

fn2();
fn1();

Aunque fn2 no fue declarada con la sintaxis de una función, esta contiene la referencia de una función, por lo que si quieres obtener el resultado, tendrás que ejecutarla como una funcion.

Una funcion para JavaScript es un Objeto de tipo function , y por ser Object mantiene su referencia

JackNavaRow
  • 6,836
  • 5
  • 22
  • 49
Einer
  • 20,190
  • 2
  • 14
  • 36