bind() 的功能

bind() 用于将函数内的this指向目标对象(bind的第一个参数)

f.bind(obj),可以理解为obj.f()

bind() 的使用场景

this 的指向不符合预期时,可以使用 bind() 改变this的指向。

var a = {
b: function() {
var func = function() {
// 这里的this指向的是全局作用域
console.log(this.c);
}
func();
},
c: 'hello'
}
a.b(); // undefined

不使用 bind() 的写法

var a = {
b: function() {
var _this = this; // 通过赋值的方式传递正确的this
var func = function() {
console.log(_this.c);
}
func();
},
c: 'hello'
}
a.b(); // hello

bind() 的用法

写法一

var a = {
b: function() {
var func = function() {
console.log(this.c);
}.bind(this);
func();
},
c: 'hello'
}
a.b(); // hello

写法二

var a = {
b: function() {
var func = function() {
console.log(this.c);
}
func.bind(this)();
},
c: 'hello'
}
a.b(); // hello

更多高级用法

// 分析:这里的bind方法会把它的第一个实参绑定给f函数体内的this,所以里的this即指向{x:1}对象;
// 从第二个参数起,会依次传递给原始函数,这里的第二个参数2即是f函数的y参数;
// 最后调用m(3)的时候,这里的3便是最后一个参数z了,所以执行结果为1+2+3=6
// 分步处理参数的过程其实是一个典型的函数柯里化的过程(Curry)
function f(y,z){
return this.x+y+z;
}
var m = f.bind({x:1},2);
console.log(m(3)); // 6
// 分析:直接调用a的话,this指向的是global或window对象,所以会报错;
// 通过bind或者call方式绑定this至document对象即可正常调用
var a = document.write;
a('hello'); // error
a.bind(document)('hello'); // hello
a.call(document,'hello'); // hello
// 实现预定义参数
// 分析:Array.prototype.slice.call(arguments)是用来将参数由类数组转换为真正的数组;
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1,2,3]
// 第一个参数undefined表示this的指向,第二个参数10即表示list中真正的第一个参数,依次类推
var a = list.bind(undefined, 10);
var list2 = a(); // [10]
var list3 = a(1, 2, 3); // [10,1,2,3]

原生 js 实现 bind()

只可绑定,不可传参的bind

Function.prototype.my_bind = function(context){
var self = this;
return function(){
self.apply(context,arguments);
}
}
function a(){
console.log(this.name);
}
a(); // ''
var b = {
name: 'apple'
};
a.bind(b)(); // apple
a.my_bind(b)(); // apple

可传参的bind

Function.prototype.my_bind = function() {
var self = this, // 保存原函数
context = Array.prototype.shift.call(arguments), // 保存需要绑定的this上下文
// 上一行等价于 context = [].shift.call(arguments);
args = Array.prototype.slice.call(arguments); // 剩余的参数转为数组
return function() { // 返回一个新函数
self.apply(context, Array.prototype.concat.call(args, Array.prototype.slice.call(arguments)));
}
}

function a(m, n,) {
console.log(this.name + ' ' + m + ' ' + n + ' ' + o);
}

var b = {
name: 'kong'
};

a.my_bind(b, 7, 8)(9); // kong 7 8 9