文章序
这是个老生常谈的问题了,就算不让你手写,那也大概率会问到你他们三个的区别和原理,本文就旨在一文帮你彻底搞懂这三个方法
使用方法
myFunction.call(obj,arguments1,arguments2,arguments3...);
执行原函数,函数中this指向参数obj,原函数myFunction参数为后面的arguments
myFunction.apply(obj,[arguments1,arguments2,arguments3...]);
执行原函数,函数中this只想参数obj,原函数myFunction入参为后面的arguments数组
myFunction.bind(obj);
返回一个函数,该函数的入参传给原函数myFunction,如需执行可以写为myFunction.bind(obj)(arguments1,arguments2,arguments3...);
手写
原始用法
请看下方示例,除了res0返回undefined undefined engineer web
,其余均返回hpf 24 engineer web
function Person(name, age) {
this.myName = name;
this.myAge = age;
}
const obj = new Person("hpf", 24);
function sayName(work, type) {
return this.myName + " " + this.myAge + " " + work + " " + type;
}
let res0 = sayName("engineer", "web");
let res1 = sayName.call(obj, "engineer", "web");
let res2 = sayName.apply(obj, ["engineer", "web"]);
let res3 = sayName.bind(obj)("engineer", "web");
console.log(res0); //undefined undefined engineer web
console.log(res1); //hpf 24 engineer web
console.log(res2); //hpf 24 engineer web
console.log(res3); //hpf 24 engineer web
call
参考call的使用方法,我们可以理解为在入参obj对象上新增一个sayName函数,然后将参数传入,执行该函数,执行结束后删除掉该函数
function myCall(obj) {
if(arguments.length === 0) {
throw Error("arguments cannot be empty!");
}
const param = [...arguments].slice(1);
obj.myCall = this;
let res = obj.myCall("engineer", "web");
delete obj.myCall;
return res;
}
Function.prototype.myCall = myCall;
let res = sayName.myCall(obj, "engineer", "web");
console.log(res); //hpf 24 engineer web
apply
参考apply的使用方法和call的手写,稍加改动即可轻松秒杀
function myApply(obj) {
if(arguments.length === 0) {
throw Error("arguments cannot be empty!");
}
const param = arguments[1];
obj.myApply = this;
let res = obj.myApply("engineer", "web");
delete obj.myApply;
return res;
}
Function.prototype.myApply = myApply;
let res = sayName.myApply(obj, ["engineer", "web"]);
console.log(res); //hpf 24 engineer web
bind
参考bind的使用方法,单纯的调用myFunction.bind只是返回一个函数,因此略有不同
function myBind(obj) {
if (arguments.length === 0) {
throw Error("arguments cannot be empty!");
}
const myFun = this;
const param = [...arguments].slice(1);
return function MyFun() {
return myFun.apply(
this instanceof MyFun ? this : obj,
param.concat([...arguments])
)
}
}
Function.prototype.myBind = myBind;
let res = sayName.myBind(obj)("engineer", "web");
console.log(res); //hpf 24 engineer web