bind()方法的解析
1.bind()方法是ECMAScript新增加的一个方法,主要作用是改变this指向。bind()是Function.prototype上的一个方法,所以调用它的只能是一个方法,bind会将调用它的方法里面的this指向bind()的第一个参数。
例如:
[].slice.bind([1,2,3,4],1)(2)
[].slice === Array.prototype.slice === new Array().slice
原本slice函数中的this应该指向[],而现在指向[1,2,3,4],实际上可以理解为`[1,2,3,4].slice(1,2)`
var sli = [].slice.bind([2, 3, 4, 5, 6], 1)(3)
console.log(sli) // Array[3, 4]
2.bind()方法的实现实际上是返回了一个函数体,函数体内的参数会与bind()方法第一个参数除外的其它参数合并为一个arguments并执行(都合并参数了,肯定是返回函数被调用了!!!)。
[].slice.bind([1,2,3,4],1)(2) == [].slice.bind([1,2,3,4], 1, 2)() == [].slice.bind([1,2,3,4])(1, 2)
function func(a, b, c) {
console.log(a, b, c);
}
func.bind(null, 'linxin')('A', 'B', 'C'); // linxin A B
func.bind(null, 'linxin')('A', 'B', 'C') == windows.func('linxin', 'A', 'B', 'C') == func('linxin', 'A', 'B', 'C')
bind()方法的实现
IE老版本可能不支持 bind() 方法,所以可以写个兼容方法
if(!Function.prototype.bind) {
Function.prototype.bind = function() {
var self = this, // 存储执行上下文
context = [].shift.call(arguments), // 获取bind()方法的第一个参数(因为 arguments 是一个类数组,并非真正的数组对象,它是没有Array原型上的方法的。shift() 方法会直接改变原始对象)
args = [].slice.call(arguments); // 获取bind()方法剩下的参数
return function() {
self.apply(context, [].concat.call(args, [].slice.call(arguments)))
// self 保存了copyBind 的执行期上下文,所以这里的 self 指向的是copyBind而不是windows
// [].concat.call(args, [].slice.call(arguments)) == args.concat([].slice.call(arguments))
}
}
}
“`