先看一段代码
// 声明一个函数输出函数运行时的上下文this
var a = "window";
function func() {
console.log(this.a);
}
var obj1 = {
a: "obj1",
func,
};
var obj2 = {
a: "obj2",
func,
};
// this上下文是在运行时才确定
func();// "window"
obj1.func();// "obj1"
obj2.func();// "obj2"
如果我不想要在obj1和obj2里声明,但是我想要obj1和obj2能调用func这个方法怎么办呢?那就用call,apply直接修改func运行时的this指向
function func() {
console.log(this.a);
}
var obj1 = {
a: "obj1",
};
var obj2 = {
a: "obj2",
};
func();// "window"
func.apply(obj1);// "obj1"
func.call(obj2);// "obj2"
上面这两段代码的效果是一样的,所以反向来思考一下原理,call,apply内部的实现过程,就是给obj1加一个func,然后再运行一下obj1.func
// 实现一个自己的call
Function.prototype.fakeCall = function(obj){
obj.func = this;// 运行时this指向的是函数本身
obj.func();
delete obj.func;
}
function func() {
console.log(this.a);
}
var obj1 = {
a: "obj1",
};
func();// "window"
func.fakeCall(obj1);// "obj1"
现在的fakeCall还无法传参,只是修改了一个this指向,可以使用es6的...来传参
// 实现一个自己的call
Function.prototype.fakeCall = function(obj,...rest){
obj.func = this;// 运行时this指向的是函数本身
const res = obj.func(...rest);
delete obj.func;
return res;
}
function func(p1, p2) {
return this.a + p1 + p2;
}
var obj1 = {
a: 1,
};
func.fakeCall(obj1,2,3);// 6