Использование метода JavaScript 'bind'
Какая польза от bind()
в JavaScript?
24 ответа
Bind создает новую функцию, которая будет иметь this
установить первый параметр, переданный в bind()
,
Вот пример, который показывает, как использовать bind
передать метод члена, который имеет правильный this
:
var Button = function(content) {
this.content = content;
};
Button.prototype.click = function() {
console.log(this.content + ' clicked');
};
var myButton = new Button('OK');
myButton.click();
var looseClick = myButton.click;
looseClick(); // not bound, 'this' is not myButton - it is the global object
var boundClick = myButton.click.bind(myButton);
boundClick(); // bound, 'this' is myButton
Который распечатывает:
OK clicked
undefined clicked
OK clicked
Вы также можете добавить дополнительные параметры после 1-го (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-события, следующие действительные способы сделать это:
Button.prototype.hookEvent(element) {
// Use bind() to ensure 'this' is the 'this' inside click()
element.addEventListener('click', this.click.bind(this));
};
Или же:
Button.prototype.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() });
}
Или же:
Button.prototype.hookEvent(element) {
// => functions do not change 'this', so you can use it directly
element.addEventListener('click', () => this.click());
}
Самое простое использование 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
привязка позволяет-
- установить значение "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
Из документов 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
потому что мы передали эти значения, когда мы сделали нашу привязку.
Переменные имеют локальные и глобальные области действия. Предположим, что если у нас есть две переменные с одинаковым именем, одна определяется глобально, а другая определяется внутри замыкания функции, и мы хотим вызвать значение этой переменной, которое находится внутри замыкания функции, то мы используем это метод связывания. Пожалуйста, смотрите простой пример ниже:
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();
<!DOCTYPE html>
<html>
<body>
<p id="demo1">0</p>
<p id="demo2">0</p>
</body>
</html>
Резюме:
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
останется прежним.
Метод 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® ДЛЯ ВЕБ-РАЗРАБОТЧИКОВ
Создание новой функции путем привязки аргументов к значениям
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>
Я объясню привязку теоретически, а также практически
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;
Как уже упоминалось, Function.bind()
позволяет вам указать контекст, в котором будет выполняться функция (то есть, вы можете передать, в каком объекте this
Ключевое слово будет разрешено в теле функции.
Пара аналогичных методов API инструментария, которые выполняют аналогичную службу:
Метод привязки
Реализация привязки может выглядеть примерно так:
Function.prototype.bind = function () {
const self = this;
const args = [...arguments];
const context = args.shift();
return function () {
return self.apply(context, args.concat([...arguments]));
};
};
Функция привязки может принимать любое количество аргументов и возвращать новую функцию.
Новая функция вызовет исходную функцию с помощью JSFunction.prototype.apply
метод.
Вapply
будет использовать первый аргумент, переданный целевой функции, в качестве контекста (this
), а второй аргумент массива apply
будет комбинацией остальных аргументов целевой функции, совпадающих с аргументами, используемыми для вызова функции возврата (в этом порядке).
Пример может выглядеть примерно так:
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(); //
/**
* 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
Вот самое простое возможное объяснение:
Скажем, у вас есть функция
function _loop(n) { console.log("so: " + n) }
очевидно, вы можете назвать это как_loop(69)
по-прежнему.
Перепишите так:
var _loop = function() { console.log("so: " + this.n) }
Обратите внимание, что сейчас
- аргументов как таковых нет
- вы используете this. , чтобы перейти к именованным аргументам
Теперь вы можете вызвать функцию следующим образом:
_loop.bind( {"n": 420} )
Вот и все.
Наиболее типичный вариант использования:
Действительно типичное использование - это когда вам нужно добавить аргумент к обратному вызову.
Обратные вызовы не могут иметь аргументов.
Так что просто «перепишите» обратный вызов, как указано выше.
Рассмотрим простую программу, указанную ниже,
//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);
Простое объяснение:
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'));
Метод bind() создает новую функцию, которая при вызове имеет
this
ключевое слово установлено в предоставленное значение с заданной последовательностью аргументов, предшествующей любым, предоставленным при вызове новой функции.
Пример для первой части
взято из реактивного пакета useSt8
import { useState } from "react"
function st8() {
switch(arguments.length) {
case 0: return this[0]
case 1: return void this[1](arguments[0])
default: throw new Error("Expected 0 or 1 arguments")
}
}
function useSt8(initial) {
// this in st8 will be something like [state, setSatate]
return st8.bind(useState(initial))
}
// usage
function Counter() {
const count = useSt8(0);
return (
<>
Count: {count()}
<button onClick={() => count(0)}>Reset</button>
<button onClick={() => count(prevCount => prevCount + 1)}>inc</button>
</>
);
}
Пример для второй части
const add = (a, b) => a+b
someThis = this
// new function with this value equal to someThis
add5 = add.bind(someThis, 5)
add5(10) // 15
// we don't use this in add decelartion so this will work too.
add10 = add.bind(null, 10)
add10(5) // 15
Функция bind создает новую функцию с тем же телом функции, что и вызываемая функция. Она вызывается с аргументом this. Почему мы используем привязку fun.: когда каждый раз создается новый экземпляр, и мы должны использовать первый начальный экземпляр, мы используем привязку fun. Мы не можем переопределить привязку fun. просто она хранит начальный объект класса.
setInterval (this.animate_to.bind (this), 1000 / this.difference);
function.prototype.bind() принимает объект.
Он связывает вызывающую функцию с переданным объектом и возвращает то же самое.
Когда объект привязан к функции, это означает, что вы сможете получить доступ к значениям этого объекта изнутри функции, используя ключевое слово this.
Также можно сказать,
function.prototype.bind() используется для предоставления / изменения контекста функции.
Попробуем разобраться в этом.
let powerOfNumber = function(number) {
let product = 1;
for (let i = 1; i <= this.power; i++) {
product *= number;
}
return product;
}
Здесь, в этой функции, это соответствует объекту, связанному с функцией powerOfNumber. В настоящее время у нас нет функции, связанной с этой функцией.
Давайте создадим функцию powerOfTwo, которая найдет вторую степень числа, используя указанную выше функцию.
let powerOfTwo = powerOfNumber.bind({power:2});
alert(powerOfTwo(2));
Здесь объект {power: 2} передается в функцию powerOfNumber с помощью привязки.
Функция bind связывает этот объект с powerOfNumber() и возвращает приведенную ниже функцию в powerOfTwo. Теперь powerOfTwo выглядит так:
let powerOfNumber = function(number) {
let product = 1;
for(let i=1; i<=2; i++) {
product*=number;
}
return product;
}
Следовательно, powerOfTwo найдет вторую степень.
Не стесняйтесь проверить это.
Для начинающих Javascript с фоном ООП, как я, я обнаружил, что это простое объяснение для понимания,
https://www.youtube.com/watch?v=GhbhD1HR5vk
Вы можете перейти к 5:00, но я бы рекомендовал смотреть его с самого начала.
Простой пример
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
Я не читал приведенный выше код, но я кое-что узнал просто, поэтому хочу поделиться здесь о методе привязки после метода привязки, мы можем использовать его как любой обычный метод.
<pre> note: do not use arrow function it will show error undefined </pre>
let solarSystem = {
sun: 'red',
moon : 'white',
sunmoon : function(){
let dayNight = this.sun + ' is the sun color and present in day and '+this.moon + ' is the moon color and prenet in night';
return dayNight;
}
}
let work = function(work,sleep){
console.log(this.sunmoon()); // accessing the solatSystem it show error undefine sunmmon untill now because we can't access directly for that we use .bind()
console.log('i work in '+ work +' and sleep in '+sleep);
}
let outPut = work.bind(solarSystem);
outPut('day','night')
В дополнение к сказанному bind()
Метод позволяет объекту заимствовать метод у другого объекта без создания копии этого метода. В JavaScript это называется заимствованием функций.
Другое использование заключается в том, что вы можете передать связанную функцию в качестве аргумента другой функции, которая работает в другом контексте выполнения.
var name = "sample";
function sample(){
console.log(this.name);
}
var cb = sample.bind(this);
function somefunction(cb){
//other code
cb();
}
somefunction.call({}, cb);
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%'