Object.setPrototypeOf()

O método Object.setPrototypeOf() configura o 'prototype' (i.e., a propriedade interna [[Prototype]]) de um objeto específico para outro objeto ou null.

Aviso: 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

Compatibilidade com navegadores

BCD tables only load in the browser

Veja também