浅析 JavaScript 中的 Function.prototype.bind() 方法
Function.prototype.bind()方法
bind()
方法的主要作用就是将函数绑定至某个对象,bind()
方法会创建一个函数,函数体内this对象的值会被绑定到传入bind()
函数的值。
例如,在 f()
函数上调用 bind()
方法并传入参数 obj
,即 f.bind(obj)
,这将返回一个新函数, 新函数会把原始的函数 f()
当做 obj
的方法来调用,就像 obj.f()
似的,当然这时 f() 函数中的 this
对象指向的是 obj
。
简单使用情形一
var o={
f: function () {
var self=this;
var fff=function() {
console.log(self.value); //此时 this 指向的是全局作用域 global/window,因此需要使用 self 指向对象o
};
fff();
},
value: "Hello World!"
};
o.f(); // Hello World!
上例是我们常用了 保持 this
上下文的方法,把 this
赋值给了中间变量 self
,这样在内部嵌套的函数中能够使用 self
访问到对象o
,否则仍使用 this.value
,内部嵌套函数的this此时指向的是全局作用域,最后的输出将会是 undefined
,代码如下:
var o={
f: function () {
var self=this;
var fff=function() {
console.log(this.value);
};
fff();
},
value: "Hello World!"
};
o.f(); // undefined
但是,如果我们使用 bind()
函数,将fff
函数的绑定在对象o
中,即将fff()
函数内部的 this
对象绑定为对象 o
,那么可以遇见此时 this.value
是存在的。代码如下:
var o={
f: function () {
var self=this;
var fff=function() {
console.log(this.value); // bind(this) 中 this 指向的是o,这里也可直接写成 bind(o)
}.bind(this);
fff();
},
value: "Hello World!"
};
o.f(); // Hello World!
更普遍的使用情形
再看一个例子:
function f(y,z){
return this.x+y+z;
}
var m=f.bind({x:1},2);
console.log(m(3)); // 6
最后将输出 6
这是因为 bind()
方法会把传入它的第一个实参绑定给f函数体内的 this
,从第二个实参起,将依此传递给原始函数,因此 {x:1}
传递给this
,2
传递给形参y
,m(3)
调用时的3
传递给形参z
。
其实这个例子 f()
函数能够处理部分参数,分步计算 ( bind()
时处理了参数x
,和参数y
,调用 m(3)
时处理了参数z
)的过程其实是一个典型的Curry过程(Currying)。
bind()背后的简单原理
那么bind函数背后做了什么呢? 我们可以用以下代码来模拟:
Function.prototype.testBind = function (scope) {
var fn = this; // this 指向的是调用testBind方法的一个函数
return function () {
return fn.apply(scope, arguments);
}
};
下面是测试的例子:
var foo = {x: "Foo "};
var bar = function (str) {
console.log(this.x+(arguments.length===0?'':str));
};
bar(); // undefined
var testBindBar = bar.testBind(foo); // 绑定 foo
testBindBar("Bar!"); // Foo Bar!
当调用 testBind()
后,我们创建了一个新的函数,通过调用 apply
将 this
设置成 foo
, OK,现在应该比较清晰了,但实际 bind()
的实现远比上面的复杂,如上面提到的 curry化过程等,上面只是主要原理便于学习理解 bind()
函数。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?