【发布时间】:2011-01-15 06:10:18
【问题描述】:
bind() 在 JavaScript 中有什么用?
【问题讨论】:
-
调用函数可以看成
ptr.func(),提供上下文的是ptr。
标签: javascript function bind
bind() 在 JavaScript 中有什么用?
【问题讨论】:
ptr.func(),提供上下文的是ptr。
标签: javascript function bind
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
您还可以在第一个 (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());
}
};
【讨论】:
var Note = React.createClass({ add: function(text){ ... }, render: function () { return <button onClick={this.add.bind(null, "New Note")}/> } },那么当点击按钮时,它会传递一个参数文本“New Note”给add方法。
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
有关更多信息,请参阅 MDN Web Docs 上的此链接:
【讨论】:
prototype)。
bind 允许-
例如,您有一个扣除每月俱乐部费用的功能
function getMonthlyFee(fee){
var remaining = this.total - fee;
this.total = remaining;
return this.name +' remaining balance:'+remaining;
}
现在您想为其他俱乐部成员重复使用此功能。请注意,每月费用将因会员而异。
假设 Rachel 的余额为 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 函数可以用于其他会员费不同的会员。例如,Ross Geller 的余额为 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
【讨论】:
来自the MDN docsFunction.prototype.bind():
bind() 方法创建了一个新函数,在调用该函数时,该函数具有 此关键字设置为提供的值,具有给定的序列 调用新函数时提供的任何参数之前的参数。
那么,这是什么意思?!
好吧,让我们看一个看起来像这样的函数:
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,因为我们在绑定时传递了这些值。
【讨论】:
变量具有本地和全局范围。假设我们有两个同名的变量。一个是全局定义的,另一个是在函数闭包内定义的,我们想要获取函数闭包内的变量值。在这种情况下,我们使用这个 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>
【讨论】:
bind() 方法将对象作为第一个参数并创建一个新函数。当函数被调用时,函数体中this 的值将是bind() 函数中作为参数传入的对象。
this 在 JS 中是如何工作的javascript 中this 的值始终取决于调用函数的对象。 this 的值始终是指点左侧的对象,从那里调用函数。在全局范围的情况下,这是window(或nodeJS 中的global)。只有 call、apply 和 bind 可以不同地更改 this 绑定。下面是一个展示 this 关键字如何工作的示例:
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
Bind 可以帮助克服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 的值将保持不变。
【讨论】:
obj 的 cmets 是对象,因为它位于点的左侧,window 是对象,因为它是 window.custFunc() 的简写,而 window 是左侧点对我来说非常有见地。
我将在理论上和实践上解释绑定
javascript中的bind是一个方法——Function.prototype.bind。绑定是一种方法。它在函数原型上调用。此方法创建一个函数,其主体类似于调用它的函数,但“this”指的是传递给 bind 方法的第一个参数。它的语法是
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;
【讨论】:
bind 方法从另一个函数创建一个新函数,其中一个或多个参数绑定到特定值,包括隐式 this 参数。
这是partial application 的示例。通常我们提供一个函数,它的所有参数都会产生一个值。这被称为函数应用程序。我们将函数应用于它的参数。
部分应用程序是higher order function (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));
以下示例展示了如何使用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() 方法创建一个新函数实例,其 this 值绑定到传递给 bind() 的值。 例如:
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue
这里,通过调用 bind() 并传入对象 o,从 sayColor() 创建了一个名为 objectSayColor() 的新函数。 objectSayColor() 函数的 this 值等同于 o,因此调用该函数,即使作为全局调用,也会导致显示字符串“blue”。
参考:Nicholas C. Zakas - 面向 Web 开发人员的专业 JAVASCRIPT®
【讨论】:
如前所述,Function.bind() 允许您指定函数将在其中执行的上下文(也就是说,它允许您传入 this 关键字将在函数体中解析为的对象。
几个执行类似服务的类似工具包 API 方法:
【讨论】:
/**
* 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.prototype.bind = function () {
const self = this;
const args = [...arguments];
const context = args.shift();
return function () {
return self.apply(context, args.concat([...arguments]));
};
};
绑定函数可以接受任意数量的参数并返回一个新函数。
新函数将使用 JS 的 Function.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(); // ?
【讨论】:
考虑下面列出的简单程序,
//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 参数调用。为什么我们使用 bind fun。 : 当每次创建一个新实例并且我们必须使用第一个初始实例时,我们使用绑定乐趣。我们不能覆盖绑定乐趣。只是它存储了类的初始对象。
setInterval(this.animate_to.bind(this), 1000/this.difference);
【讨论】:
function lol(second, third) {
console.log(this.first, second, third);
}
lol(); // undefined, undefined, undefined
lol('1'); // undefined, "1", undefined
lol('1', '2'); // undefined, "1", "2"
lol.call({first: '1'}); // "1", undefined, undefined
lol.call({first: '1'}, '2'); // "1", "2", undefined
lol.call({first: '1'}, '2', '3'); // "1", "2", "3"
lol.apply({first: '1'}); // "1", undefined, undefined
lol.apply({first: '1'}, ['2', '3']); // "1", "2", "3"
const newLol = lol.bind({first: '1'});
newLol(); // "1", undefined, undefined
newLol('2'); // "1", "2", undefined
newLol('2', '3'); // "1", "2", "3"
const newOmg = lol.bind({first: '1'}, '2');
newOmg(); // "1", "2", undefined
newOmg('3'); // "1", "2", "3"
const newWtf = lol.bind({first: '1'}, '2', '3');
newWtf(); // "1", "2", "3"
【讨论】:
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;
}
let powerOfTwo = powerOfNumber.bind({power:2});
alert(powerOfTwo(2));
let powerOfThree = powerOfNumber.bind({power:3});
alert(powerOfThree(2));
let powerOfFour = powerOfNumber.bind({power:4});
alert(powerOfFour(2));
让我们试着理解这一点。
let powerOfNumber = function(number) {
let product = 1;
for (let i = 1; i <= this.power; i++) {
product *= number;
}
return product;
}
这里,在这个函数中,this对应绑定到函数powerOfNumber的对象。目前我们没有任何绑定到这个函数的函数。
让我们创建一个函数 powerOfTwo,它会使用上面的函数找到数字的二次方。
let powerOfTwo = powerOfNumber.bind({power:2});
alert(powerOfTwo(2));
这里对象 {power : 2} 使用绑定传递给 powerOfNumber 函数。
绑定函数将此对象绑定到 powerOfNumber() 并将以下函数返回给 powerOfTwo。现在,powerOfTwo 看起来像,
let powerOfNumber = function(number) {
let product = 1;
for(let i=1; i<=2; i++) {
product*=number;
}
return product;
}
因此,powerOfTwo 将找到第二个幂。
请随意查看。
【讨论】:
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
【讨论】:
另一种用法是您可以将绑定函数作为参数传递给在另一个执行上下文下运行的另一个函数。
var name = "sample";
function sample(){
console.log(this.name);
}
var cb = sample.bind(this);
function somefunction(cb){
//other code
cb();
}
somefunction.call({}, cb);
【讨论】:
除了已经说过的,bind() 方法允许一个对象从另一个对象借用一个方法,而无需复制该方法。这在 JavaScript 中称为 函数借用。
【讨论】:
bind。
我没有读过上面的代码,但是我学到了一些简单的东西,所以想在这里分享一下绑定方法之后的绑定方法,我们可以像任何普通方法一样使用它。
<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 是一个在 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%'
【讨论】: