Membros de object Javascript que são prototipados como matrizes se tornam compartilhados por todas as instâncias de class

Alguém já notou esse comportamento antes? Isso realmente me jogou fora … Eu teria esperado que as matrizes prototipadas fossem privadas para cada instância de class em vez de serem compartilhadas entre todas as instâncias de class.

Alguém pode verificar se esse é o comportamento correto e talvez explicar esse comportamento com mais detalhes?

Observe o código comentado e como isso afeta o comportamento do script.

   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 ); };      

Muito Obrigado.

O protótipo de um object é apenas um object. As propriedades do protótipo são compartilhadas entre todos os objects que herdam desse object. Nenhuma cópia das propriedades é feita se você criar uma nova instância de uma “class” (classs não existem de qualquer maneira no JS), isto é, um object que herda do protótipo.

Isso só faz diferença em como você usa essas propriedades herdadas:

 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 

Em todos esses casos, você está sempre trabalhando com o mesmo object.

Mas se você atribuir um valor a uma propriedade do object, a propriedade será definida / criada no próprio object, não em seu protótipo e, portanto, não será compartilhada:

 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"] 

Se você quiser criar matrizes próprias para cada instância, você deve defini-lo no construtor:

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

porque aqui, this se refere ao new object que é gerado quando você chama o new Foo() .

A regra geral é: Dados específicos da instância devem ser atribuídos à instância dentro do construtor , dados compartilhados (como methods) devem ser atribuídos ao protótipo .


Você pode querer ler Detalhes do modelo de object que descreve as diferenças entre os idiomas baseados em class versus os baseados em protótipos e como os objects realmente funcionam.

Atualizar:

É possível acessar o protótipo de um object via Object.getPrototypeOf(obj) (pode não funcionar em navegadores muito antigos) e Object.getPrototypeOf(a) === Object.getPrototypeOf(b) fornece a true . É o mesmo object, também conhecido como Foo.prototype .

O comportamento está correto. [] é transferido para o new Array() em tempo de execução, mas apenas um desses arrays é criado.

Em outras palavras, Obj.prototype = {...} é executado como qualquer outra atribuição.

Quando você faz var exp1 = new C() , o JavaScript define exp1.[[Prototype]] = C.prototype . Quando você acessa as propriedades da instância, o JavaScript primeiro verifica se elas existem diretamente nesse object e, caso contrário, procura no [[Prototype]] . Isso significa que todas as coisas que você define no protótipo são efetivamente compartilhadas por todas as instâncias, e você pode até mesmo alterar partes do protótipo e fazer com que as alterações apareçam em todas as instâncias existentes.