recorrer orientado objetos objeto lista herencia ejemplos crear clases array agregar javascript arrays oop class prototype

orientado - prototype javascript ejemplos



Los miembros de objetos Javascript que son prototipados como matrices se comparten entre todas las instancias de clases (3)

Cuando hace var exp1 = new C() , JavaScript establece exp1.[[Prototype]] = C.prototype . Cuando luego accede a las propiedades de la instancia, JavaScript primero verifica si existen en ese objeto directamente, y si no, se ve en [[Prototype]] . Esto significa que todas las cosas que define en el prototipo se comparten de manera efectiva en todas las instancias, e incluso más adelante puede cambiar partes del prototipo y hacer que los cambios aparezcan en todas las instancias existentes.

¿Alguien ha notado este comportamiento antes? Esto realmente me sorprendió ... Hubiera esperado que los arrays de prototipos fueran privados para cada instancia de clase en lugar de compartirse entre todas las instancias de clase.

¿Puede alguien verificar que este es el comportamiento correcto y quizás explicar este comportamiento con más detalle?

Observe el código comentado y cómo afecta el comportamiento del script.

<html> <head> <script type="text/javascript"> function print_r( title, object ) { var output = ''''; for( var key in object ) { output += key + ": " + object[ key ] + "/n"; } output = title + "/n/n" + output; alert( output ); } function Sandwich() { // Uncomment this to fix the problem //this.ingredients = []; } Sandwich.prototype = { "ingredients" : [], "addIngredients" : function( ingArray ) { for( var key in ingArray ) { this.addIngredient( ingArray[ key ] ); } }, "addIngredient" : function( thing ) { this.ingredients.push( thing ); } } var cheeseburger = new Sandwich(); cheeseburger.addIngredients( [ "burger", "cheese" ] ); var blt = new Sandwich(); blt.addIngredients( [ "bacon", "lettuce", "tomato" ] ); var spicy_chicken_sandwich = new Sandwich(); spicy_chicken_sandwich.addIngredients( [ "spicy chicken pattie", "lettuce", "tomato", "honey dijon mayo", "love" ] ); var onLoad = function() { print_r( "Cheeseburger contains:", cheeseburger.ingredients ); }; </script> </head> <body onload="onLoad();"> </body> </html>

Muchas gracias.


El comportamiento es correcto. [] se traduce en una new Array() en tiempo de ejecución, pero solo se crea una.

En otras palabras, Obj.prototype = {...} se ejecuta como cualquier otra asignación.


El prototipo de un objeto es solo un objeto. Las propiedades del prototipo se comparten entre todos los objetos que heredan de ese objeto. No se realizan copias de las propiedades si crea una nueva instancia de una "clase" (las clases no existen de todos modos en JS), es decir, un objeto que hereda del prototipo.

Solo hace una diferencia sobre cómo usar estas propiedades heredadas:

function Foo() {} Foo.prototype = { array: [], func: function() {} } a = new Foo(); b = new Foo(); a.array.push(''bar''); console.log(b.array); // prints ["bar"] b.func.bar = ''baz''; console.log(a.func.bar); // prints baz

En todos estos casos, siempre está trabajando con el mismo objeto.

Pero si asigna un valor a una propiedad del objeto, la propiedad se establecerá / creará en el objeto mismo, no en su prototipo, y por lo tanto no se comparte:

console.log(a.hasOwnProperty(''array'')); // prints false console.log(a.array); // prints ["bar"] a.array = [''foo'']; console.log(a.hasOwnProperty(''array'')); // prints true console.log(a.array); // prints ["foo"] console.log(b.array); // prints ["bar"]

Si desea crear matrices propias para cada instancia, debe definirlas en el constructor:

function Foo() { this.array = []; }

porque aquí, this refiere al new objeto que se genera cuando llamas a un new Foo() .

La regla general es: los datos específicos de instancia se deben asignar a la instancia dentro del constructor , los datos compartidos (como los métodos) se deben asignar al prototipo .

Es posible que desee leer Detalles del modelo de objetos que describe las diferencias entre los lenguajes basados ​​en clases y prototipos y cómo funcionan realmente los objetos.

Actualizar:

Puede acceder al prototipo de un objeto a través de Object.getPrototypeOf(obj) (puede que no funcione en navegadores muy antiguos), y Object.getPrototypeOf(a) === Object.getPrototypeOf(b) le da true . Es el mismo objeto, también conocido como Foo.prototype .