Какая польза от JavaScript-метода bind?


651

Какая польза от bind()JavaScript?


8
Мой стандартный вариант использования:select = document.querySelector.bind(document)
ceving

1
^ И для всех, кто интересуется, причина, по которой это необходимо, заключается в том, что thisв противном случае он ссылается windowна глобальный объект. С document.querySelector.bind(document), мы гарантируем , что select«s thisотносится к document, а не window. Кто-то поправит меня, если я неправильно это понял.
АлександрH

Ответы:


615

Bind создает новую функцию, которая заставит thisвнутреннюю функцию быть параметром, переданным вbind() .

Вот пример, который показывает, как использовать bindдля передачи метода члена, который имеет правильный 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

Который распечатывает:

OK clicked
undefined clicked
OK clicked

Вы также можете добавить дополнительные параметры после параметра 1st ( this) и bindпередать эти значения исходной функции. Любые дополнительные параметры, которые вы позже передадите связанной функции, будут переданы после связанных параметров:

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

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

Который распечатывает:

15

Проверьте JavaScript Function bind для получения дополнительной информации и интерактивных примеров.

Обновление: ECMAScript 2015 добавляет поддержку =>функций. =>функции более компактны и не изменяют thisуказатель из области их определения, поэтому вам не нужно использовать их bind()так часто. Например, если вы хотели, чтобы функция Buttonиз первого примера подключала clickобратный вызов к событию DOM, все следующие допустимые способы сделать это:

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

Или:

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

Или:

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

6
Отличное объяснение, но я изо всех сил пытаюсь найти примеры, где я хотел бы использовать третий вариант, который вы описали, вместо первого. Можете ли вы описать ситуации, когда вы чувствовали необходимость использовать третий вариант?
Дэррил

5
Я не думаю, что когда-либо использовал связывание, кроме как для связывания «это». Другая форма известна как частичное приложение и довольно распространена в функциональных языках. Я предполагаю, что это включено для полноты.
Нкрон

43
В случае, если кто-то интересуется, почемуooseClick () не привязан к myButton, это потому, что «this» относится к объекту, который вызывает функцию (ooseClick ()). Объект, который вызываетooseClick (), является глобальным объектом.
Покер

4
@Darryl - одна из причин, по которой следует передавать параметры из обработчиков событий. Если у вас есть этот код реакции:, var Note = React.createClass({ add: function(text){ ... }, render: function () { return <button onClick={this.add.bind(null, "New Note")}/> } }то при нажатии кнопки он передаст текст параметра «Новая заметка» addметоду.
П. Майер Нор

2
«Вы можете также добавить дополнительные параметры после 1-го параметра, и bind передаст эти значения исходной функции перед передачей дополнительных параметров, которые вы передаете связанной функции:« Эта формулировка сбивает с толку.
Кен Ингрэм

271

Самое простое использование bind()- сделать функцию, которая, независимо от того, как она вызывается, вызывается с определенным thisзначением.

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

Пожалуйста, обратитесь по этой ссылке для получения дополнительной информации

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


38
Лучшее введение в bind (), которое я когда-либо видел.
Томасфль

3
Отличный ответ, поскольку ваш пример не требует знания языковых функций (например prototype), которые могут быть новыми для начинающих.
Эдвард

1
сжато и очень ясно!
папий

172

привязка позволяет-

  • установить значение «this» для конкретного объекта. Это становится очень полезным, так как иногда это не то, что предназначено.
  • повторно использовать методы
  • карри функции

Например, у вас есть функция для вычета ежемесячных клубных сборов

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

Теперь вы хотите повторно использовать эту функцию для другого члена клуба. Обратите внимание, что ежемесячная плата будет варьироваться от участника к участнику.

Давайте представим, что у Рейчел баланс 500, а ежемесячный членский взнос 90.

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

Теперь создайте функцию, которую можно использовать снова и снова, чтобы вычитать комиссию с ее счета каждый месяц.

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

Теперь ту же функцию getMonthlyFee можно использовать для другого члена с другим членским взносом. Например, Росс Геллер имеет баланс 250 и ежемесячную плату 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
В вашем примере, я думаю, я был бы склонен настроить объект члена, созданный с помощью нового ключевого слова, где у каждого члена были свои свойства / методы. Тогда это просто вопрос ross.getMonthlyFee (25). Был ли этот пример просто для демонстрации использования bind (), или есть какое-то преимущество для вашего подхода?
Дэррил

люблю карри!
Джерри Лю

я не знаю, но я бы сделал var getRachelFee = getMonthlyFee (rachel, 90); И функция будет функцией getMonthlyFee (member, fee) {} что-то в этом роде.
Мигель

1
@KhanSharp Ваш ответ правильный, но именно ваши ссылки на сериал «Друзья» заставляют меня комментировать и поднимать голос. Спасибо за ответ 🤗.
Саурабх Ленде

79

Из Документов MDN на Function.prototype.bind():

Метод bind () создает новую функцию, которой при вызове присваивается ключевое слово this с указанным значением, причем заданная последовательность аргументов предшествует любому из предоставленных при вызове новой функции.

Так что это значит?!

Хорошо, давайте возьмем функцию, которая выглядит следующим образом:

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

Теперь давайте возьмем объект, который выглядит следующим образом:

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

Мы можем привязать нашу функцию к нашему объекту так:

Obj.log = logProp.bind(Obj);

Теперь мы можем запустить Obj.logгде-нибудь в нашем коде:

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

Это работает, потому что мы привязали значение thisк нашему объекту Obj.


Интересно, когда вы связываете не только значение this, но и его аргумент prop:

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

Теперь мы можем сделать это:

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

В отличие от с Obj.log, нам не нужно передавать xили y, потому что мы передали эти значения, когда мы сделали нашу привязку.


9
Этот ответ должен получить больше любви. Хорошо объяснил.
Chax

Очень хорошая комбинация общего обзора и конкретного примера.
Кен Инграм

Где кнопка, которая стреляет прямо 100 взлетов?
kushalvm

При этом я бы также рекомендовал прочитать раздел Документы MDN Частично примененных функций, чтобы понять использование bind «null». Это должно закрыть ворота для большей части использования привязки. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
kushalvm

23

Переменные имеют локальные и глобальные области применения. Давайте предположим, что у нас есть две переменные с одинаковым именем. Один определяется глобально, а другой определяется внутри замыкания функции, и мы хотим получить значение переменной, которое находится внутри замыкания функции. В этом случае мы используем этот метод bind (). Пожалуйста, смотрите простой пример ниже:

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

Резюме:

bind()Метод принимает объект в качестве первого аргумента и создает новую функцию. Когда функция вызывается, значением thisв теле функции будет объект, который был передан в качестве аргумента вbind() функции.

Как this работает в JS

Значение thisв javascript всегда зависит от того, какой объект вызывается функцией. Значение this всегда относится к объекту слева от точки, откуда вызывается функция . В случае глобальной области это window(или globalв nodeJS). Только call, applyи bindможет изменить это связывание по- разному. Вот пример, чтобы показать, как работает это ключевое слово:

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

Как используется связывание?

Привязка может помочь в преодолении трудностей с thisключевым словом, имея фиксированный объект, на который thisбудет ссылаться. Например:

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'

Как только функция привязана к определенному thisзначению, мы можем передать его и даже поместить в свойства других объектов. Значение thisостанется прежним.


3
Ваши комментарии в вашем коде об objобъекте - это объект, потому что он слева от точки, и windowобъект, потому что это сокращение от него window.custFunc()и windowслева от точки, было очень проницательным для меня.
nzaleski

12

Я объясню привязку теоретически, а также практически

bind в javascript это метод - Function.prototype.bind. привязка это метод. Вызывается по прототипу функции. Этот метод создает функцию, тело которой похоже на функцию, для которой он вызывается, но «this» относится к первому параметру, переданному методу связывания. Его синтаксис

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

Пример:--

  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;

Это в основном превращает все, что «это» внутри функции, в любой объект, который вы передаете, правильно?
Харви Лин

11

Метод bind () создает новый экземпляр функции, это значение которого связано со значением, переданным в bind (). Например:

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

Здесь новая функция с именем objectSayColor () создается из sayColor () путем вызова bind () и передачи объекта o. Функция objectSayColor () имеет это значение, эквивалентное o, поэтому вызов функции, даже в качестве глобального вызова, приводит к отображению строки «синий».

Справка: Николас С. Закас - ПРОФЕССИОНАЛЬНЫЙ JAVASCRIPT® ДЛЯ ВЕБ-РАЗРАБОТЧИКОВ


краткий и лаконичный пример
Ахмад Шариф

9

Создание новой функции путем привязки аргументов к значениям

bindМетод создает новую функцию из другой функции с одним или несколькими аргументами , связанными с конкретными значениями, в том числе неявного thisаргумента.

Частичное применение

Это пример частичного применения . Обычно мы предоставляем функцию со всеми ее аргументами, которая дает значение. Это известно как функция приложения. Мы применяем функцию к ее аргументам.

Функция высшего порядка (HOF)

Частичное применение является примером функции более высокого порядка (HOF), потому что она дает новую функцию с меньшим количеством аргументов.

Связывание нескольких аргументов

Вы можете использовать bindдля преобразования функций с несколькими аргументами в новые функции.

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

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

Преобразование из метода экземпляра в статическую функцию

В наиболее распространенном случае использования при вызове с одним аргументом bindметод создает новую функцию, thisзначение которой связано с конкретным значением. По сути это превращает метод экземпляра в статический метод.

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

Реализация StateBall CallBack

В следующем примере показано, как использование привязки thisможет позволить объектному методу действовать как обратный вызов, который может легко обновлять состояние объекта.

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

Как уже упоминалось, Function.bind()позволяет вам указать контекст, в котором будет выполняться функция (то есть, он позволяет вам указать, к какому объекту thisразрешается ключевое слово в теле функции.

Пара аналогичных методов API инструментария, которые выполняют аналогичную службу:

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

Рассмотрим простую программу, перечисленную ниже,

//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 создает новую функцию с тем же телом функции, что и вызываемая функция. Она вызывается с аргументом this. Почему мы используем привязку fun. : когда каждый раз создается новый экземпляр, и мы должны использовать первый начальный экземпляр, тогда мы используем привязку fun. Мы не можем переопределить привязку fun. просто она хранит начальный объект класса.

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

0

Другое использование состоит в том, что вы можете передать связанную функцию в качестве аргумента другой функции, которая работает в другом контексте выполнения.

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

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

0

Простой пример

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

Метод связывания

Реализация привязки может выглядеть примерно так:

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

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

Функция bind может принимать любое количество аргументов и возвращать новую функцию .

Новая функция вызовет исходную функцию, используя Function.prototype.applyметод JS . Метод будет использовать первый аргумент , передаваемый целевую функцию в качестве контекста ( ), а второй аргумент массива из метода будет представлять собой сочетание остальных аргументов из целевой функции, CONCAT с аргументами используется для вызова возврата функция (в таком порядке). Пример может выглядеть примерно так:
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

Простое объяснение:

bind () создает новую функцию, новую ссылку на функцию, которую она возвращает вам.

В параметре после этого ключевого слова вы передаете параметр, который хотите предварительно настроить. На самом деле он не выполняется сразу, просто готовится к исполнению.

Вы можете предварительно настроить столько параметров, сколько хотите.

Простой пример для понимания 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'));

-1

bind - это функция, которая доступна в прототипе java-скрипта, так как имя предполагает, что bind используется для привязки вызова вашей функции к контексту, с чем бы вы ни имели дело, например:

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.