Jakie jest zastosowanie metody JavaScript „bind”?

650

Jakie jest zastosowanie bind()w JavaScript?

Sandeep Kumar
źródło
8
Mój standardowy przypadek użycia:select = document.querySelector.bind(document)
Ceving
1
^ I ktoś zastanawiasz się, dlatego, że jest to potrzebne, ponieważ thisw przeciwnym razie patrz window, globalnego obiektu. Dzięki document.querySelector.bind(document)zapewniamy, że selectto thisodnosi się do document, a nie do window. Ktoś mnie poprawi, jeśli źle to zrozumiem.
AleksandrH

Odpowiedzi:

612

Powiązanie tworzy nową funkcję, która zmusi thiswnętrze funkcji do przekazania parametru bind().

Oto przykład, który pokazuje, jak użyć binddo przekazania metody członka, która ma poprawną wartość 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

Który drukuje:

OK clicked
undefined clicked
OK clicked

Możesz również dodać dodatkowe parametry po parametrze 1st ( this) i bindprzekaże te wartości do pierwotnej funkcji. Wszelkie dodatkowe parametry przekazane później do funkcji powiązanej zostaną przekazane po parametrach powiązanych:

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

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

Który drukuje:

15

Sprawdź powiązanie funkcji JavaScript, aby uzyskać więcej informacji i interaktywne przykłady.

Aktualizacja: ECMAScript 2015 dodaje obsługę =>funkcji. =>funkcje są bardziej zwarte i nie zmieniają thiswskaźnika z zakresu ich definiowania, więc nie trzeba go używać bind()tak często. Na przykład, jeśli chcesz, aby funkcja Buttonod pierwszego przykładu łączyła clickwywołanie zwrotne ze zdarzeniem DOM, poniższe są wszystkie prawidłowe sposoby:

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

Lub:

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

Lub:

var myButton = {
  ... // As above
  hookEvent(element) {
    // => functions do not change 'this', so you can use it directly
    element.addEventListener('click', () => this.click());
  }
};
nkron
źródło
6
Doskonałe wyjaśnienie, ale staram się znaleźć przykłady, w których chciałbym użyć trzeciej opcji, którą opisałeś, zamiast pierwszej. Czy możesz opisać sytuacje, w których czułeś potrzebę skorzystania z trzeciej opcji?
Darryl
5
Nie sądzę, żebym kiedykolwiek używał wiązania innego niż do wiązania „tego”. Druga forma nosi nazwę częściowej aplikacji i jest dość powszechna w językach funkcjonalnych. Wyobrażam sobie, że jest to uwzględnione dla kompletności.
nkron
42
Jeśli ktoś zastanawia się, dlaczego looseClick () nie jest związany z myButton, dzieje się tak dlatego, że „to” odnosi się do obiektu wywołującego funkcję (looseClick ()). Obiekt wywołujący looseClick () jest obiektem globalnym.
pokero
4
@Darryl - Jednym z powodów, dla których warto przekazywać parametry z procedur obsługi zdarzeń. Jeśli masz ten kod reagowania: var Note = React.createClass({ add: function(text){ ... }, render: function () { return <button onClick={this.add.bind(null, "New Note")}/> } }to po kliknięciu przycisku przekazuje on do parametru tekst parametru „Nowa notatka” add.
P. Myer Nore,
2
„Możesz również dodać dodatkowe parametry po pierwszym parametrze, a bind przekaże te wartości do oryginalnej funkcji przed przekazaniem dodatkowych parametrów, które przekażesz do funkcji powiązanej:” To sformułowanie jest mylące.
Ken Ingram
271

Najprostszym zastosowaniem bind()jest utworzenie funkcji, która niezależnie od tego, jak zostanie wywołana, wywoływana jest z określoną thiswartością.

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

Więcej informacji można znaleźć pod tym linkiem

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

Renganathan MG
źródło
38
Najlepsze wprowadzenie do bind (), jakie kiedykolwiek widziałem.
thomasfl
3
Świetna odpowiedź, ponieważ twój przykład nie wymaga znajomości funkcji językowych (np. prototype), Które mogą być nowe dla początkujących.
Edward,
1
zwięzłe i bardzo jasne!
papigee
172

wiązanie pozwala

  • ustaw wartość „this” na konkretny obiekt. Staje się to bardzo pomocne, a czasem to nie jest to, co jest przeznaczone.
  • metody ponownego wykorzystania
  • curry funkcję

Na przykład masz funkcję odejmowania miesięcznych opłat klubowych

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

Teraz chcesz ponownie użyć tej funkcji dla innego członka klubu. Pamiętaj, że opłata miesięczna będzie się różnić w zależności od członka.

Wyobraźmy sobie, że Rachel ma saldo 500, a miesięczna opłata członkowska wynosi 90.

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

Teraz utwórz funkcję, której można używać wielokrotnie, aby co miesiąc pobierać opłatę z jej konta

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

Teraz ta sama funkcja getMonthlyFee może być używana dla innego członka z inną opłatą członkowską. Na przykład Ross Geller ma saldo 250 i miesięczną opłatę w wysokości 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
źródło
9
W twoim przykładzie myślę, że byłbym skłonny ustawić obiekt członkowski utworzony w instancji za pomocą nowego słowa kluczowego, w którym każdy członek miał własne właściwości / metody. To po prostu kwestia ross.getMonthlyFee (25). Czy ten przykład miał po prostu zademonstrować użycie bind (), czy też ma jakieś zalety w twoim podejściu?
Darryl
Uwielbiam curry funkcjonalne!
Jerry Liu,
nie wiem, ale zrobiłbym var getRachelFee = getMonthlyFee (rachel, 90); A funkcja byłaby funkcją getMonthlyFee (członek, opłata) {} coś w tym stylu.
Miguel
1
@KhanSharp Twoja odpowiedź jest prawidłowa, ale to twoje odniesienia do seriali telewizyjnych Friends skłaniają mnie do komentowania i wyrażania opinii. Dziękuję za odpowiedź 🤗.
Saurabh Lende
79

Z dokumentów MDN na Function.prototype.bind():

Metoda bind () tworzy nową funkcję, której wywołanie powoduje ustawienie tego słowa kluczowego na podaną wartość, z podaną sekwencją argumentów poprzedzającą podaną podczas wywołania nowej funkcji.

Więc, co to znaczy?!

Cóż, weźmy funkcję, która wygląda następująco:

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

A teraz weźmy obiekt, który wygląda następująco:

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

Możemy powiązać naszą funkcję z naszym obiektem w następujący sposób:

Obj.log = logProp.bind(Obj);

Teraz możemy uruchomić w Obj.logdowolnym miejscu naszego kodu:

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

To działa, ponieważ związaliśmy wartość thisnaszego obiektu Obj.


Ciekawie staje się nie tylko przypisanie wartości this, ale również argumentu prop:

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

Możemy teraz to zrobić:

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

W przeciwieństwie do Obj.logtego nie musimy przekazywać xani y, ponieważ przekazaliśmy te wartości, kiedy wykonaliśmy swoje zobowiązanie.

John Slegers
źródło
9
Ta odpowiedź powinna zyskać więcej miłości. Dobrze wyjaśnione.
Chax
Bardzo dobre połączenie ogólnego przeglądu i konkretnego przykładu.
Ken Ingram,
Gdzie jest przycisk, który strzela prosto w górę 100?
kushalvm
Z tym poleciłbym również przeczytanie sekcji dokumentacji MDN w Częściowo zastosowanych funkcjach, aby zrozumieć użycie wiązania „null”. Powinien on zamknąć bramy dla większości przypadków użycia bind. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
kushalvm
23

Zmienne mają zasięg lokalny i globalny. Załóżmy, że mamy dwie zmienne o tej samej nazwie. Jeden jest zdefiniowany globalnie, a drugi jest zdefiniowany wewnątrz zamknięcia funkcji, a my chcemy uzyskać wartość zmiennej, która jest wewnątrz zamknięcia funkcji. W takim przypadku używamy tej metody bind (). Zobacz prosty przykład poniżej:

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
źródło
18

Podsumowanie:

bind()Metoda przyjmuje obiekt jako pierwszy argument i tworzy nową funkcję. Po wywołaniu funkcji wartością thisw treści funkcji będzie obiekt przekazany jako argument bind()funkcji.

Jak w ogóle thisdziała w JS

Wartość thisw javascript jest zależna zawsze zależy od tego, jaki obiekt jest wywoływany. Wartość tego zawsze odnosi się do obiektu po lewej stronie kropki, z którego wywoływana jest funkcja . W przypadku zasięgu globalnym jest to window(lub globalw nodeJS). Tylko call, applya bindmoże zmienić to wiązanie inaczej. Oto przykład pokazujący, jak działa to słowo kluczowe:

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

Jak stosować bind?

Powiązanie może pomóc w przezwyciężeniu trudności ze thissłowem kluczowym, ponieważ ma ustalony obiekt, do którego thisbędzie się odnosił. Na przykład:

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'

Gdy funkcja zostanie przypisana do określonej thiswartości, możemy ją przekazać, a nawet nadać właściwości innym obiektom. Wartość thispozostanie taka sama.

Willem van der Veen
źródło
3
Twoje komentarze w twoim kodzie na temat tego objobiektu są tym, że pozostały po kropce i windowsą tym obiektem, ponieważ są skrótem window.custFunc()i windowpozostały po kropce, były dla mnie bardzo wnikliwe.
nzaleski
12

Wyjaśnię wiążę zarówno teoretycznie, jak i praktycznie

bind w javascript to metoda - Function.prototype.bind. bind jest metodą. Nazywa się to prototypem funkcji. Ta metoda tworzy funkcję, której ciało jest podobne do funkcji, na której jest wywoływana, ale „to” odnosi się do pierwszego parametru przekazanego do metody wiązania. Jego składnia to

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

Przykład:--

  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
źródło
Zasadniczo przekształca to „to” wewnątrz funkcji w dowolny obiekt, który przekazujesz, prawda?
Harvey Lin
11

Metoda bind () tworzy nową instancję funkcji, której wartość jest powiązana z wartością przekazaną do bind (). Na przykład:

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

Tutaj tworzona jest nowa funkcja o nazwie objectSayColor () z sayColor () poprzez wywołanie bind () i przekazanie obiektu o. Funkcja objectSayColor () ma tę wartość równoważną o, więc wywołanie funkcji, nawet jako wywołanie globalne, powoduje wyświetlenie ciągu „niebieski”.

Referencje: Nicholas C. Zakas - PROFESJONALNY JAVASCRIPT® DLA DEWELOPERÓW INTERNETOWYCH

Otti
źródło
zwięzły i lakoniczny przykład
Ahmad Sharif
9

Tworzenie nowej funkcji poprzez wiązanie argumentów z wartościami

bindMetoda tworzy nową funkcję z innej funkcji z jednym lub więcej argumentów związanych z określonymi wartościami, w tym niejawny thisargument.

Częściowe zastosowanie

To jest przykład częściowego zastosowania . Zwykle podajemy funkcję ze wszystkimi jej argumentami, co daje wartość. Jest to znane jako aplikacja funkcji. Stosujemy funkcję do jej argumentów.

Funkcja wyższego rzędu (HOF)

Częściowa aplikacja jest przykładem funkcji wyższego rzędu (HOF), ponieważ daje nową funkcję z mniejszą liczbą argumentów.

Wiązanie wielu argumentów

Możesz użyć binddo przekształcenia funkcji z wieloma argumentami w nowe funkcje.

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

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

Konwersja metody instancji na funkcję statyczną

W najczęstszym przypadku użycia, wywołana z jednym argumentem, bindmetoda utworzy nową funkcję, której thiswartość jest powiązana z określoną wartością. W efekcie przekształca to metodę instancji w metodę statyczną.

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

Wdrożenie stanowego wywołania zwrotnego

Poniższy przykład pokazuje, w jaki sposób użycie powiązania thismoże umożliwić obiektowej metodzie działanie jako wywołanie zwrotne, które może z łatwością zaktualizować stan obiektu.

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
źródło
6

Jak wspomniano, Function.bind()pozwala określić kontekst, w którym funkcja będzie wykonywana (tzn. Pozwala przekazać obiekt, do którego thissłowo kluczowe rozpozna w treści funkcji.

Kilka analogicznych metod interfejsu API zestawu narzędzi, które wykonują podobną usługę:

jQuery.proxy ()

Dojo.hitch ()

mtyson
źródło
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
źródło
3

Rozważ prosty program wymieniony poniżej,

//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
źródło
2

Funkcja bind tworzy nową funkcję z tym samym ciałem co funkcja, którą wywołuje. Jest wywoływana z tym argumentem. Dlaczego używamy bind fun. : gdy za każdym razem, gdy tworzona jest nowa instancja i musimy użyć pierwszej instancji początkowej, używamy bind fun. Nie możemy przesłonić bind fun. po prostu przechowuje początkowy obiekt klasy.

setInterval(this.animate_to.bind(this), 1000/this.difference);
użytkownik2485861
źródło
0

Innym zastosowaniem jest to, że możesz przekazać powiązaną funkcję jako argument do innej funkcji, która działa w innym kontekście wykonania.

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.
źródło
0

Prosty przykład

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
Karl Morrison
źródło
0

Metoda wiązania

Implementacja wiązania może wyglądać mniej więcej tak:

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

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

Funkcja powiązania może przyjąć dowolną liczbę argumentów i zwrócić nową funkcję .

Nowa funkcja wywoła funkcję oryginalną przy użyciu Function.prototype.applymetody JS . Sposób stosuje pierwszy argument przekazany do funkcji docelowego jako kontekst ( ), a drugi argument tablicę metody będzie połączenie z resztą argumentów funkcji docelowego concat z argumentów do wywołania powrotu funkcja (w tej kolejności). Przykład może wyglądać mniej więcej tak:
applythisapply

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
źródło
0

Proste objaśnienie:

bind () utwórz nową funkcję, nowe odwołanie do funkcji, która do Ciebie zwraca.

W parametrze po tym słowie kluczowym podajesz parametr, który chcesz wstępnie skonfigurować. W rzeczywistości nie wykonuje się natychmiast, po prostu przygotowuje się do wykonania.

Możesz wstępnie skonfigurować dowolną liczbę parametrów.

Prosty przykład zrozumienia wiązania:

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
źródło
-1

bind jest funkcją dostępną w prototypie skryptu Java, ponieważ nazwa sugeruje, że bind jest używany do powiązania twojego wywołania funkcji z kontekstem, niezależnie od tego, z czym masz do czynienia, np .:

    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
źródło