由于在低版本浏览器没有js原生bind方法,所以要兼容低版本浏览器的话就要手动实现
了解bind函数
bind 强制将函数的执行环境绑定到目标作用域中去
与 call 和 apply 其实有点类似,但是不同点在于,bind 方法不会立即执行
“bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。”
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
if(typeof this != 'function'){// 判断调用者是不是函数
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var self = this, // 保存原函数 (this指向调用bind者)
context = [].shift.call(arguments), // 把参数中的第一个剪切出来,保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数
self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}
}
}
复制代码
看到[].concat.call(args, [].slice.call(arguments)也有点蒙圈,参数不就是args么,为什么要合并它自己?如果你也是这么认为的那就请认真往下阅读 其实args是绑定上下文的时候(也就是bind())传递的参数,而后面的arguments则是调用bind()()第二个括号传递的参数,所以这里才会需要合并 如果还是有点不明白可以看看一下的代码
Function.prototype.binding = function () {
let self = this;
let context = [].shift.call(arguments);
let args = [].slice.call(arguments);
console.log(args);
return function () {
self.apply(context, [].concat.call(args, [].slice.call(arguments)))
}
};
let obj = {
a: 'a'
};
function f(b, c, d) {
console.log(this.a, b, c, d)
}
f.binding(obj, 'b', 'c', 'd')('e');
f.binding(obj, 'b', 'c')('d', 'e');
f.binding(obj, 'b')('c', 'd', 'e');
f.binding(obj)('b', 'c', 'd', 'e');
输出:
[ 'b', 'c', 'd' ] a b c d
[ 'b', 'c' ] a b c d
[ 'b' ] a b c d
[] a b c d