題目
實現一個 call / apply 方法。
解析
call 和 apply 方法一個重要的特徵就是第一個參數可以綁定 this 指向。如下案例:
var a = 100;
var obj = {
a:1000;
}
function fun(){
console.log(this.a);//1000
}
fun.call(obj);
如上所示,如果沒有使用 call 方法顯式地將 obj 對象綁定到 this。fun 函數中 this 指向的就是 window。而 apply 與 call 的區別就是 apply 方法從第二參數開始是以數組的形式傳參。
實現 call/apply 方法有兩個關鍵點:
-
綁定 this。this 指向問題可以用一句話概括,“誰調用,this 就指向誰”。所以綁定 this 就需要將調用的方法添加到傳過來的對象上去。再通過對象去調用。這樣就可以實現將 this 指向這個對象。
即結合以上案例可以簡單地理解爲是將 fun 方法添加到 obj 對象的屬性上。然後通過 obj 對象的屬性去調用 fun 方法,就可以實現 fun 中的 this 指向 obj。 -
傳遞參數。除了將方法添加到對象上,還需要將參數進行傳遞。傳遞參數可以有三種方式, apply,eval(循壞數組,拼接字符串),ES6 的數組解構。以下案例中使用的是 ES6 的數組解構。
代碼
實現一個 call 方法
Function.prototype._call = function(){
//1.將第一個參數(綁定this的對象)和剩餘參數解構出來
let [thisObj,...arg] = [...arguments];
//2.如果第一個參數爲空,則this爲全局對象
if(!thisObj){
thisObj = typeof window === 'undefined'? global:window;
}
//3.把this(調用_call的方法) 賦值到該對象的一個屬性上
thisObj._this = this;
//4.調用對象綁定的方法。
var result = thisObj._this(...arg);
//5.刪除綁定的屬性
delete thisObj._this;
//6.返回調用結果
return result;
}
//測試
var num = 18;
function Person(a,b) {
console.log(this.num + a + b);//60
}
var obj = {
num:20
}
Person._call(obj,20,20);
實現一個 apply 方法。
Function.prototype._apply = function(){
//1.將第一個參數(綁定this的對象)和數組參數(這裏是apply與call的區別)解構出來
let [thisObj,arg] = [...arguments];
//2.如果第一個參數爲空,則this爲全局對象
if(!thisObj){
thisObj = typeof window === 'undefined'? global:window;
}
//3.把this(調用_apply的方法) 賦值到該對象的一個屬性上
thisObj._this = this;
//4.調用對象綁定的方法。
var result;
if(arg){
if(!Array.isArray(arg)){
throw new Error("參數爲數組")
}else{
result = thisObj._this(...arg);
}
}else {
result = thisObj._this();
}
//5.刪除綁定的屬性
delete thisObj._this;
//6.返回調用結果
return result;
}
//測試
var num = 18;
function Person(a,b) {
console.log(this.num + a + b);//60
}
var obj = {
num:20
}
Person._apply(obj,[20,20]);