EDITAR fevereiro de 2012: a resposta abaixo não é mais precisa. __proto__ está sendo adicionado ao ECMAScript 6 como "opcional normativo", o que significa que sua implementação não é obrigatória, mas se for, deve seguir o conjunto de regras fornecido. Isso não está resolvido no momento, mas pelo menos fará parte oficialmente da especificação do JavaScript.
Esta questão é muito mais complicada do que parece na superfície, e está além do nível de pagamento da maioria das pessoas no que diz respeito ao conhecimento interno de Javascript.
A prototype
propriedade de um objeto é usada ao criar novos objetos filho desse objeto. Mudá-lo não reflete no próprio objeto, ao invés disso, é refletido quando esse objeto é usado como um construtor para outros objetos, e não tem nenhuma utilidade na mudança do protótipo de um objeto existente.
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
Os objetos têm uma propriedade interna [[prototype]] que aponta para o protótipo atual. A maneira como funciona é sempre que uma propriedade em um objeto é chamada, ela começa no objeto e então sobe pela cadeia [[protótipo]] até encontrar uma correspondência, ou falha, após o protótipo raiz do objeto. É assim que o Javascript permite a construção e modificação de objetos em tempo de execução; tem um plano para buscar o que precisa.
A __proto__
propriedade existe em algumas implementações (muitas agora): qualquer implementação do Mozilla, todas as do webkit que eu conheço, algumas outras. Esta propriedade aponta para a propriedade interna [[prototype]] e permite modificação pós-criação em objetos. Todas as propriedades e funções serão instantaneamente alteradas para corresponder ao protótipo devido a essa pesquisa em cadeia.
Esse recurso, embora esteja sendo padronizado agora, ainda não é uma parte necessária do JavaScript e, em linguagens que o suportam, tem uma grande probabilidade de derrubar seu código na categoria "não otimizado". Os mecanismos JS têm que fazer o melhor para classificar o código, especialmente o código "quente", que é acessado com frequência, e se você estiver fazendo algo sofisticado como modificar __proto__
, eles não otimizarão seu código de forma alguma.
Esta postagem https://bugzilla.mozilla.org/show_bug.cgi?id=607863 discute especificamente as implementações atuais __proto__
e as diferenças entre elas. Cada implementação faz isso de maneira diferente, porque é um problema difícil e sem solução. Tudo em Javascript é mutável, exceto a.) A sintaxe b.) Objetos de host (o DOM existe fora do Javascript tecnicamente) e c.) __proto__
. O resto está completamente nas mãos de você e de todos os outros desenvolvedores, então você pode ver por que __proto__
se destaca como um polegar dolorido.
Há uma coisa que __proto__
permite que isso seja impossível de fazer: a designação de um protótipo de objeto em tempo de execução separado de seu construtor. Este é um caso de uso importante e um dos principais motivos pelos quais __proto__
ainda não morreu. É importante o suficiente para que tenha sido um ponto de discussão sério na formulação do Harmony, ou em breve será conhecido como ECMAScript 6. A capacidade de especificar o protótipo de um objeto durante a criação fará parte da próxima versão do Javascript e esta será o sino que indica __proto__
os dias está formalmente contado.
No curto prazo, você pode usar __proto__
se estiver visando navegadores que o suportem (não o IE, e nenhum IE jamais oferecerá). É provável que funcione no webkit e moz pelos próximos 10 anos, pois o ES6 não será finalizado até 2013.
Brendan Eich - re: Abordagem de novos métodos de Objeto no ES5 :
Desculpe, ... mas configurável __proto__
, além do caso de uso do inicializador de objeto (ou seja, em um novo objeto ainda não alcançável, análogo ao Object.create do ES5), é uma ideia terrível. Escrevo isto tendo projetado e implementado configurável há __proto__
mais de 12 anos.
... a falta de estratificação é um problema (considere os dados JSON com uma chave "__proto__"
). E pior, a mutabilidade significa que as implementações devem verificar cadeias de protótipos cíclicos para evitar ilooping. [verificações constantes para recursão infinita são necessárias]
Finalmente, a mutação __proto__
em um objeto existente pode interromper métodos não genéricos no novo objeto de protótipo, que não pode funcionar no objeto receptor (direto) que __proto__
está sendo definido. Isso é simplesmente uma má prática, uma forma de confusão intencional de tipo, em geral.