Qual é o uso do método 'bind' do JavaScript?

651

Para que serve o bind()JavaScript?

Sandeep Kumar
fonte
8
Meu caso de uso padrão:select = document.querySelector.bind(document)
ceving 01/12/19
1
^ E para quem se pergunta, o motivo necessário é porque this, de outra forma, se referiria ao windowobjeto global. Com document.querySelector.bind(document), podemos garantir que select's thisrefere-se a document, e não para window. Alguém me corrija se eu não entendi isso, no entanto.
AleksandrH

Respostas:

614

Vincular cria uma nova função que força o thisinterior da função a ser o parâmetro passado bind().

Aqui está um exemplo que mostra como usar bindpara passar um método membro com o correto this:

var myButton = {
  content: 'OK',
  click() {
    console.log(this.content + ' clicked');
  }
};

myButton.click();

var looseClick = myButton.click;
looseClick(); // not bound, 'this' is not myButton - it is the globalThis

var boundClick = myButton.click.bind(myButton);
boundClick(); // bound, 'this' is myButton

Que imprime:

OK clicked
undefined clicked
OK clicked

Você também pode adicionar parâmetros extras após o 1º thisparâmetro ( ) e bindpassará esses valores para a função original. Quaisquer parâmetros adicionais que você passar posteriormente para a função vinculada serão passados ​​após os parâmetros associados:

// Example showing binding some parameters
var sum = function(a, b) {
  return a + b;
};

var add5 = sum.bind(null, 5);
console.log(add5(10));

Que imprime:

15

Confira a função JavaScript bind para obter mais informações e exemplos interativos.

Atualização: o ECMAScript 2015 adiciona suporte para =>funções. =>As funções são mais compactas e não alteram o thisponteiro do escopo definido; portanto, talvez você não precise usá-lo com tanta bind()frequência. Por exemplo, se você deseja que uma função Buttondo primeiro exemplo ligue o clickretorno de chamada a um evento DOM, todas as formas a seguir são válidas:

var myButton = {
  ... // As above
  hookEvent(element) {
    // Use bind() to ensure 'this' is the 'this' inside click()
    element.addEventListener('click', this.click.bind(this));
  }
};

Ou:

var myButton = {
  ... // As above
  hookEvent(element) {
    // Use a new variable for 'this' since 'this' inside the function
    // will not be the 'this' inside hookEvent()
    var me = this;
    element.addEventListener('click', function() { me.click() });
  }
};    

Ou:

var myButton = {
  ... // As above
  hookEvent(element) {
    // => functions do not change 'this', so you can use it directly
    element.addEventListener('click', () => this.click());
  }
};
nkron
fonte
6
Excelente explicação, mas estou lutando para encontrar exemplos em que gostaria de usar a terceira opção que você descreveu em vez da primeira opção. Você pode descrever situações em que sentiu necessidade de usar a terceira opção?
Darryl
5
Eu acho que nunca usei bind a não ser para vincular 'this'. A outra forma é conhecida como Aplicativo Parcial e é bastante comum em linguagens funcionais. Eu imagino que está incluído para ser completo.
Nkron
43
Caso alguém esteja se perguntando por que looseClick () não está vinculado ao myButton, é porque "this" se refere ao objeto que chama a função (looseClick ()). O objeto que chama looseClick () é o objeto global.
Pokero
4
@ Darryl - Uma razão pela qual seria passar parâmetros de manipuladores de eventos. Se você tiver este código de reação:, var Note = React.createClass({ add: function(text){ ... }, render: function () { return <button onClick={this.add.bind(null, "New Note")}/> } }quando clicar no botão, ele passará o texto de parâmetro "Nova Nota" para o addmétodo.
P. Myer Nore
2
"Você também pode adicionar parâmetros extras após o 1º parâmetro e a ligação passará esses valores para a função original antes de passar os parâmetros extras que você passará para a função vinculada:" Esta redação é confusa.
Ken Ingram
271

O uso mais simples de bind()é criar uma função que, não importa como seja chamada, é chamada com um thisvalor específico .

x = 9;
var module = {
    x: 81,
    getX: function () {
        return this.x;
    }
};

module.getX(); // 81

var getX = module.getX;
getX(); // 9, because in this case, "this" refers to the global object

// create a new function with 'this' bound to module
var boundGetX = getX.bind(module);
boundGetX(); // 81

Consulte este link para mais informações

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Renganathan MG
fonte
38
A melhor introdução ao bind () que eu já vi.
Thomasfl 26/08/16
3
Ótima resposta, já que seu exemplo não requer conhecimento sobre os recursos do idioma (por exemplo prototype) que podem ser novos para iniciantes.
Edward
1
sucinto e muito claro!
papigee 03/06
172

vincular permite

  • defina o valor "this" para um objeto específico. Isso se torna muito útil, pois às vezes não é esse o objetivo.
  • métodos de reutilização
  • curry uma função

Por exemplo, você tem a função de deduzir as taxas mensais do clube

function getMonthlyFee(fee){
  var remaining = this.total - fee;
  this.total = remaining;
  return this.name +' remaining balance:'+remaining;
}

Agora você deseja reutilizar esta função para um sócio do clube diferente. Observe que a taxa mensal varia de membro para membro.

Vamos imaginar que Rachel tenha um saldo de 500 e uma taxa de associação mensal de 90.

var rachel = {name:'Rachel Green', total:500};

Agora, crie uma função que possa ser usada repetidamente para deduzir a taxa da conta dela todos os meses

//bind
var getRachelFee = getMonthlyFee.bind(rachel, 90);
//deduct
getRachelFee();//Rachel Green remaining balance:410
getRachelFee();//Rachel Green remaining balance:320

Agora, a mesma função getMonthlyFee pode ser usada para outro membro com uma taxa de associação diferente. Por exemplo, Ross Geller tem um saldo de 250 e uma taxa mensal de 25

var ross = {name:'Ross Geller', total:250};
//bind
var getRossFee = getMonthlyFee.bind(ross, 25);
//deduct
getRossFee(); //Ross Geller remaining balance:225
getRossFee(); //Ross Geller remaining balance:200
Jhankar Mahbub
fonte
9
No seu exemplo, acho que estaria inclinado a configurar um objeto de membro instanciado com a nova palavra-chave em que cada membro tinha suas próprias propriedades / métodos. Então é simplesmente uma questão de ross.getMonthlyFee (25). Este exemplo foi apenas para demonstrar o uso de bind () ou há alguma vantagem em sua abordagem?
Darryl
amo o curry uma função!
Jerry Liu
eu não sei, mas eu faria var getRachelFee = getMonthlyFee (rachel, 90); E function seria function getMonthlyFee (member, fee) {} algo ao longo das linhas.
Miguel
1
@KhanSharp Sua resposta está correta, mas são suas referências aos amigos da série de TV que me fazem comentar e votar. Obrigado pela resposta 🤗.
Saurabh Lende
79

A partir dos documentos MDN sobre Function.prototype.bind():

O método bind () cria uma nova função que, quando chamada, tem sua palavra-chave definida com o valor fornecido, com uma sequência de argumentos fornecida antes de qualquer fornecida quando a nova função é chamada.

Então, o que isso significa?!

Bem, vamos assumir uma função que se parece com isso:

var logProp = function(prop) {
    console.log(this[prop]);
};

Agora, vamos pegar um objeto que se parece com isso:

var Obj = {
    x : 5,
    y : 10
};

Podemos vincular nossa função ao nosso objeto assim:

Obj.log = logProp.bind(Obj);

Agora, podemos executar Obj.logem qualquer lugar do nosso código:

Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10

Isso funciona, porque vinculamos o valor de thisao nosso objeto Obj.


O que realmente interessa é quando você não apenas vincula um valor para this, mas também seu argumento prop:

Obj.logX = logProp.bind(Obj, 'x');
Obj.logY = logProp.bind(Obj, 'y');

Agora podemos fazer isso:

Obj.logX(); // Output : 5
Obj.logY(); // Output : 10

Ao contrário de Obj.log, não temos que passar xou y, porque passamos esses valores quando fizemos nossa ligação.

John Slegers
fonte
9
Esta resposta deve ter mais amor. Bem explicado.
Chax 04/07/19
Muito boa combinação de visão geral e exemplo específico.
Ken Ingram
Onde está o botão que dispara 100 ups seguidos?
Kushalvm
Com isso, eu também recomendaria a leitura da seção de documentos MDN das funções parcialmente aplicadas para entender o uso de bind "null". Ele deve fechar os portões durante a maior parte do uso da ligação. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
kushalvm
23

Variáveis ​​tem escopos locais e globais. Vamos supor que tenhamos duas variáveis ​​com o mesmo nome. Um é definido globalmente e o outro é definido dentro de um fechamento de função e queremos obter o valor da variável que está dentro do fechamento de função. Nesse caso, usamos este método bind (). Por favor, veja o exemplo simples abaixo:

var x = 9; // this refers to global "window" object here in the browser
var person = {
  x: 81,
  getX: function() {
    return this.x;
  }
};

var y = person.getX; // It will return 9, because it will call global value of x(var x=9).

var x2 = y.bind(person); // It will return 81, because it will call local value of x, which is defined in the object called person(x=81).

document.getElementById("demo1").innerHTML = y();
document.getElementById("demo2").innerHTML = x2();
<p id="demo1">0</p>
<p id="demo2">0</p>

krati agarwal
fonte
18

Resumo:

O bind()método pega um objeto como primeiro argumento e cria uma nova função. Quando a função é invocada, o valor de thisno corpo da função será o objeto que foi passado como argumento na bind()função.

Como thisfunciona em JS de qualquer maneira

O valor de thisem javascript é dependente sempre depende de qual objeto a função é chamada. O valor disso sempre se refere ao objeto à esquerda do ponto de onde a função é chamada . No caso do escopo global este é window(ou globalno nodeJS). Apenas call, applye bindpode alterar o presente de ligação diferente. Aqui está um exemplo para mostrar como essa palavra-chave funciona:

let obj = {
  prop1: 1,
  func: function () { console.log(this); } 
}

obj.func();   // obj left of the dot so this refers to obj

const customFunc = obj.func;  // we store the function in the customFunc obj

customFunc();  // now the object left of the dot is window, 
               // customFunc() is shorthand for window.customFunc()
               // Therefore window will be logged

Como o bind é usado?

O Bind pode ajudar a superar dificuldades com a thispalavra - chave, tendo um objeto fixo ao qual thisse referirá. Por exemplo:

var name = 'globalName';

const obj = {
  name: 'myName',
  sayName: function () { console.log(this.name);}
}

const say = obj.sayName; // we are merely storing the function the value of this isn't magically transferred

say(); // now because this function is executed in global scope this will refer to the global var

const boundSay = obj.sayName.bind(obj); // now the value of this is bound to the obj object

boundSay();  // Now this will refer to the name in the obj object: 'myName'

Uma vez que a função está vinculada a um thisvalor específico , podemos distribuí-la e até colocá-la nas propriedades de outros objetos. O valor de thispermanecerá o mesmo.

Willem van der Veen
fonte
3
Seus comentários em seu código sobre o objé o objeto porque ele é deixado no ponto e windowé o objeto porque é uma abreviação para window.custFunc()e windowé deixado no ponto foi muito perspicaz para mim.
Nzaleski 03/03/19
12

Vou explicar vincular teoricamente, bem como praticamente

bind em javascript é um método - Function.prototype.bind. bind é um método É chamado no protótipo de função. Este método cria uma função cujo corpo é semelhante à função na qual é chamado, mas o 'this' refere-se ao primeiro parâmetro passado ao método de ligação. Sua sintaxe é

     var bindedFunc = Func.bind(thisObj,optionsArg1,optionalArg2,optionalArg3,...);

Exemplo:--

  var checkRange = function(value){
      if(typeof value !== "number"){
              return false;
      }
      else {
         return value >= this.minimum && value <= this.maximum;
      }
  }

  var range = {minimum:10,maximum:20};

  var boundedFunc = checkRange.bind(range); //bounded Function. this refers to range
  var result = boundedFunc(15); //passing value
  console.log(result) // will give true;
dinesh_malhotra
fonte
Basicamente, transforma qualquer 'isso' dentro da função em qualquer objeto que você transmita, correto?
Harvey Lin
11

O método bind () cria uma nova instância de função cujo valor está vinculado ao valor que foi passado para bind (). Por exemplo:

   window.color = "red"; 
   var o = { color: "blue" }; 
   function sayColor(){ 
       alert(this.color); 
   } 
   var objectSayColor = sayColor.bind(o); 
   objectSayColor(); //blue 

Aqui, uma nova função chamada objectSayColor () é criada a partir de sayColor () chamando bind () e passando o objeto o. A função objectSayColor () possui esse valor equivalente a o, portanto, chamar a função, mesmo como uma chamada global, resulta na exibição da string "azul".

Referência: Nicholas C. Zakas - JAVASCRIPT® PROFISSIONAL PARA DESENVOLVEDORES DA WEB

Otti
fonte
exemplo conciso e lacônico
Ahmad Sharif
9

Criando uma nova função vinculando argumentos a valores

O bindmétodo cria uma nova função a partir de outra função com um ou mais argumentos vinculados a valores específicos, incluindo o thisargumento implícito .

Aplicação Parcial

Este é um exemplo de aplicação parcial . Normalmente, fornecemos uma função com todos os seus argumentos que produzem um valor. Isso é conhecido como aplicativo de função. Estamos aplicando a função a seus argumentos.

Uma função de ordem superior (HOF)

A aplicação parcial é um exemplo de uma função de ordem superior (HOF) porque produz uma nova função com um número menor de argumentos.

Vinculando vários argumentos

Você pode usar bindpara transformar funções com vários argumentos em novas funções.

function multiply(x, y) { 
    return x * y; 
}

let multiplyBy10 = multiply.bind(null, 10);
console.log(multiplyBy10(5));

Convertendo do método de instância para função estática

No caso de uso mais comum, quando chamado com um argumento, o bind método cria uma nova função que tem o thisvalor vinculado a um valor específico. Com efeito, isso transforma um método de instância em um método estático.

function Multiplier(factor) { 
    this.factor = factor;
}

Multiplier.prototype.multiply = function(x) { 
    return this.factor * x; 
}

function ApplyFunction(func, value) {
    return func(value);
}

var mul = new Multiplier(5);

// Produces garbage (NaN) because multiplying "undefined" by 10
console.log(ApplyFunction(mul.multiply, 10));

// Produces expected result: 50
console.log(ApplyFunction(mul.multiply.bind(mul), 10));

Implementando um retorno de chamada com estado

O exemplo a seguir mostra como o uso da ligação de thispode permitir que um método de objeto atue como um retorno de chamada que pode atualizar facilmente o estado de um objeto.

function ButtonPressedLogger()
{
   this.count = 0;
   this.onPressed = function() {
      this.count++;
      console.log("pressed a button " + this.count + " times");
   }
   for (let d of document.getElementsByTagName("button"))
      d.onclick = this.onPressed.bind(this);
}

new ButtonPressedLogger();      
<button>press me</button>
<button>no press me</button>

cdiggins
fonte
6

Conforme mencionado, Function.bind()permite especificar o contexto em que a função será executada (ou seja, permite passar em qual objeto o objetothis palavra chave será resolvida no corpo da função.

Alguns métodos análogos da API do kit de ferramentas que executam um serviço semelhante:

jQuery.proxy ()

Dojo.hitch ()

mtyson
fonte
3
/**
 * Bind is a method inherited from Function.prototype same like call and apply
 * It basically helps to bind a function to an object's context during initialisation 
 * 
 * */

window.myname = "Jineesh";  
var foo = function(){ 
  return this.myname;
};

//IE < 8 has issues with this, supported in ecmascript 5
var obj = { 
    myname : "John", 
    fn:foo.bind(window)// binds to window object
}; 
console.log( obj.fn() ); // Returns Jineesh
Jineesh
fonte
3

Considere o Programa Simples listado abaixo,

//we create object user
let User = { name: 'Justin' };

//a Hello Function is created to Alert the object User 
function Hello() {
  alert(this.name);
}

//since there the value of this is lost we need to bind user to use this keyword
let user = Hello.bind(User);
user();

//we create an instance to refer the this keyword (this.name);
GoodnessGoodness Chi
fonte
2

A função bind cria uma nova função com o mesmo corpo da função que está chamando. É chamada com este argumento .por que usamos o bind fun. : quando toda vez que uma nova instância é criada e precisamos usar a primeira instância inicial, usamos bind fun. Não podemos substituir o bind fun.simply ele armazena o objeto inicial da classe.

setInterval(this.animate_to.bind(this), 1000/this.difference);
user2485861
fonte
0

Outro uso é que você pode passar a função vinculada como argumento para outra função que esteja operando em outro contexto de execução.

var name = "sample";
function sample(){
  console.log(this.name);
}
var cb = sample.bind(this);

function somefunction(cb){
  //other code
  cb();
}
somefunction.call({}, cb);
Amar T
fonte
0

Exemplo simples

function lol(text) {
    console.log(this.name, text);
}

lol(); // undefined undefined
lol('first'); // undefined first
lol.call({name: 'karl'}); // karl undefined
lol.call({name: 'karl'}, 'second'); // karl second
lol.apply({name: 'meg'}); // meg undefined
lol.apply({name: 'meg'}, ['third']); // meg third
const newLol = lol.bind({name: 'bob'});
newLol(); // bob undefined
newLol('fourth'); // bob fourth
K - A toxicidade no SO está crescendo.
fonte
0

Método de ligação

Uma implementação de ligação pode ser algo assim:

Function.prototype.bind = function () {
  const self = this;
  const args = [...arguments];
  const context = args.shift();

  return function () {
    return self.apply(context, args.concat([...arguments]));
  };
};

A função de ligação pode receber qualquer número de argumentos e retornar uma nova função .

A nova função chamará a função original usando o Function.prototype.applymétodo JS .
O applymétodo usará o primeiro argumento passado para a função de destino como seu contexto ( this), e o segundo argumento de matriz do applymétodo será uma combinação do restante dos argumentos da função de destino, concatenando com os argumentos usados ​​para chamar o retorno função (nessa ordem).

Um exemplo pode ser algo assim:

function Fruit(emoji) {
  this.emoji = emoji;
}

Fruit.prototype.show = function () {
  console.log(this.emoji);
};

const apple = new Fruit('🍎');
const orange = new Fruit('🍊');

apple.show();  // 🍎
orange.show(); // 🍊

const fruit1 = apple.show;
const fruit2 = apple.show.bind();
const fruit3 = apple.show.bind(apple);
const fruit4 = apple.show.bind(orange);

fruit1(); // undefined
fruit2(); // undefined
fruit3(); // 🍎
fruit4(); // 🍊

Lior Elrom
fonte
0

Explicação simples:

bind () cria uma nova função, uma nova referência na função que ela retorna para você.

No parâmetro após esta palavra-chave, você passa o parâmetro que deseja pré-configurar. Na verdade, ele não é executado imediatamente, apenas se prepara para execução.

Você pode pré-configurar quantos parâmetros desejar.

Exemplo simples para entender o bind:

function calculate(operation) {
  if (operation === 'ADD') {
   alert('The Operation is Addition');
  } else if (operation === 'SUBTRACT') {
   alert('The Operation is Subtraction');
  }
}

addBtn.addEventListener('click', calculate.bind(this, 'ADD'));
subtractBtn.addEventListener('click', calculate.bind(this, 'SUBTRACT'));
Shivu
fonte
-1

bind é uma função que está disponível no protótipo de script java, pois o nome sugere bind é usado para vincular sua chamada de função ao contexto com o qual você está lidando, por exemplo:

    var rateOfInterest='4%';
    var axisBank=
    {
    rateOfInterest:'10%',
    getRateOfInterest:function()
    {
    return this.rateOfInterest;
    }
    }
    axisBank.getRateOfInterest() //'10%' 


    let knowAxisBankInterest=axisBank.getRateOfInterest // when you want to assign the function call to a varaible we use this syntax
    knowAxisBankInterest(); // you will get output as '4%' here by default the function is called wrt global context

let knowExactAxisBankInterest=knowAxisBankInterest.bind(axisBank);     //so here we need bind function call  to its local context


    knowExactAxisBankInterest() // '10%' 

Thara
fonte