Function.prototype.bind()
=========================

O método **`bind()`** cria uma nova função que, quando chamada, tem sua palavra-chave `this` definida com o valor fornecido, com uma sequência determinada de argumentos precedendo quaisquer outros que sejam fornecidos quando a nova função é chamada.

Experimente
-----------

Sintaxe
-------
```

function.bind(thisArg[, arg1[, arg2[, ...]]])
```

### Parâmetros

`thisArg`

O valor a ser passado como parâmetro `this` para a função de destino quando a função vinculada é chamada. O valor é ignorado se a função ligada é construída usando o operador `new`.

`arg1, arg2, ...`

Argumentos que precedem outros argumentos fornecidos para a função vinculada ao invocar a função de destino.

### Valor de retorno

Uma cópia da função fornecida com o valor `this` especificado e argumentos iniciais.

Descrição
---------

A função `bind()` cria uma nova **função vinculada** (*bound function*). Uma função vinculada é um **objeto de função exótico** (termo da **ECMAScript 2015**) que encapsula o objeto de função original. Chamar uma função vinculada geralmente resulta na execução de sua **função encapsulada**.

Uma função vinculada tem as seguintes propriedades internas:

* **[[BoundTargetFunction]]** - o objeto de função encapsulado;
* **[[BoundThis]]** - o valor que sempre é passado como `this` quando se chama a função encapsulada;
* **[[BoundArguments]]** - uma lista de valores cujos elementos são usados como os primeiros argumentos para qualquer chamada da função encapsulada;
* **[[Call]]** - executa código associado com este objeto. Invocado através de uma expressão de chamada de função. Os argumentos para o método interno são um valor `this` e uma lista contendo os argumentos passados para a função por uma expressão de chamada.

Quando a função vinculada é chamada, ela chama seu método interno **[[Call]]** na **[[BoundTargetFunction]],** na forma `Call(boundThis, args)`, onde `boundThis` é **[[BoundThis]]** e `args` é **[[BoundArguments]]** seguido pelos argumentos passados pela chamada de função.

Uma função vinculada também pode ser construída usando-se o operador `new`; ao fazê-lo, o resultado é o mesmo que seria se a função alvo tivesse sido construída. O valor de `this` fornecido é ignorado, porém os argumentos precedentes são fornecidos à função emulada.

Exemplos
--------

### Criando uma função vinculada

O uso mais simples de `bind()` é fazer com que uma função que, independentemente da chamada, é chamada com um determinado valor `this`. Um erro comum para programadores JavaScript novatos é extrair um método de um objeto e, em seguida, chamar essa função e esperar que ele use o objeto original como o seu `this` (por exemplo, usando esse método num código baseado em *callback*). Sem a devida atenção, no entanto, o objeto original é normalmente perdido. Criar uma função vinculada a partir da função, usando o objeto original, resolve perfeitamente esse problema:


```js
this.x = 9; //this aqui se refere ao objeto global "window" do navegador
var module = {
  x: 81,
  getX: function () {
    return this.x;
  },
};

module.getX(); // 81

var retrieveX = module.getX;
retrieveX();
// retorna 9 - a função foi invocada no escopo global

// Criando uma nova função com 'this' vinculada ao módulo
// Programadores novatos podem confundir a variável x
// global com a propriedade x do módulo
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
```

### Funções parcialmente aplicadas

O próximo uso mais simples de `bind()` é criar uma função com argumentos iniciais pré-especificados. Esses argumentos (caso existam) acompanham o valor `this` fornecido e então são inseridos no início dos argumentos passados para a função alvo, seguidos pelos argumentos passados para a função vinculada, sempre que a função vinculada é chamada.


```js
function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

// Cria uma função com um argumento principal predefinido
var leadingThirtysevenList = list.bind(null, 37);

var list2 = leadingThirtysevenList();
// [37]

var list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
```

### Com `setTimeout`

Por padrão, dentro de `window.setTimeout()` (en-US) a palavra-chave `this` vai ser definida com o objeto `window` (ou com o objeto `global`). Ao trabalhar com métodos de classes que requerem que `this` se refira à instâncias de classes, você pode vincular `this` explicitamente à função de *callback*, de modo a manter a instância.


```js
function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() \* 12) + 1;
}

// Declarar bloom depois de um intervalo de 1 segundo
LateBloomer.prototype.bloom = function () {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function () {
  console.log("I am a beautiful flower with " + this.petalCount + " petals!");
};

var flower = new LateBloomer();
flower.bloom();
// depois de 1 segundo, ativa o método 'declare'
```

### Funções vinculadas usadas como construtores

**Aviso:** Esta seção demonstra capacidades do JavaScript e documenta alguns casos de borda do método `bind()`. Os métodos mostrados abaixo não são os melhores jeitos de se fazer as coisas e provavelmente não deveriam ser usados em nenhum ambiente produtivo.

Funções vinculadas são automaticamente adequadas para uso com o operador `new` para construir novas instâncias criadas pela função alvo. Quando uma função vinculada é usada para construir um valor, o `this` fornecido é ignorado. Porém, argumentos fornecidos ainda são prefixados à chamada do construtor:


```js
function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return this.x + "," + this.y;
};

var p = new Point(1, 2);
p.toString(); // '1,2'

// não suportado no polyfill abaixo,
// funciona bem com o bind nativo:

var YAxisPoint = Point.bind(null, 0 /\*x\*/);

var emptyObj = {};
var YAxisPoint = Point.bind(emptyObj, 0 /\*x\*/);

var axisPoint = new YAxisPoint(5);
axisPoint.toString(); // '0,5'

axisPoint instanceof Point; // true
axisPoint instanceof YAxisPoint; // true
new Point(17, 42) instanceof YAxisPoint; // true
```


Note que você não precisa fazer nada de especial para criar uma função vinculada para usar com `new`. O corolário é que você não precisa fazer nada de especial para criar uma função vinculada que será chamada de forma clara, mesmo que você preferisse que a função vinculada fosse somente chamada usando-se `new`.


```js
// Exemplo pode ser executado diretamente no seu console JavaScript
// ...continuando o exemplo acima

// Ainda pode ser chamada como uma função normal
// (apesar de que isso geralmente não é desejado)
YAxisPoint(13);

emptyObj.x + "," + emptyObj.y;
// > '0,13'
```


Se você quer suportar o uso de uma função vinculada somente através de `new`, ou somente a chamando, a função alvo deve impor essa restrição.

### Criando atalhos

`bind()` itambém é útil em casos onde você quer criar um atalho para uma função que requer um valor específico de `this`.

Tome por exemplo `Array.prototype.slice`, que você quer usar para converter um objeto *array-like* em um vetor verdadeiro. Você poderia criar um atalho assim:


```js
var slice = Array.prototype.slice;

// ...

slice.apply(arguments);
```


Com `bind()`, isso pode ser simplificado. No seguinte trecho de código, `slice` é uma função vinculada à função `apply()` de `Function.prototype` (en-US), com o valor `this` definido com a função `slice()` de `Array.prototype`. Isso significa que chamadas adicionais de `apply()` podem ser eliminadas:


```js
// mesmo que "slice" no exemplo anterior
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);

// ...

slice(arguments);
```

Polyfill
--------

A função `bind` é uma adição à ECMA-262, 5ª. edição; como tal, pode não estar presente em todos os navegadores. Você pode contornar isso parcialmente inserindo o seguinte código no começo de seus *scripts*, permitindo o uso de muita parte da funcionalidade de `bind()` em implementações que não a suportam nativamente.


```js
if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // mais próximo possível da função interna
      // IsCallable da ECMAScript 5
      throw new TypeError(
        "Function.prototype.bind - what is trying to be bound is not callable",
      );
    }

    var aArgs = Array.prototype.slice.call(arguments, 1),
      fToBind = this,
      fNOP = function () {},
      fBound = function () {
        return fToBind.apply(
          this instanceof fNOP ? this : oThis,
          aArgs.concat(Array.prototype.slice.call(arguments)),
        );
      };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}
```


Algumas das muitas diferenças (é bem possível que haja outras, já que esta lista não pretende seriamente ser completa) entre este algoritmo e o algoritmo especificado são:

* Esta implementação parcial depende dos métodos internos `Array.prototype.slice()`, `Array.prototype.concat()`, `Function.prototype.call()` e `Function.prototype.apply()` possuírem seus valores originais.
* Esta implementação parcial cria funções que não tem um `caller` imutável como "mecanismo de defesa" e propriedades `arguments` que lançam um `TypeError` ao usar *get*, *set*, ou ao deletar. (Isto pode ser adicionado se a implementação suporta `Object.defineProperty`, ou parcialmente implementado sem um comportamento *throw-on-delete* se a implementação suporta as extensões `Object.prototype.__defineGetter__()` e `Object.prototype.__defineSetter__()`)
* Esta implementação parcial cria funções que tem uma propriedade `prototype`. (Funções vinculadas apropriadas não a tem.)
* Esta implementação parcial cria funções vinculadas cuja propriedade `length` não cumpre com a regra da ECMA-262: cria funções com comprimento zero, quando uma implementação completa, dependendo do comprimento da função alvo e do número de argumentos pre-especificados, pode retornar um comprimento não-nulo.

Se você escolher utilizar esta implementação parcial, **você não deve confiar em casos onde o comportamento é diferente da ECMA-262, 5ª. edição!** Porém, com algum cuidado (e talvez com modificação adicional para atender necessidades específicas), esta implementação parcial pode ser uma ponte razoável para quando `bind()` for amplamente implementada de acordo com a especificação.

Especificações
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-function.prototype.bind |

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

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

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

* `Function.prototype.apply()`
* `Function.prototype.call()`
* Functions