手写call、apply、bind函数
来源
https://juejin.cn/post/6968713283884974088#heading-9
https://mp.weixin.qq.com/s/uKPVedfQkgEPYoRUtwyeQQ
call
Function.prototype.mCall = function (context, ...args) {
context = context || window || global;
// 避免变量名重复
const funcName = Symbol();
// 保证函数执行时的this是context(谁调用的该函数,谁就是函数执行时的this)
context[funcName] = this;
const res = args.length ? context[funcName](...args) : context[funcName]();
// 对应上面的添加,避免对context造成变量污染
delete context[funcName];
return res;
}
apply
Function.prototype.mApply = function (context, args = []) {
context = context || window || global;
const funcName = Symbol();
context[funcName] = this;
// 传入的参数不是数组
if (!Array.isArray(args)) {
args = [];
}
const res = args.length ? context[funcName](...args) : context[funcName]();
delete context[funcName];
return res;
}
bind
这里有一些特殊,如果绑定后返回的新函数被使用new运算符调用,绑定时的this参数会被忽略
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
原bind函数关于new操作符的使用
参考:
https://www.webhek.com/post/javascript-bind.html
https://mp.weixin.qq.com/s/nI8VHuVQP73DGBrBdh5i2w
function Person (name, age) {
this.name = name;
this.age = age;
console.log(this);
}
const mPerson = Person.bind({ height: 180 });
mPerson('zhangsan', 18); // { height: 180, name: 'zhangsan', age: 18 }
new mPerson('lisi', 19); // Person { name: 'lisi', age: 19 } ,绑定时的this被忽略
手写实现
Function.prototype.mBind = function (thisArg, ...args) {
thisArg = thisArg || window || global;
const fn = this;
// 返回命名函数,用于比较是否是使用new运算符调用的绑定函数
return function /*newFn*/(...newArgs) {
// 是使用new运算符调用的该函数,忽略thisArg
// if (this instanceof newFn) {
// return new fn(...args, ...newArgs);
// }
// 或者下面这样。`new.target`可以检测函数是否是用`new`运算符调用的
if (new.target) {
return new fn(...args, ...newArgs)
}
return fn.apply(thisArg, [...args, ...newArgs]);
}
}


浙公网安备 33010602011771号