Ya hay algunas respuestas muy buenas, pero estoy publicando una nueva para enfatizar mi observación en el caso III a continuación sobre lo que sucede cuando tiene una declaración de retorno explícita en una función que está new
activando. Echa un vistazo a los siguientes casos:
Caso I :
var Foo = function(){
this.A = 1;
this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1
Arriba hay un caso simple de llamar a la función anónima señalada por Foo
. Cuando llama a esta función, vuelve undefined
. Como no hay una declaración de retorno explícita, el intérprete de JavaScript inserta con fuerza una return undefined;
declaración al final de la función. Aquí ventana es el objeto de invocación (contextual this
) que obtiene nueva A
y B
propiedades.
Caso II :
var Foo = function(){
this.A = 1;
this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1
Aquí, el intérprete de JavaScript que ve la new
palabra clave crea un nuevo objeto que actúa como el objeto de invocación (contextual this
) de la función anónima señalada por Foo
. En este caso A
y B
propiedades convertido en el objeto recién creado (en lugar del objeto de la ventana). Como no tiene ninguna declaración de retorno explícita, el intérprete de JavaScript inserta a la fuerza una declaración de retorno para devolver el nuevo objeto creado debido al uso de la new
palabra clave.
Caso III :
var Foo = function(){
this.A = 1;
this.B = 2;
return {C:20,D:30};
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.
Aquí nuevamente el intérprete de JavaScript al ver la new
palabra clave crea un nuevo objeto que actúa como el objeto de invocación (contextual this
) de la función anónima señalada por Foo
. Nuevamente, A
y B
conviértase en propiedades en el objeto recién creado. Pero esta vez tiene una declaración de retorno explícita, por lo que el intérprete de JavaScript no hará nada por sí mismo.
Lo que hay que tener en cuenta en el caso III es que el objeto que se está creando debido a la new
palabra clave se perdió de su radar. bar
en realidad apunta a un objeto completamente diferente que no es el que el intérprete de JavaScript creó debido a la new
palabra clave.
Citando a David Flanagan de JavaScripit: The Definitive Guide (6th Edition), cap. 4, página # 62:
Cuando se evalúa una expresión de creación de objeto, JavaScript primero crea un nuevo objeto vacío, como el creado por el inicializador de objeto {}. A continuación, invoca la función especificada con los argumentos especificados, pasando el nuevo objeto como el valor de esta palabra clave. La función puede usar esto para inicializar las propiedades del objeto recién creado. Las funciones escritas para su uso como constructores no devuelven un valor, y el valor de la expresión de creación del objeto es el objeto recién creado e inicializado. Si un constructor devuelve un valor de objeto, ese valor se convierte en el valor de la expresión de creación del objeto y el objeto recién creado se descarta.
--- Información adicional ---
Las funciones utilizadas en el fragmento de código de los casos anteriores tienen nombres especiales en el mundo JS de la siguiente manera:
Caso I y II - Función de constructor
Caso III - Función de fábrica. Las funciones de fábrica no deben usarse con la new
palabra clave que he hecho para explicar el concepto en el hilo actual.
Puedes leer sobre la diferencia entre ellos en este hilo.