2011-03-22 14 views
11

En el código para el módulo Express para Node.js me encontré con esta línea, el establecimiento de la herencia para el servidor:La confusión acerca de la configuración something.prototype .__ proto__

Server.prototype.__proto__ = connect.HTTPServer.prototype; 

no estoy seguro de lo que esto hace - la documentación del MDC (https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited#prototype_and_ proto) parecen decir que yo sólo podía hacer:

Server.prototype = connect.HTTPServer.prototype; 

de hecho, lo hice esta prueba:

var parent = function(){} 
parent.prototype = { 
    test: function(){console.log('test')}; 
} 

var child1 = function(){}; 
child1.prototype = parent.prototype; 
var instance1 = new child1(); 
instance1.test();  // 'test' 

var child2 = function(){}; 
child2.prototype.__proto__ = parent.prototype; 
var instance2 = new child2(); 
instance2.test();  // 'test' 

¿Parece ser lo mismo? Entonces, yah, me pregunto para qué sirve object.prototype .__ proto. ¡Gracias!

+0

Posible duplicado de [\ _ \ _ proto \ _ \ _ VS. prototipo en JavaScript] (http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript) –

Respuesta

10

Tenga una mirada en el diagrama de la this page (mckoss.com) que muestra los prototype, constructor, __proto__ las relaciones de una pequeña jerarquía. También el código debajo del diagrama describe la relación bastante bien.

Cuando se tiene una función Base, y establecer el prototipo del objeto función definida, la declaración Derived.prototype = new Base; establece el __proto__ (en realidad el interior [[prototype]]) de Derived.prototype a Base.prototype de forma automática, haciendo que a su vez deriva de una clase que se pueden crear instancias de objetos de . Esta parece ser una forma más compatible con los estándares de definir una clase derivada.

Por lo que he leído, __proto__ es una forma no estándar de acceder al [[prototype]] interno de un objeto. Parece estar bien soportado, pero no estoy seguro de si debería ser confiable.

En cualquier caso, su ejemplo Server.prototype.__proto__ = connect.HTTPServer.prototype; parece hacer la derivación al revés: primero definir un objeto, Server definiendo el constructor y el proto, y luego conectar el [[prototype]] interno manualmente para transformarse en una clase derivada desde HTTPServer.

En cuanto a su alternativa sugerida, Server.prototype = connect.HTTPServer.prototype;: esa es una mala idea. Aquí, configura el prototipo de Server para que sea el mismo objeto que el prototipo de HTTPServer. Por lo tanto, cualquier cambio que realice en la clase Server se reflejará directamente en HTTPServer, y será accesible desde otras clases derivadas de HTTPServer. Puede crear imágenes del caos si dos clases derivadas de HTTPServer intentan definir el mismo miembro.

+0

Gracias por el enlace del artículo de mckoss: solo una aclaración antes de concluir, creo que tengo esto correcto: mi alternativa sugerida (Derived.prototype = Base.prototype) está bien si nadie se atornilla con el prototipo, la razón por la que queremos hacer "Derived.prototype = new Base" (que establecerá el prototipo de Derived en un nuevo objeto que tiene su [[prototype]] configurado en Base.prototype), es asegurarse de que cualquier modificación en el prototipo de Derived NO PUEDE afectar el prototipo de Base. – ambertch

+0

Tu comprensión y la mía son las mismas. Dado que no estoy muy bien versado en Javascript, puede haber algunas otras sutilezas que me he perdido. Además, si necesita instanciar la clase derivada, 'Derived.prototype.constructor' será' Base.prototype.constructor', por lo que llamará a la función incorrecta si usa 'new Derived'. Creo. – vhallac

2

La propiedad no estándar __proto__ le permite establecer el prototipo de un objeto existente.

En su ejemplo, tanto en versión será lograr el mismo efecto, pero hay una diferencia:

child1 'prototipo s es la misma que parent' prototipo s, mientras que child2 's prototipo es un objeto vacío y esto el prototipo de objeto vacío es el mismo que el prototipo parent.

Por supuesto, como child2 y su prototipo no tiene un método test, este método se buscará más arriba en la cadena del prototipo.

Considera también esto:

desea crear un solo objeto que debe heredar de otro objeto. Ahora bien, podría escribir una función de constructor, pero JavaScript tiene una notación literal de objeto para crear objetos directamente y desea usarla.

Si tiene una función de constructor, dejar que los nuevos objetos hereden de otro objeto es una configuración tan fácil como prototype de la función de constructor para ese objeto.

Obviamente, esto no funciona para literales de objetos. Pero en Firefox puede utilizar __proto__ para configurarlo:

var server = { 
    __proto__: connect.HTTPServer.prototype, 
    other: properties 
}; 

ya que esta propiedad no es estándar, se debe evitar el uso de la misma.

+0

Gracias Félix, las respuestas de tu + Dysaster combinadas realmente aclararon las cosas, ojalá pudiera marcarlas a ambas – ambertch

+1

En realidad, __proto__ está en el estándar ECMAScript 6, también es muy compatible con los navegadores modernos (IE9 +) – csuwldcat

Cuestiones relacionadas