大家好,我是你們的導師,我每天都會在這里給大家分享一些干貨內容(當然了,周末也要允許老師休息一下哈)。昨天給大家分享了JAVAScript的閉包,今天給大家分享一下call和Apply的模擬實現。
1. call函數
一句話介紹 call:call() 方法在使用一個指定的 this 值和若干個指定的參數值的前提下調用某個函數或方法。舉個例子:
注意兩點:
1)call 改變了 this 的指向,指向到 foo;
2)bar 函數執行了
2. 模擬實現第一步
那么我們該怎么模擬實現這兩個效果呢?試想當調用 call 的時候,把 foo 對象改造成如下:
這個時候 this 就指向了 foo,是不是很簡單呢?但是這樣卻給 foo 對象本身添加了一個屬性,這可不行吶!不過也不用擔心,我們用 delete 再刪除它不就好了。所以我們模擬的步驟可以分為:
1)將函數設為對象的屬性
2)執行該函數
3)刪除該函數
以上個例子為例,就是:
fn 是對象的屬性名,反正最后也要刪除它,所以起成什么都無所謂。根據這個思路,我們可以嘗試著去寫第一版的 call2 函數:
3. 模擬實現第二步
最一開始也講了,call 函數還能給定參數執行函數。舉個例子:
注意:傳入的參數并不確定,這可咋辦?不急,我們可以從 Arguments 對象中取值,取出第二個到最后一個參數,然后放到一個數組里。比如這樣:
不定長的參數問題解決了,我們接著要把這個參數數組放到要執行的函數的參數里面去。
也許有人想到用 ES6 的方法,不過 call 是 ES3 的方法,我們為了模擬實現一個 ES3 的方法,要用到ES6的方法,好像……,嗯,也可以啦。但是我們這次用 eval 方法拼成一個函數,類似于這樣:
eval('context.fn(' + args +')')
這里 args 會自動調用 Array.toString() 這個方法。所以我們的第二版克服了兩個大問題,代碼如下:
4. 模擬實現第三步
模擬代碼已經完成 80%,還有兩個小點要注意:
1)this 參數可以傳 null,當為 null 的時候,視為指向 window,舉個例子:
雖然這個例子本身不使用 call,結果依然一樣。
2)函數是可以有返回值的!舉個例子:
不過都很好解決,讓我們直接看第三版也就是最后一版的代碼:
到此,我們完成了 call 的模擬實現。
5. apply的模擬實現
apply 的實現跟 call 類似,在這里直接給代碼:
今天就分享到這,如果覺得對你有一丟丟幫助,請點擊【收藏評論】,讓更多人看到該文章。大家也可以在底部給我留言,對于有價值的留言,我們都會一一回復的。