手写bind函数与call函数
手写bind函数算是公司前端面试的一个高频考点,今天我们就来手写一个bind函数和一个call函数,这个bind函数的功能是要把this的值绑定到第一个参数上,将后续参数作为返回函数的参数,当出现异常(使用构造函数,没有设置参数)时,返回指定结果,就跟一个真的bind函数一样
let obj = {
name: 'xiaoxiaomeng',
say: function() {
console.log(arguments)
console.log(this.name)
}
}
let obj2 = {
name: 'miaomaiozi'
}
// obj.say();
// obj.say.call(obj2, 1, 2, 3);
// obj.say.apply(obj2, [1, 2, 3]);
// let sayclone = obj.say.bind(obj2, 1, 2, 3);
// sayclone();
// 原生JavaScript实现bind函数
Function.prototype.mybind = function(objThis, ...params) { //将我们手写的函数挂载到函数的原型链上,让所有函数都可以调用
const thisFn = this; //保存当前调用的函数
let funcForBind = (...secondparams) => {
const isNew = this instanceof funcForBind; //构造函数的优先级比bind高,如果用new执行构造函数,this会指向其本身,因此要先判断是否是构造函数
const thisArg = isNew ? this : objThis; //如果是构造函数,this指向其本身,否则将this绑定到第一个参数上
return thisFn.call(thisArg, ...params, ...secondparams)
}
funcForBind.prototype = Object.create(thisFn.prototype) //将调用函数的原型链复制一份赋值给被返回的函数
return funcForBind
}
let sayclone = obj.say.mybind(obj2, 1, 2, 3);
sayclone();
// 原生JavaScript实现call
Function.prototype.mycall = function(thisArg, ...arr) {
if (thisArg === null || thisArg === undefined) {
thisArg = window; //如果第一个参数为空,则默认为window
} else {
const specialMethod = Symbol('anything');//构造一个独一无二的方法(symbol类型)来装载调用的函数
thisArg[specialMethod] = this; //让装载的函数作为第一个参数的方法,此时方法内部的this指向第一个参数,等号后面的this就是调用call方法的函数
let result = thisArg[specialMethod](...arr);//返回这个函数的结果
delete thisArg[specialMethod];//清除这个方法
return result;
}
}
obj.say.mycall(obj2, 1, 2, 3);
`