- 首先我们要了解bind函数的用法,通过用法进行模拟
- bind用法:fn.bind(obj,x,y,...) obj为绑定this指向对象,x,y为绑定参数。
- 了解了上述用法我们开始说干就干
第一步 我们先把obj和参数绑定上去
Function.prototype.myBind = function(){
const targetFn = this; // 目标函数
const [targetObj,...targetArgs] = [...arguments]; // 解构对象及绑定时参数
if(typeof targetFn !== 'function') {
throw `${this} must be a function`
}
return function(){
targetFn.apply(targetObj,targetArgs);
}
}
第二步 我们发现上述函数生成新的函数后不能传参了,因此我们进行下改造
Function.prototype.myBind = function(){
const targetFn = this; // 目标函数
const [targetObj,...targetArgs] = [...arguments]; // 解构对象及绑定时参数
if(typeof targetFn !== 'function') {
throw `${this} must be a function`
}
return function(...args){
targetFn.apply(targetObj,[...targetArgs, ...args]);
}
}
第三步 我们绑定后的函数必须支持new 然而此时我们怎么new也new不正确就因为我们永远都是作用于目标对象 因此我们要进行判断是否使用new
Function.prototype.myBind = function(){
const targetFn = this; // 目标函数
const [targetObj,...targetArgs] = [...arguments]; // 解构对象及绑定时参数
if(typeof targetFn !== 'function') {
throw `${this} must be a function`
}
const newFn = function(...args){
const isNewFlag = this instanceof newFn // 如果进行了new 那么new出来的对象也就是this指向一定为newFn的实例 此处会为true;
targetFn.apply(isNewFlag ? this : targetObj,[...targetArgs, ...args]);
// 此处做判断,如果为new操作符的话 所有绑定应为此刻new的对象上
}
return newFn
}
第四步 new出来的对象其__proto__指向了新bind的函数 然而当前函数的prototype并没有指向原targetFn的prototype 因此我们需要设定一下 并注意不能直接引用否则再更改新bind出来的函数的prototype时会造成targetFn原型的修改
Function.prototype.myBind = function(){
const targetFn = this; // 目标函数
const [targetObj,...targetArgs] = [...arguments]; // 解构对象及绑定时参数
if(typeof targetFn !== 'function') {
throw `${this} must be a function`
}
const newFn = function(...args){
const isNewFlag = this instanceof newFn // 如果进行了new 那么new出来的对象也就是this指向一定为newFn的实例 此处会为true;
targetFn.apply(isNewFlag ? this : targetObj,[...targetArgs, ...args]);
// 此处做判断,如果为new操作符的话 所有绑定应为此刻new的对象上
}
const temporarilyFn = function(){};
temporarilyFn.prototype = targetFn.prototype;
newFn.proptotype = new temporarilyFn();
return newFn
}
以上便是我们bind函数的自我实现,其中与浏览器相比有一点不同的就是浏览器实现的bind函数是没有prototype属性的,但是当其使用new操作符时却仍然能够将其__proto__ 引用为targetFn的原型prototype上 很是神奇 有知道如何实现的大佬可以给予一下思路~