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, o) { console.log(this.name + ' ' + m + ' ' + n + ' ' + o); } var b = { name: 'kong' }; a.my_bind(b, 7, 8)(9); // kong 7 8 9