JavaScript 'bağlama' yönteminin kullanımı nedir?


651

bind()JavaScript'te kullanımı nedir ?


8
Standart kullanım select = document.querySelector.bind(document)
durumum

1
^ Ve merak eden herkes için ihtiyaç duyulan neden, thisaksi takdirde windowküresel nesneye atıfta bulunulmasıdır . İle document.querySelector.bind(document), select'ın thisifade etmesini documentve olmamasını sağlıyoruz window. Yine de yanlış anlarsam biri beni düzeltir.
AleksandrH

Yanıtlar:


613

Bind, işlevin thisiçinin geçirilen parametre olmasını zorlayacak yeni bir işlev oluştururbind() .

Aşağıda bind, doğru olan bir üye yöntemini iletmek için nasıl kullanılacağını gösteren bir örnek verilmiştir 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

Hangi çıktılar:

OK clicked
undefined clicked
OK clicked

Ayrıca 1st ( this) parametresinden sonra fazladan parametreler ekleyebilirsiniz ve bindbu değerleri orijinal işleve geçirir. Daha sonra ilişkili işleve ilettiğiniz ek parametreler, bağlı parametrelerden sonra iletilir:

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

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

Hangi çıktılar:

15

Daha fazla bilgi ve etkileşimli örnekler için JavaScript İşlev bağına göz atın .

Güncelleme: ECMAScript 2015 =>işlevler için destek ekler . =>işlevleri daha kompakttır ve thisişaretçiyi tanımlayıcı kapsamından değiştirmez, bu nedenle bind()sık kullanmanıza gerek olmayabilir . Örneğin Button, ilk örnekteki bir işlevin clickgeri çağrıyı bir DOM etkinliğine bağlamasını istiyorsanız, aşağıdakilerin tümü geçerli yöntemlerdir:

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

Veya:

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

Veya:

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

6
Mükemmel bir açıklama, ancak ilk seçenek yerine açıkladığınız üçüncü seçeneği kullanmak isteyeceğim örnekleri bulmakta zorlanıyorum. Üçüncü seçeneği kullanmanız gerektiğini düşündüğünüz durumları açıklayabilir misiniz?
Darryl

5
'Bunu' bağlamaktan başka bağlama kullandığımı sanmıyorum. Diğer form Kısmi Uygulama olarak bilinir ve işlevsel dillerde oldukça yaygındır. Tamlık için dahil olduğunu hayal ediyorum.
nkron

42
Bir kimse neden looseClick () öğesinin myButton'a bağlı olmadığını merak ederse, bunun nedeni "this" işlevini çağıran nesneyi ifade eder (looseClick ()). LooseClick () öğesini çağıran nesne genel nesnedir.
pokero

4
@Darryl - Olay işleyicilerinden parametre iletmenin bir nedeni olabilir. Bu tepki koduna sahipseniz:, var Note = React.createClass({ add: function(text){ ... }, render: function () { return <button onClick={this.add.bind(null, "New Note")}/> } }düğmeye tıklandığında, addyönteme "Yeni Not" parametre metnini iletir.
P. Myer Nore

2
Msgstr "1. parametreden sonra ilave parametreler de ekleyebilirsiniz ve bağlama, bağlı işleve ilettiğiniz ekstra parametreleri iletmeden önce bu değerlerin orijinal işlevine geçmesini sağlar:" Bu ifade kafa karıştırıcıdır.
Ken Ingram

271

En basit kullanımı, bind()nasıl adlandırılırsa adlandırılsın, belirli bir thisdeğerle çağrılan bir işlev yapmaktır .

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

Daha fazla bilgi için lütfen bu bağlantıya bakın

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


38
Bind () gördüğüm en iyi giriş.
thomasfl

3
Harika yanıt, çünkü örneğiniz prototypeyeni başlayanlar için yeni olabilecek dil özellikleri (ör. ) Hakkında bilgi gerektirmez .
Edward

1
kısa ve özlü!
papigee

172

bağlama sağlar

  • "this" değerini belirli bir nesneye ayarlayın. Bu çok yardımcı olur çünkü bazen amaçlanan bu değildir.
  • yeniden kullanım yöntemleri
  • bir işlevi köri

Örneğin, aylık kulüp ücretlerini düşürebilirsiniz.

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

Şimdi bu işlevi farklı bir kulüp üyesi için yeniden kullanmak istiyorsunuz. Aylık ücretin üyeden üyeye değişeceğini unutmayın.

Rachel'ın 500 bakiyesi ve aylık üyelik ücreti 90 olduğunu düşünelim.

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

Şimdi, ücretini her ay hesabından düşmek için tekrar tekrar kullanılabilecek bir işlev oluşturun

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

Artık aynı getMonthlyFee işlevi, farklı bir üyelik ücreti olan başka bir üye için kullanılabilir. Örneğin, Ross Geller'in 250 bakiyesi ve aylık ücreti 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
Örneğinizde, her üyenin kendi özelliklerine / yöntemlerine sahip olduğu yeni anahtar kelimeyle örneklenmiş bir üye nesnesi oluşturmaya meyilli olduğumu düşünüyorum. O zaman bu sadece bir ross.getMonthlyFee (25) meselesidir. Bu örnek sadece bind () kullanımını göstermek için miydi yoksa yaklaşımınızın bir avantajı var mı?
Darryl

köri bir işlev bir seviyorum!
Jerry Liu

bilmiyorum, ama ben var yapmak istiyorum getRachelFee = getMonthlyFee (rachel, 90); Ve fonksiyon hat boyunca getMonthlyFee (üye, ücret) {} fonksiyonudur.
Miguel

1
@KhanSharp Cevabınız doğru, ancak TV dizisi Friends'e yaptığınız referanslar beni yorum ve upvote ediyor. Cevabınız için teşekkürler 🤗.
Saurabh Lende

79

Gönderen MDN docs üzerinde Function.prototype.bind():

Bağlaması () metodu çağrıldığında, yeni bir işlev çağrıldığında bir mesafede önceki argümanlar, belirli bir sekans ile, verilen bir değer olan bu kelime grubu olan yeni bir fonksiyonu oluşturur.

Peki bunun anlamı nedir?!

Peki, şuna benzer bir işlev alalım:

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

Şimdi şuna benzer bir nesne alalım:

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

İşlevimizi nesnemize şu şekilde bağlayabiliriz:

Obj.log = logProp.bind(Obj);

Şimdi, Obj.logkodumuzun herhangi bir yerinde çalışabiliriz :

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

Bu işe yarar, çünkü değerini thisnesnemize bağladık Obj.


Gerçekten ilginç hale geldiği yer, sadece bir değeri değil this, aynı zamanda argümanını da bağladığınız zamandır prop:

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

Şimdi bunu yapabiliriz:

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

Bunun aksine Obj.log, geçmemiz gerekmiyor xya da y, çünkü bağımızı yaparken bu değerleri geçtik.


9
Bu cevap daha çok sevilmeli. İyi açıkladı.
Chax

Genel bakış ve spesifik örneğin çok iyi kombinasyonu.
Ken Ingram

Düz yukarı 100 atış yapan düğme nerede?
kushalvm

Bununla da bağ "null" kullanımını anlamak için Kısmen uygulanan işlevlerin MDN dokümanlar bölümünü okumanızı tavsiye ederim . Bağlama kullanımının çoğu için kapıları kapatmalıdır. developer.mozilla.org/tr/docs/Web/JavaScript/Reference/…
kushalvm

23

Değişkenlerin yerel ve küresel kapsamları vardır. Aynı ada sahip iki değişkenimiz olduğunu varsayalım. Biri genel olarak tanımlanır ve diğeri bir işlev kapanışının içinde tanımlanır ve işlev kapanışının içindeki değişken değerini almak istiyoruz. Bu durumda bu bind () yöntemini kullanırız. Lütfen aşağıdaki basit örneğe bakın:

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

Özet:

bind()Yöntem, birinci bağımsız değişken olarak bir nesneyi alır ve yeni bir fonksiyonu oluşturur. İşlev çağrıldığında thisişlev gövdesindeki değeri, öğede bağımsız değişken olarak iletilen nesne olur.bind() .

Nasıl thisYine de JS'de çalışır

thisJavascript içindeki değeri her zaman işlevin hangi Object olarak adlandırıldığına bağlıdır. Bunun değeri daima işlevin çağrıldığı noktadan noktanın solundaki nesneyi ifade eder . Küresel kapsamda bu window(ya da globaliçindedir nodeJS). Sadece call, applyve bindfarklı bağlanması bu değiştirebilir. Bu anahtar kelimenin nasıl çalıştığını gösteren bir örnek:

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

Bağlama nasıl kullanılır?

Bind, başvuracağı thissabit bir nesneye sahip olarak anahtar kelimeyle ilgili zorlukların üstesinden gelmede yardımcı olabilir this. Örneğin:

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'

İşlev belirli bir thisdeğere bağlandıktan sonra onu geçirebilir ve hatta diğer nesneler üzerindeki özelliklere koyabiliriz. Değeri thisaynı kalacaktır.


3
Kodunuzdaki yorumlarınız obj, nesnenin noktadan ayrılması ve windownesnenin kısaltması window.custFunc()ve windownoktanın solundan ayrılması benim için çok anlayışlı olduğu için nesnedir .
nzaleski

12

Bağlamayı teorik olduğu kadar pratik olarak da açıklayacağım

Javascript'te bağlama bir yöntemdir - Function.prototype.bind. bağlama bir yöntemdir. Fonksiyon prototipinde çağrılır. Bu yöntem, gövdesi çağrıldığı işleve benzeyen bir işlev oluşturur, ancak 'this' bağlama yöntemine iletilen ilk parametreyi belirtir. Sözdizimi

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

Misal:--

  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;

Temelde, fonksiyonun içindeki 'bu' her şeyi, geçtiğiniz herhangi bir nesneye dönüştürür, değil mi?
Harvey Lin

11

Bind () yöntemi, bu değeri bind () öğesine iletilen değere bağlı olan yeni bir işlev örneği oluşturur. Örneğin:

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

Burada, bind () öğesini çağırarak ve o nesnesini ileterek sayColor () öğesinden objectSayColor () adında yeni bir işlev oluşturulur. ObjectSayColor () işlevi o değerine eşdeğer bir değere sahiptir, bu nedenle işlevi genel bir çağrı olarak çağırmak, “mavi” dizesinin görüntülenmesine neden olur.

Referans: Nicholas C. Zakas - WEB GELİŞTİRİCİLERİ İÇİN PROFESYONEL JAVASCRIPT®


kısa ve özlü örnek
Ahmad Sharif

9

Bağımsız Değişkenleri Değerlere Bağlayarak Yeni Bir İşlev Oluşturma

bindYöntem örtülü de dahil olmak üzere, belirli değerlere bağlı bir ya da daha fazla bağımsız değişken ile başka bir işlev, yeni bir işlev oluştururthis argüman.

Kısmi Başvuru

Bu kısmi uygulamanın bir örneğidir . Normalde, tüm argümanları ile birlikte bir değer sağlayan bir fonksiyon sağlıyoruz. Bu işlev uygulaması olarak bilinir. İşlevi argümanlarına uyguluyoruz.

Daha Yüksek Sipariş Fonksiyonu (HOF)

Kısmi uygulama, daha az sayıda bağımsız değişkeni olan yeni bir işlev sağladığı için daha üst düzey bir işleve (HOF) bir örnektir .

Birden Çok Bağımsız Değişken Bağlama

bindBirden çok bağımsız değişkeni olan işlevleri yeni işlevlere dönüştürmek için kullanabilirsiniz .

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

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

Örnek Yöntemi'nden Statik İşleve Dönüştürme

En yaygın kullanım durumunda, bindyöntem bir argümanla çağrıldığında yöntem thisbelirli bir değere bağlı değere sahip yeni bir işlev oluşturur . Aslında bu, bir örnek yöntemini statik bir yönteme dönüştürür.

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

Durumsal bir Geri Arama Uygulaması

Aşağıdaki örnek, bağlanmasının kullanılmasının thisbir nesne yönteminin, bir nesnenin durumunu kolayca güncelleyebilen bir geri çağırma işlevi görmesini nasıl sağlayabileceğini göstermektedir.

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

Belirtildiği gibi Function.bind(), işlevin yürütüleceği bağlamı belirtmenize izin verir (yani, thisanahtar kelimenin işlevin gövdesinde çözeceği nesneyi iletmenizi sağlar .

Benzer bir hizmet sunan birkaç benzer araç seti API yöntemi:

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

Aşağıda listelenen Basit Programı düşünün,

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

Bind işlevi, çağırdığı işlevle aynı işlev gövdesi ile yeni bir işlev oluşturur. Bu argüman ile çağrılır. Neden bind fun kullanıyoruz. : her yeni örnek oluşturulduğunda ve ilk ilk örneği kullanmamız gerektiğinde bind fun kullanıyoruz. bind fun değerini geçersiz kılamayız. basitçe sınıfın ilk nesnesini saklar.

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

0

Başka bir kullanım, bağlı işlevi başka bir yürütme bağlamında çalışan başka bir işleve bağımsız değişken olarak geçirebilmenizdir.

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

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

0

Basit örnek

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

Bağlama Yöntemi

Bir bağlama uygulaması şöyle görünebilir:

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

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

Bind işlevi herhangi bir sayıda argüman alabilir ve yeni bir işlev döndürebilir .

Yeni işlev , JS Function.prototype.applyyöntemini kullanarak orijinal işlevi çağıracaktır . Yöntem, içerik (hedef işleve geçirilen ilk argüman kullanır ) ve ikinci dizi bağımsız değişkeni hedef işlevinden bağımsız değişkenler kalan bir kombinasyonu olacaktır yöntemi, bağımsız değişken ile concat dönüş çağırmak için kullanılan işlevi (bu sırayla). Bir örnek şöyle görünebilir:
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(); // 🍊


0

Basit Açıklama:

bağlaması () yeni bir işlev oluşturur, size döndürdüğü işlevde yeni bir başvuru oluşturur.

Bu anahtar kelimeden sonraki parametrede, önceden yapılandırmak istediğiniz parametreyi iletirsiniz. Aslında hemen yürütülmüyor, sadece uygulamaya hazırlanıyor.

İstediğiniz sayıda parametreyi önceden yapılandırabilirsiniz.

Bağlamayı anlamak için basit bir örnek:

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, java script prototipinde kullanılabilen bir işlevdir, çünkü name bind, işlev çağrınızı bağlama uğraşırken bağlama bağlanırken kullanılır; örneğin:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.