2011-08-03 17 views
6

Acabo de recibir Javascript: The Good Parts por Douglas Crockford y estoy teniendo algunas dificultades para entender uno de sus ejemplos con respecto a los prototipos. El código en el libro se lee de la siguiente manera:confusión sobre el ejercicio de Javascript

if (typeof Object.create !== "function") { 
    Object.create = function(o) { 
     var F = function() {} 
     F.prototype = o; 
     return new F; 
    }; 
} 

Estoy asumiendo que este código se utiliza para apuntar el prototipo de una función. Pero, ¿por qué usar un enfoque tan complejo? ¿Por qué no usar variable .prototype? Crockford es el experto líder en Javascript, así que estoy seguro de que hay una buena razón para usar este modelo. ¿Alguien puede ayudarme a entenderlo mejor? Cualquier ayuda sería apreciada.

Respuesta

5

En ECMAScript 3, el operador new era la única manera estándar para establecer la propiedad interna [[Prototype]] de un objeto, en este caso, Crockford es sólo con una función constructora temporal F para ese propósito.

El argumento o de ese método, se establece como la propiedad prototype del constructor temporal, y mediante la invocación de new F(); Construye un nuevo objeto vacío que hereda de F.prototype (ver this question para más detalles acerca de cómo funciona new).

Por ejemplo:

var a = { a: 1 }; 
var b = Object.create(a); // b inherits from a 
b.a; // 1 

En el ejemplo anterior, podemos decir que [[Prototype]] puntos de propiedades internas del b 's a a.

Object.getPrototypeOf(b) === a; // true 

En otras palabras, b hereda de a.

Con el mismo ejemplo, se podría utilizar un constructor vacío, por ejemplo:

function F(){} 
F.prototype = a; 

var b = new F(); // b again inherits from a (F.prototype) 

Recuerde también que la propiedad prototype de funciones es diferente de la propiedad [[Prototype]] que todos los objetos tienen, la propiedad prototype de funciones es se usa cuando se llaman con el nuevo operador para construir un nuevo objeto que hereda de esa propiedad.

Además, tenga en cuenta que ahora, el estándar ECMAScript 5 se está implementando, y esta cuña, no concuerda al 100% con la especificación, de hecho, hay algunas características del método Object.create estándar that cannot be emulated on ES3.

Consulte también:

+0

@ CMS, pero en este caso, 'Object.create' está configurado como una función vacía. Entonces no hay herencia aquí ... ¿verdad? Además, dado que 'Object.create' es un método del constructor' Object', establecerlo igual a una función vacía sería 'null' correcto? – dopatraman

+0

@codeninja, no entiendo por qué dices 'Object.create' está * set * en una función * empty *, tal vez debido a la última línea (' return new F; ') ??? La última línea simplemente devuelve un nuevo objeto que invoca el constructor 'F' (un objeto que hereda de' F.prototype'), podría parecer poco familiar ya que los paréntesis faltan al final, pero son opcionales cuando se usa el 'nuevo 'operator (' new F(); 'es equivalente a' new F; ') ... – CMS

+0

@ CMS - El código dice' Object.create = var F' que está configurado '=' to 'function() { } ' ¿no significa esto que en cierto sentido está configurado para una función vacía? – dopatraman

0

Este método creará una instancia de un nuevo objeto dado el objeto pasado como el prototipo.

+0

@ Nathan_Romano - ¿por qué no usar el objeto 'new'? – dopatraman

3
var bar = Object.create(foo) 

vs

var bar = new Object() 

la primera bar tiene foo como su prototipo; el segundo tiene Object como prototipo.

+0

Typo: "el segundo tiene' Objeto' como su prototipo "debería ser" el segundo tiene 'Objeto.prototipo' como su prototipo ..." ('Objeto' es solo una función de constructor) – CMS

+0

@ Claudiu - en este caso 'Object.create' está establecido en' function() ', no asigna un prototipo a ninguna variable. – dopatraman

1

Este código es para implementaciones de JavaScript más viejos que no soportan Object.create, que se especifica en el estándar ECMAScript 5 lanzado en noviembre de 2009.

Mucha gente dice que la forma preferida de crear un objeto es especificar un prototipo para él en el momento de la creación. Esto se puede llamar differential inheritance o prototypal inheritance. De hecho, eso es lo que hace Object.create:

var protoCircle = {x: 0, y: 0, radius: 1, color:"black"}; 
var myCircle = Object.create(protoCircle); 
myCircle.x = 3; 
myCircle.color = "green"; 

Esto crea un círculo verde de radio 1 con centro en (3,0).

La razón por la que el código es tan complejo que antes Object.create se añadió a JavaScript, la única manera de establecer prototipo de un objeto era crear con el operador new. Los objetos creados con new obtuvieron, como su prototipo, el valor de la propiedad prototype del constructor. Definitivamente es confuso, pero la propiedad prototype NO es el prototipo de un objeto. Dado un objeto de función f, f.prototype es el objeto que se asignará como el prototipo de todos los objetos construidos a través de new f(). El prototipo real de un objeto se llama [[prototype]] o __proto__, pero no puede acceder a estos en ECMAScript estándar. Confuso, ¿eh?

Como nota al margen. la especificación ES5 tiene una especificación Object.prototype más mejorada que la que definió Crockford. Se necesita un segundo objeto para configurar las propiedades del objeto que se está definiendo.

Cuestiones relacionadas