先看一段代碼
// 聲明一個函數(shù)輸出函數(shù)運行時的上下文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能調(diào)用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內(nèi)部的實現(xiàn)過程辕棚,就是給obj1加一個func焦人,然后再運行一下obj1.func
// 實現(xiàn)一個自己的call
Function.prototype.fakeCall = function(obj){
obj.func = this;// 運行時this指向的是函數(shù)本身
obj.func();
delete obj.func;
}
function func() {
console.log(this.a);
}
var obj1 = {
a: "obj1",
};
func();// "window"
func.fakeCall(obj1);// "obj1"
現(xiàn)在的fakeCall還無法傳參竖独,只是修改了一個this指向,可以使用es6的...來傳參
// 實現(xiàn)一個自己的call
Function.prototype.fakeCall = function(obj,...rest){
obj.func = this;// 運行時this指向的是函數(shù)本身
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