简单实现具体看下面这个列子:
let objA = {
name: "肖哥哥",
age: 20,
objAFun: function(form, to) {
console.log(`姓名:${this.name},年龄:${this.age},来自:${form},目的地是:${to}。`);
}
}
let objB = {
name: "七叶一枝花",
age: 23
}
objA.objAFun.myCall(objB, "广州", "广西");
objA.objAFun.myApply(objB, ["上海"]);
objA.objAFun.myBind(objB, ["北京"])();
1,实现call函数
Function.prototype.myCall = function(context) {
// 判断调用对象objAFun是否为函数
if(typeof this !== 'function') {
throw TypeError("typeof error");
}
// 获取所有参数
let args = [...arguments].slice(1);
let result = null;
// 判断context上下文是否传入,否则设置为对象函数
context = context || window;
// 将调用对象设为对象函数
context.fn = this;
// 调用函数
result = context.fn(...args);
// 将属性删除
delete context.fn;
return result;
}
2,实现apply函数
Function.prototype.myApply = function(context) {
if (typeof this !== 'function') {
throw TypeError("type error");
}
context = context || window;
context.fn = this;
let result = null;
// 如果有传入参数,则传入参数并调用函数
if ([...arguments][1]) {
result = context.fn([...arguments][1])
} else {
result = context.fn();
}
delete context.fn;
return result;
}
3,实现bind函数
Function.prototype.myBind = function(context) {
if (typeof this !== "function") {
throw TypeError("type error");
}
let args = [...arguments].slice(1);
let fn = this;
return function Fn() {
// 根据调用方式,传入不同绑定值
return fn.apply(this instanceof Fn ? this : context, args.concat(...arguments));
}
}