//bind特点
1.函数调用改变this;
2.返回一个绑定this的函数
3.接受多个参数
4.支持柯里化形式传参 fn(1)(2)
5.一个绑定的函数也能使用new操作法创建对象,且提供的this会被忽略。
- 可以通过call,apply可以实现bind函数
Function.prototype.mybind = function(context) {
if(typeof this !== 'function') {
throw new TypeError('Error')
}
let _this = this;
let arg = [...arguments].slice(1)
return function F() {
//处理函数使用new的情况
if(this instanceof F) {
return new _this(...arg, ...arguments)
} else {
return _this.apply(context,arg.concat(...arguments))
}
}
}
// 2.简易版的实现
Function.prototype.mybind2 = function(context, ...preArgs) {
return (...args) => this.call(context,...preArgs, ...args);
}
Function.peototype.bind3 = function(context) {
let self = this;
//支持柯里化传参,保存参数
let arg = [...arguments].slice(1)
return function() {
//同样因为支持科利华形式传参,我们需要再次获取存储参数
let newArg = [...arguments]
console.log(newArg)
//返回函数绑定的this,传入两次保存的参数
//考虑返回函数有返回值做了return
return self.apply(context, arg.concat(newArg))
}
}
4.推荐写法
Function.prototype.bind4 = function(context) {
if(typeof this !== "function") {
throw new Error(
"Error"
);
}
var self = this;
var args = Array.prototype.slice.call(arguments,1)
var fBound = function() {
var innerArgs = Array.prototype.slice.call(arguments);
return self.apply(
this instanceof fNOP ? this : context,
args.concat(innerArgs)
);
};
var fNOP = function() {};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
Function.prototype.bind2 = function(context) {
// 1. 判断调用bind的是不是一个函数
if (typeof this !== "function") {
throw new Error(
"error"
);
}
// 2. 外层的this指向调用者(也就是调用的函数)
var self = this;
// 3. 收集调用bind时的其它参数
var args = Array.prototype.slice.call(arguments, 1);
// 4. 创建一个返回的函数
var fBound = function() {
// 6. 收集调用新的函数时传入的其它参数
var innerArgs = Array.prototype.slice.call(arguments);
// 7. 使用apply改变调用函数时this的指向
// 作为构造函数调用时this表示的是新产生的对象, 不作为构造函数用的时候传递context
return self.apply(
this instanceof fNOP ? this : context,
args.concat(innerArgs)
);
};
// 5. 创建一个空的函数, 且将原型指向调用者的原型(为了能用调用者原型中的属性)
// 下面三步的作用有点类似于 fBoun.prototype = this.prototype 但有区别
var fNOP = function() {};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
// 8. 返回最后的结果
return fBound;
};
个人比较推荐最后一种写法。 欢迎加群。