作用:改变函数this指向,返回一个绑定了this的新函数,你需要再次调用此函数才会执行。
知识储备
- bind与apply/call一样都能改变函数this指向 ,但bind并不会立即执行函数。
- 对call/apply的实现很清晰。
- 函数柯里化:
函数调用时只传递一部分参数,于是会返回一个新函数去处理剩下的参数,一个经典简单的例子:
//函数柯里化
function fn(x, y) {
return function (y) {
console.log(x + y);
};
};
var fn_ = fn(1);
fn_(2); //3
fn(1)(3) //3
可见 函数柯里化使用了闭包。
实现步骤
-
从调用fn._bind(obj)就得知,_bind里的this指的就是它的调用者也就是这个fn函数,所以先缓存起来
-
返回一个函数,函数里利用call或是apply把this指向修改掉
代码实现
版本一
Function.prototype._bind = function (obj) {
var fn = this;
return function () {
fn.apply(obj);
};
};
注意:
- 程序一上来就要先this保存,否则后续在调用bind时内部this会指向window,var fn = this。
- 新函数的this无法再次被修改,使用
call、apply也不行
测试代码
var obj = {
num: 1
};
function fn() {
console.log(this.num);
};
var bound = fn._bind(obj);
bound(); //1
版本一虽然满足了this修改与函数返回,但不支持函数传参,于是:
版本二
Function.prototype._bind= function (obj) {
//第0位是this,所以得从第一位开始裁剪
var args = Array.prototype.slice.call(arguments, 1);
var fn = this;
return function () {
fn.apply(obj, args);
};
}
从官方文档知道bind还支持函数柯里化,在首次调用bind时先传部分参数,再调用返回的bound时可以补全剩余参数。
版本三
Function.prototype._bind = function (obj) {
//第0位是this,所以得从第一位开始裁剪
var args = Array.prototype.slice.call(arguments, 1);
var fn = this;
return function () {
//二次调用我们也抓取arguments对象
var params = Array.prototype.slice.call(arguments);
//注意concat的顺序
fn.apply(obj, args.concat(params));
};
};
测试代码
var obj = {
num: 1
};
function fn(x, y) {
console.log(x + y + this.num);
};
var bound = fn._bind(obj, 2);
bound(3); //6