2011-09-08 20 views
5

Considere el siguiente código:"newing" una función en JavaScript, ¿qué significa?

var f = function() { return 10; } 
typeof f;       // returns "function" 
f();        // returns 10 

var g = f; 
g();        // returns 10, obviously 

var h = new f; 
h;        // console evaluates to f - ???? 
h();        // Type error - called_non_callable 
typeof h;       // returns "object" 

Entonces, ¿qué es h aquí? La consola de Chrome parece evaluarlo como f, pero no se puede llamar. ¿Qué significa "nuevo" una función como esta? ¿Cómo está h ahora relacionado con f?

Como acotación al margen, estas dos líneas parecen ser equivalentes:

var h = new f; 
var h = new f(); 

¿Qué pasa con eso?

+2

posible duplicado de [¿Cuál es la palabra clave 'nueva' en JavaScript?] (Http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript) –

Respuesta

4

La raíz de su confusión es la forma en que Chrome representa objetos en su consola.

La expresión new f() en su ejemplo se representa como 'f' en la salida de la consola del cromo, pero sólo como un mero "conveniencia" de esta consola en particular, por ejemplo, el registro de la siguiente objeto:

({constructor: function Foo(){}}); 

Mostrará que se representa como "Foo". Básicamente, la consola intenta encontrar una representación cuyo constructor su objeto es instancia de.

Entonces, la consola muestra f, pero no está registrando la función, el operador new produce un objeto que hereda de f.prototype.

Usted está devolviendo 10 de la función, pero como se le llama con new, y el tipo de retorno es una primitiva , se descarta el valor, el objeto de nueva creación que hereda se devuelve forma f.prototype.

Por ejemplo:

var F = function() { return 10; }; 
F.prototype.inherited = 'foo'; 

var h = new F(); // the 10 returned is ignored 
h instanceof F; // true 
h.inherited; // "foo" 

Por otro lado, si usted devuelve un objeto a partir de un constructor, la instancia del objeto que el operador new crea detrás del scened (y hereda desde el prototipo del constructor) se perderán , por ejemplo:

var F = function() { return {}; }; 
F.prototype.inherited = 'foo'; 

var h = new F(); // the empty object is returned 
h instanceof F; // false 
h.inherited; // undefined 

Sí, new f; y new f(); son completamente equivalentes, aunque las personas que recomiendan el uso de los paréntesis para añadir claridad a su código.

+0

uno de los mejores explicaciones sobre SO! Gracias por mantenerlo simple. – demisx

1

Básicamente, la nueva palabra clave llama a f como el constructor de un nuevo objeto. La primera respuesta a esta pregunta, en StackOverflow, lo resume muy bien:

What is the 'new' keyword in JavaScript?

4

es así como la orientación a objetos en JavaScript funciona. si llama al new en una función, esta función se trataría como si fuera un constructor de una clase (las palabras clave class para definir una clase como otros idiomas no existen en js).

llamando var h = new f(); así hace h un objeto de clase f, y un objeto en sí mismo no es exigible (por eso se obtiene called_non_callable).

si usted quiere dar a sus "clase" algunos methots, debe hacerlo de esta manera:

function cat(name) { 
    this.name = name; 
    this.talk = function() { 
     alert(this.name + " says meeow!") 
    } 
} 

cat1 = new cat("felix") 
cat1.talk() //alerts "felix says meeow!" 

cat2 = new cat("ginger") 
cat2.talk() //alerts "ginger says meeow!" 

que es un ejemplo de page 2 de this tutorial. para obtener más información, lea eso o ask Google for object-orientation in JavaScript.

1

En JavaScript, las funciones no son solo funciones, y no son solo objetos; también están acostumbrados a los constructores definidos para los tipos.

Hablando en general, cuando tiene una función f, esa función define un tipo, ya sea que fue intencional o no. Así la línea

var h = new f(); 

define un objeto h cuyo tipo es f.

nunca he visto la línea

var h = new f; 

pero estoy asumiendo que hace lo mismo que la otra línea.

2

Recomiendo leer https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/this, especialmente la sección sobre "Contexto de la función".

En pocas palabras, cuando new función, se está creando un nuevo objeto: var h = new f;

Esta dice: "Crear un nuevo objeto referenciado por la variable llamada h de tipo f". La función luego se trata como un constructor en lugar de lo que está esperando.

Una vez que se ha creado el objeto, ya no se puede llamar (por eso está experimentando un error en la línea h().

En la mayoría de los idiomas (Javascript no se excluye), el () de un constructor es opcional (a menos que haya parámetros necesarios (en algunos idiomas)).

Cuestiones relacionadas