2011-10-03 14 views
5

Siempre he supuesto que el prototipo de una función se compartió entre todos los objetos, en cierto sentido por referencia. Entonces, si cambia el valor de una propiedad del prototipo, todos los objetos que comparten ese prototipo también cambian los valores para ellos. Por ejemplo, debajo parece que en lugar de compartir la barra de propiedades entre todos los objetos, se copia. ¿Es esto correcto? ¿Las propiedades del prototipo del constructor simplemente se copian a todos los objetos de la clase a medida que se crean, o se comparten mediante el enlace?Javascript y asignación de prototipo de función

function foo() 
{ 
    this.bar = 1; 
} 
function derived() { } 
derived.prototype = new foo() 

object1 = new derived() 
object2 = new derived() 

object1.bar = 2; 
//but notice if I had said here derived.prototype.bar = 3, object1.bar would still equal 2 but object2.bar would equal 3 
alert(object2.bar) // this prints 1; 

Respuesta

12

Cuando asigna object1.bar = 2, está creando una propiedad en object1, esta propiedad existir sólo en esa instancia de objeto, y no tiene nada que ver con su prototipo.

Esta propiedad de object1 hará sombra el valor de la existente en derived.prototype, esto significa que cuando las operaciones de búsqueda object1.bar, encontrará un valor directamente existente en ese objeto.

Por otro lado, si las operaciones de búsqueda object2.bar, este objeto no tiene una propia bar propiedad, por lo que la búsqueda de propiedad buscará en el objeto de éste hereda de (derived.prototype) y encontrará el valor 1.

Su estructura del objeto es como la siguiente:

 
object1 
-------- 
| bar: 2 | ----------------- 
--------     |   derived.prototype 
          |  ---------- 
          |------> | bar: 1 | -- foo.prototype 
object2 (no own properties)|  ---------- | ------------------ 
--------     |      -> | constructor: foo | 
|  | -----------------       ------------------ 
--------             | 
                  v 
                ------------------ 
                | Object.prototype | 
                ------------------ 
                  | 
                  v 
                  null 

Cuando las ---> líneas denotan el enlace interno [[Prototype]] que expresa la herencia.

+0

ohhh, tiene mucho sentido, siempre que no lo vuelva a asignar, se refiere a la propiedad heredada, por lo que una vez que lo asigne se convierta en propiedad propia? – rubixibuc

+0

Lo tengo ahora, ese diagrama ayudó mucho, muchas gracias, tu respuesta fue increíble :-) – rubixibuc

+0

@rubixibuc, a la derecha, una vez que lo asignes, se convertirá en propiedad propia y * sombra * cualquier valor hasta en la cadena de prototipos. También tenga en cuenta que el enlace '[[Prototype]]' no se puede cambiar una vez que se crea un objeto, por ejemplo, después de crear 'object1' y' object2', reasigna un objeto diferente a 'derived.prototype' esto no afectará las propiedades heredadas por esos dos objetos. – CMS

2

Por ejemplo, usted tiene código:

function Animal() { 
} 
Animal.prototype.name="animal"; 

function Dog() { 
} 
Dog.prototype = new Animal 
Dog.prototype.constructor=Dog; 
Dog.prototype.name="dog"; 

object1 = new Animal(); 
object2 = new Dog(); 

Como resultado, usted tiene dos instancias de objeto, que parecía como (Esto se puede comprobar por ejemplo en Chrome devtools o FF o incendiario ...):

object1: 
    __proto__: (is ref into an Animal.prototype object) 
    constructor: function Animal() 
    name: "animal" 
    __proto__: Object (is ref into an Object.prototype object) 

object2: 
    __proto__: (is ref into an Dog.prototype object) 
    constructor: function Dog() 
    name: "dog" 
    __proto__: (is ref into an Animal.prototype object) 
     constructor: function Animal() 
     name: "animal" 
     __proto__: (is ref into an Object.prototype object) 

Cuando se ejecuta el código siguiente (por ejemplo):

alert(object1.name); // displayed "animal" 
alert(object2.name); // displayed "dog" 

¿Qué pasó? 1) Javascript buscó el nombre de la propiedad en la instancia del objeto (en object1 o object2). 2) Cuando no se encuentra, se buscó en la instancia de objeto proto propiedad (que es lo mismo que el prototipo de la función de clase). 3) Cuando no se buscó en proto de proto y el siguiente y el siguiente mientras no se encuentra name propiedad y otros proto encontrado. Si se encuentra como resultado de la propiedad de búsqueda, se devuelve el valor, si no se encuentra, se devuelve undefined.

¿Qué pasó si se ejecuta el código siguiente:

object2.name = "doggy"; 

Como resultado, usted tiene para objeto2:

object2: 
    name: "doggy" 
    __proto__: (is ref into an Dog.prototype object) 
    constructor: function Dog() 
    name: "dog" 
    __proto__: (is ref into an Animal.prototype object) 
     constructor: function Animal() 
     name: "animal" 
     __proto__: (is ref into an Object.prototype object) 

propiedad se asigna directamente a instancia de objeto, pero el objeto prototipo se mantiene sin cambios.Y cuando se ejecuta:

alert(object1.name); // displayed "animal" 
alert(object2.name); // displayed "doggy" 

cuando se necesita para crear | cambio compartida propiedad de clase, puede utilizar uno de los siguientes algoritms: 1)

Animal.prototype.secondName="aaa"; 
alert(object1.secondName); // displayed "aaa" 
alert(object2.secondName); // displayed "aaa" 
Animal.prototype.secondName="bbb"; 
alert(object1.secondName); // displayed "bbb" 
alert(object2.secondName); // displayed "bbb" 
// but 
Animal.prototype.secondName="ccc"; 
object1.secondName="ddd"; 
alert(object1.secondName); // displayed "ccc" 
alert(object2.secondName); // displayed "ddd" 

2) Cree una propiedad de tipo object en prototipo de clase de función y asigne valores a las propiedades de este objeto.

Animal.prototype.propObject={thirdName:"zzz"}; 
alert(object1.propObject.thirdName); // displayed "zzz" 
alert(object2.propObject.thirdName); // displayed "zzz" 
Animal.prototype.propObject.thirdName="yyy"; 
alert(object1.propObject.thirdName); // displayed "yyy" 
alert(object2.propObject.thirdName); // displayed "yyy" 
object1.propObject.thirdName="xxx"; 
alert(object1.propObject.thirdName); // displayed "xxx" 
alert(object2.propObject.thirdName); // displayed "xxx" 
object2.propObject.thirdName="www"; 
alert(object1.propObject.thirdName); // displayed "www" 
alert(object2.propObject.thirdName); // displayed "www" 
+0

Bien explicado. –

Cuestiones relacionadas