O método Object.setPrototypeOf()
configura o 'prototype' (i.e., a propriedade interna [[Prototype]]
) de um objeto específico para outro objeto ou null
.
Atenção: Mudar o [[Prototype]]
de um objeto é, pela natureza de como os modernos mecanismos JavaScript otimizam os acessos de propriedade, uma operação muito lenta, em todos navegadores e mecanismos JavaScript. O efeito sobre o desempenho de alterar a herança são sutis e vastas e não se limitam simplesmente ao tempo gasto em obj.__proto__ = ...
statement, mas pode estender a qualquer código que tem acesso a qualquer objeto cujo [[Prototype]]
foi alterado. Se você se preocupa com desempenho, você deveria evitar configurar o [[Prototype]]
de um objeto. Em vez disso, crie um novo objeto com o [[Prototype]] desejado usando
Object.create()
.
Sintaxe
Object.setPrototypeOf(obj, prototype);
Parâmetros
obj
- O objeto que deve ter seu 'prototype' definido.
prototype
- O novo 'prototype' do objeto (um objeto ou
null
).
Valor de retorno
O objeto especificado.
Descrição
Gera uma exceção TypeError
se o objeto cujo [[Prototype]]
é para ser modificado não for extensível de acordo com Object.isExtensible()
. Não faz nada se o parâmetro 'prototype'
não for um objeto ou null
(ex., número, texto, boleano, ou undefined
). Caso contrário, este método muda o [[Prototype]]
do obj
para um novo valor.
Object.setPrototypeOf() é uma especificação
ECMAScript 2015. É geralmente considerada a maneira correta de definir o 'prototype' de um objeto, em relação à propriedade mais controversa Object.prototype.__proto__
.
Exemplos
var dict = Object.setPrototypeOf({}, null);
Polyfill
Usando a propriedade mais antiga Object.prototype.__proto__
, nós podemos facilmente definir Object.setPrototypeOf
se já não estiver disponível:
// Funciona somente no Chrome e FireFox, não funciona no IE: Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) { obj.__proto__ = proto; return obj; }
Adicionando 'Prototype' em cadeia
Uma combinação de Object.getPrototypeOf() e
Object.prototype.__proto__
permite anexar toda uma cadeia de 'prototype' a um novo objeto 'prototype':
/** *** Object.appendChain(@object, @prototype) * * Acrescente o primeiro 'prototype' não nativo de uma cadeia a um novo 'prototype'. * Retorna @object (se for um valor primitivo, será transformado em um objeto). * *** Object.appendChain(@object [, "@arg_name_1", "@arg_name_2", "@arg_name_3", "..."], "@function_body") *** Object.appendChain(@object [, "@arg_name_1, @arg_name_2, @arg_name_3, ..."], "@function_body") * * Adicione o primeiro 'prototype' não nativo de uma cadeia ao objeto nativo Function.prototype, então anexar a nova função * Function(["@arg"(s)], "@function_body") àquela cadeia. * Retorna a função. * **/ Object.appendChain = function(oChain, oProto) { if (arguments.length < 2) { throw new TypeError('Object.appendChain - Argumentos insuficientes'); } if (typeof oProto !== 'object' && typeof oProto !== 'string') { throw new TypeError('segundo argumento de Object.appendChain deve ser um objeto ou uma string'); } var oNewProto = oProto, oReturn = o2nd = oLast = oChain instanceof this ? oChain : new oChain.constructor(oChain); for (var o1st = this.getPrototypeOf(o2nd); o1st !== Object.prototype && o1st !== Function.prototype; o1st = this.getPrototypeOf(o2nd) ) { o2nd = o1st; } if (oProto.constructor === String) { oNewProto = Function.prototype; oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1)); this.setPrototypeOf(oReturn, oLast); } this.setPrototypeOf(o2nd, oNewProto); return oReturn; }
Exemplos
Primeiro exemplo: Adicionar uma cadeia a um 'prototype'.
function Mammal() { this.isMammal = 'yes'; } function MammalSpecies(sMammalSpecies) { this.species = sMammalSpecies; } MammalSpecies.prototype = new Mammal(); MammalSpecies.prototype.constructor = MammalSpecies; var oCat = new MammalSpecies('Felis'); console.log(oCat.isMammal); // 'yes' function Animal() { this.breathing = 'yes'; } Object.appendChain(oCat, new Animal()); console.log(oCat.breathing); // 'yes'
Segundo exemplo: Transformar um valor primitivo em uma instância de seu construtor e anexar sua cadeia a um 'prototype'.
function MySymbol() { this.isSymbol = 'yes'; } var nPrime = 17; console.log(typeof nPrime); // 'number' var oPrime = Object.appendChain(nPrime, new MySymbol()); console.log(oPrime); // '17' console.log(oPrime.isSymbol); // 'yes' console.log(typeof oPrime); // 'object'
Terceiro exemplo: Anexar uma cadeia ao objeto Function.prototype e anexar uma nova função a essa cadeia.
function Person(sName) { this.identity = sName; } var george = Object.appendChain(new Person('George'), 'console.log("Hello guys!!");'); console.log(george.identity); // 'George' george(); // 'Hello guys!!'
Especificações
Especificação | Situação | Comentário |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object.setProtoypeOf' in that specification. |
Padrão | Definição inicial. |
ECMAScript Latest Draft (ECMA-262) The definition of 'Object.setProtoypeOf' in that specification. |
Rascunho |
Compatibilidade do navegador
Configuração | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Suporte básico | 34 | 31 (31) | 11 | (Yes) | 9 |
Configuração | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Suporte básico | Não suportado | Não suportado | 31.0 (31) | ? | Não suportado | 9 |