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


```js
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:


```js
// 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':


```js
/\*\*
 \*\*\* 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'


```js
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'


```js
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


```js
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
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.setprototypeof |

Compatibilidade com navegadores
-------------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Veja também
-----------

* `Reflect.setPrototypeOf()` (en-US)
* `Object.prototype.isPrototypeOf()`
* `Object.getPrototypeOf()`
* `Object.prototype.__proto__`