Qual è l'uso del metodo JavaScript "bind"?


651

A cosa serve bind()JavaScript?


8
Il mio caso d'uso standard:select = document.querySelector.bind(document)
ceving

1
^ E per chiunque si chieda, il motivo necessario è perché thisaltrimenti farebbe riferimento windowall'oggetto globale. Con document.querySelector.bind(document), ci assicuriamo che select's thissi riferisce a document, e non window. Qualcuno mi correggerà se lo capissi male, però.
AleksandrH

Risposte:


614

Bind crea una nuova funzione che forzerà l' thisinterno della funzione a essere il parametro passato bind().

Ecco un esempio che mostra come utilizzare bindper passare un metodo membro che ha il corretto 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

Che stampa:

OK clicked
undefined clicked
OK clicked

È inoltre possibile aggiungere parametri aggiuntivi dopo il primo thisparametro ( ) e bindpassare tali valori alla funzione originale. Eventuali parametri aggiuntivi in ​​seguito passati alla funzione associata verranno passati dopo i parametri associati:

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

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

Che stampa:

15

Dai un'occhiata al bind della funzione JavaScript per maggiori informazioni ed esempi interattivi.

Aggiornamento: ECMAScript 2015 aggiunge il supporto per le =>funzioni. =>le funzioni sono più compatte e non cambiano il thispuntatore dal loro ambito di definizione, quindi potrebbe non essere necessario utilizzarle bind()con frequenza. Ad esempio, se si desidera attivare una funzione Buttondal primo esempio per collegareclick callback a un evento DOM, i seguenti sono tutti modi validi per farlo:

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

O:

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() });
  }
};    

O:

var myButton = {
  ... // As above
  hookEvent(element) {
    // => functions do not change 'this', so you can use it directly
    element.addEventListener('click', () => this.click());
  }
};

6
Eccellente espianto, ma faccio fatica a trovare esempi in cui vorrei usare la terza opzione che hai descritto invece della prima. Puoi descrivere situazioni in cui hai sentito la necessità di utilizzare la terza opzione?
Darryl,

5
Non credo di aver mai usato il bind se non per legare "questo". L'altra forma è conosciuta come Applicazione parziale ed è piuttosto comune nei linguaggi funzionali. Immagino che sia incluso per completezza.
nkron,

43
Nel caso in cui qualcuno si stia chiedendo perché looseClick () non è associato a myButton, è perché "this" si riferisce all'oggetto che invoca la funzione (looseClick ()). L'oggetto che invoca looseClick () è l'oggetto globale.
pokero,

4
@Darryl - Uno dei motivi per cui dovrebbe essere passare i parametri dai gestori di eventi. Se si dispone di questo codice di reazione:, var Note = React.createClass({ add: function(text){ ... }, render: function () { return <button onClick={this.add.bind(null, "New Note")}/> } }quando si fa clic sul pulsante, passerà al addmetodo il testo di un parametro "Nuova nota" .
P. Myer Nore l'

2
"Puoi anche aggiungere parametri extra dopo il primo parametro e il bind passerà quei valori alla funzione originale prima di passare i parametri extra che passi alla funzione associata:" Questa formulazione è confusa.
Ken Ingram,

271

L'uso più semplice di bind()è creare una funzione che, indipendentemente da come viene chiamata, viene chiamata con un thisvalore particolare .

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

Si prega di fare riferimento a questo link per ulteriori informazioni

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


38
La migliore introduzione a bind () che abbia mai visto.
thomasfl,

3
Ottima risposta, dal momento che il tuo esempio non richiede conoscenze sulle funzionalità linguistiche (ad es. prototype) Che potrebbero essere nuove per i principianti.
Edward,

1
succinta e molto chiara!
papigee,

172

il legame consente-

  • imposta il valore di "this" su un oggetto specifico. Questo diventa molto utile come a volte questo non è ciò che è destinato.
  • metodi di riutilizzo
  • curry una funzione

Ad esempio, hai una funzione per detrarre le tasse mensili del club

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

Ora vuoi riutilizzare questa funzione per un altro membro del club. Si noti che la tariffa mensile varierà da membro a membro.

Immaginiamo che Rachel abbia un saldo di 500 e una quota associativa mensile di 90.

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

Ora crea una funzione che può essere utilizzata più volte per detrarre la commissione dal suo account ogni mese

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

Ora, la stessa funzione getMonthlyFee potrebbe essere utilizzata per un altro membro con una quota di iscrizione diversa. Ad esempio, Ross Geller ha un saldo di 250 e una commissione mensile di 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

9
Nel tuo esempio, penso che sarei propenso a configurare un oggetto membro con un'istanza con la nuova parola chiave in cui ogni membro aveva le proprie proprietà / metodi. Quindi è semplicemente una questione di ross.getMonthlyFee (25). Questo esempio è stato solo per dimostrare l'uso di bind () o c'è qualche vantaggio nel tuo approccio?
Darryl,

amo il curry una funzione uno!
Jerry Liu,

non lo so, ma farei var getRachelFee = getMonthlyFee (rachel, 90); E la funzione sarebbe funzione getMonthlyFee (membro, tariffa) {} qualcosa lungo le linee.
Miguel,

1
@KhanSharp La tua risposta è corretta, ma sono i tuoi riferimenti alla serie TV Friends che mi fa commentare e votare. Grazie per la tua risposta 🤗.
Saurabh Lende,

79

A partire dal documenti MDN suFunction.prototype.bind():

Il metodo bind () crea una nuova funzione che, quando viene chiamata, ha questa parola chiave impostata sul valore fornito, con una determinata sequenza di argomenti che precede quella fornita quando viene chiamata la nuova funzione.

Che cosa vuol dire?!

Bene, prendiamo una funzione simile a questa:

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

Ora prendiamo un oggetto simile al seguente:

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

Possiamo associare la nostra funzione al nostro oggetto in questo modo:

Obj.log = logProp.bind(Obj);

Ora, possiamo eseguire Obj.logovunque nel nostro codice:

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

Questo funziona, perché abbiamo legato il valore thisal nostro oggetto Obj.


Dove diventa davvero interessante, è quando non solo si lega un valore per this, ma anche per il suo argomento prop:

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

Ora possiamo fare questo:

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

A differenza di Obj.log, non dobbiamo passare xo y, perché abbiamo passato quei valori quando abbiamo fatto il nostro legame.


9
Questa risposta dovrebbe ricevere più amore. Ben spiegato.
Chax,

Ottima combinazione di panoramica generale ed esempio specifico.
Ken Ingram,

Dov'è il pulsante che spara dritto fino a 100 up?
kushalvm,

Con questo, consiglierei anche di leggere la sezione dei documenti MDN delle funzioni parzialmente applicate per capire l'uso di bind "null". Dovrebbe chiudere i cancelli per la maggior parte dell'utilizzo del bind. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
kushalvm

23

Le variabili hanno ambiti locali e globali. Supponiamo di avere due variabili con lo stesso nome. Uno è definito a livello globale e l'altro è definito all'interno di una chiusura di funzione e vogliamo ottenere il valore variabile che si trova all'interno della chiusura di funzione. In quel caso usiamo questo metodo bind (). Si prega di consultare il semplice esempio di seguito:

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>


18

Sommario:

Il bind()metodo accetta un oggetto come primo argomento e crea una nuova funzione. Quando viene invocata la funzione, il valore di thisnel corpo della funzione sarà l'oggetto che è stato passato come argomento nella bind()funzione.

Come fa this funziona comunque in JS

Il valore di thisin javascript dipende sempre da quale oggetto viene chiamata la funzione. Il valore di questo si riferisce sempre all'oggetto a sinistra del punto da dove viene chiamata la funzione . Nel caso dell'ambito globale questo è window(o globaldentro nodeJS). Solo call, applye bindpossono alterare l'questo legame in modo diverso. Ecco un esempio per mostrare come funziona questa parola chiave:

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

Come si usa il bind?

Il bind può aiutare a superare le difficoltà con la thisparola chiave avendo un oggetto fisso a cui thisfare riferimento. Per esempio:

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'

Una volta che la funzione è legata a un thisvalore particolare , possiamo passarla in giro e persino metterla su proprietà su altri oggetti. Il valore di thisrimarrà lo stesso.


3
I tuoi commenti nel tuo codice objsull'oggetto è perché è a sinistra del punto ed windowè l'oggetto perché è una scorciatoia per window.custFunc()ed windowè a sinistra del punto è stato molto perspicace per me.
nzaleski,

12

Spiegherò il legame sia teoricamente che praticamente

bind in javascript è un metodo: Function.prototype.bind. bind è un metodo. Si chiama prototipo di funzione. Questo metodo crea una funzione il cui corpo è simile alla funzione su cui viene chiamato ma "this" si riferisce al primo parametro passato al metodo bind. La sua sintassi è

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

Esempio:--

  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;

Fondamentalmente trasforma qualunque "questo" all'interno della funzione in qualunque oggetto in cui passi, giusto?
Harvey Lin,

11

Il metodo bind () crea una nuova istanza di funzione il cui valore è associato al valore che è stato passato a bind (). Per esempio:

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

Qui, una nuova funzione chiamata objectSayColor () viene creata da sayColor () chiamando bind () e passando l'oggetto o. La funzione objectSayColor () ha questo valore equivalente a o, pertanto la chiamata della funzione, anche come chiamata globale, comporta la visualizzazione della stringa "blu".

Riferimento: Nicholas C. Zakas - PROFESSIONISTA JAVASCRIPT® PER SVILUPPATORI WEB


esempio conciso e laconico
Ahmad Sharif,

9

Creazione di una nuova funzione associando argomenti a valori

Il bindmetodo crea una nuova funzione da un'altra funzione con uno o più argomenti associati a valori specifici, incluso l' thisargomento implicito .

Applicazione parziale

Questo è un esempio di applicazione parziale . Normalmente forniamo una funzione con tutti i suoi argomenti che produce un valore. Questo è noto come funzione application. Stiamo applicando la funzione ai suoi argomenti.

Una funzione di ordine superiore (HOF)

L'applicazione parziale è un esempio di una funzione di ordine superiore (HOF) perché produce una nuova funzione con un numero minore di argomenti.

Argomenti multipli vincolanti

È possibile utilizzare bindper trasformare funzioni con più argomenti in nuove funzioni.

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

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

Conversione da metodo di istanza a funzione statica

Nel caso d'uso più comune, quando viene chiamato con un argomento, il bindmetodo creerà una nuova funzione che ha il thisvalore associato a un valore specifico. In effetti, questo trasforma un metodo di istanza in un metodo statico.

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

Implementazione di un CallBack con stato

L'esempio seguente mostra come l'uso dell'associazione di thispuò abilitare un metodo a oggetto per agire come un callback che può facilmente aggiornare lo stato di un oggetto.

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>


6

Come accennato, Function.bind()consente di specificare il contesto in cui verrà eseguita la funzione (ovvero, consente di passare in quale oggetto la thisparola chiave risolverà nel corpo della funzione.

Un paio di metodi API toolkit analoghi che eseguono un servizio simile:

jQuery.proxy ()

Dojo.hitch ()


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

3

Considera il programma semplice elencato di seguito,

//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);

2

La funzione bind crea una nuova funzione con lo stesso corpo della funzione che sta chiamando. Viene chiamata con questo argomento. Perché usiamo bind fun. : quando ogni volta che viene creata una nuova istanza e dobbiamo usare la prima istanza iniziale, utilizziamo bind fun. Non possiamo ignorare il bind fun. Semplicemente memorizza l'oggetto iniziale della classe.

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

0

Un altro utilizzo è che è possibile passare la funzione associata come argomento a un'altra funzione che opera in un altro contesto di esecuzione.

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

function somefunction(cb){
  //other code
  cb();
}
somefunction.call({}, cb);

0

Semplice esempio

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

0

Metodo di associazione

Un'implementazione di bind potrebbe essere simile a questa:

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

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

La funzione bind può accettare qualsiasi numero di argomenti e restituire una nuova funzione .

La nuova funzione chiamerà la funzione originale usando il Function.prototype.applymetodo JS .
Il applymetodo utilizzerà il primo argomento passato alla funzione target come suo contesto ( this), e il secondo argomento array del applymetodo sarà una combinazione del resto degli argomenti della funzione target, in accordo con gli argomenti usati per chiamare il ritorno funzione (in quell'ordine).

Un esempio può apparire così:

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(); // 🍊


0

Spiegazione semplice:

bind () crea una nuova funzione, un nuovo riferimento in una funzione che ti restituisce.

Nel parametro dopo questa parola chiave, si passa al parametro che si desidera preconfigurare. In realtà non si esegue immediatamente, si prepara solo per l'esecuzione.

Puoi preconfigurare tutti i parametri che desideri.

Semplice esempio per capire il legame:

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'));

-1

bind è una funzione disponibile nel prototipo di script java, poiché il nome suggerisce che bind viene utilizzato per associare la chiamata della funzione al contesto, indipendentemente dal caso in cui si tratti di:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.