背景:
之前今日頭條的面試題,有一道題是自己實現(xiàn)一個bind方法,有同學由于考慮的情況不夠完全,結(jié)果崩了。今天在群里私聊我希望我可以通俗易懂的跟他分享下我的理解。今天下班后想起他這個問題想了想還是打開電腦開始碼字,現(xiàn)在大腦思緒還不是很齊全,就簡單的分享下。
這里大致總結(jié)一下:
首先我們要知道call方法做了什么,它做了兩點:

1.call 改變了 this 的指向,指向到 foo
2.bar 函數(shù)執(zhí)行了
我們知道它做了兩點,那么就可以設(shè)計思路了,至于怎么一步步實現(xiàn)這個方法,上面的鏈接,這里不多說,那么直接附上完整代碼:

大概的思路就是首先利用函數(shù)的原型
Function.prototype.call2 = function(context){這里面的this指向調(diào)用該call2方法的函數(shù)} 為所有函數(shù)增添一個call2方法,然后利用call方法傳進去的第一個參數(shù)(對象),在對象里面增添一個屬性,該屬性是一個方法,那么,這個方法(添加到對象里面的方法)的this就指向這個對象,然后就是執(zhí)行該方法(添加到對象的方法),并把call方法的其他參數(shù)傳進去執(zhí)行。
?這里就有一個問題
上面的參數(shù)存放到數(shù)組里面,那么怎么把數(shù)組變成參數(shù)添加到函數(shù)里面并執(zhí)行呢?無疑,ES6的擴展運算符可以做到,但是封裝一個call方法用到es6的方法就不太好了,這里的關(guān)鍵就是一個用到eval函數(shù),它能調(diào)用js解析器把參數(shù)當做js表達式執(zhí)行。
看到上面的代碼,首先我覺得奇怪的是args.push('arguments[' + i + ']');
(為了能夠更好的理解下面的內(nèi)容,可以先跳到后面看eval函數(shù)里面的那個數(shù)組發(fā)生了什么事情)這段代碼為什么要用引號引起來,也就是push一個字符轉(zhuǎn)到數(shù)組里面,執(zhí)行了這段代碼
args里面是['arguments[1]','arguments[2]'],那讓我們看看不用引號,直接執(zhí)行args.push(arguments[i]) 會發(fā)生什么,把上面的代碼的這個args.push('arguments[' + i + ']'); 換成args.push(arguments[i]) 它會發(fā)生什么? 沒錯它報錯了,報了下面的錯誤

kevin這個東西沒有定義?為什么,因為現(xiàn)在args是這樣的值[‘kevin’,18],它在執(zhí)行eval函數(shù)的時候報錯了,也就是var result = eval('context.fn(' + args +')'); 這里報錯,為什么會報錯,eval是什么東東,下面我們來測試一下

這就是報錯的原因,當執(zhí)行到var result = eval('context.fn(' + args +')'); 這段代碼的時候,eval調(diào)用js解釋器,將里面的執(zhí)行,這時候args是[‘kevin’,18],這兩個東西上文根本就沒定義,不是變量,由上圖知道,只有有聲明定義的變量eval函數(shù)才不會報錯,這就是它報錯的原因,而若是用這個`args.push('arguments[' + i + ']'); ,那么args就是['argsments[1]','arguments[2]'],而argsments[1]和argusment[2]是聲明定義的,argsments[1] = 'kevin', arguments[2] = 18,也就是eval('arguments[1]')不會報錯而eval('kevin')會報錯,和上圖報錯是一樣的。 現(xiàn)在再來看看var result = eval('context.fn(' + args +')'); 這個函數(shù)為什么可以把數(shù)組變成參數(shù)和函數(shù)結(jié)合起來,我看之前的文章的時候就漏看了一點,當執(zhí)行到這里的時候,args會自動調(diào)用toString()方法,也就是變成了"arguments[1],arguments[2]" ,這樣數(shù)組就變成參數(shù)串然后和前面的函數(shù)拼接起來執(zhí)行。這就能執(zhí)行函數(shù)了,為了驗證eval()函數(shù)的參數(shù)是數(shù)組,是不是調(diào)用了toString()方法,我進行了試驗,發(fā)現(xiàn)貌似只有是在執(zhí)行函數(shù)當做函數(shù)參數(shù)的時候才調(diào)用toString()方法,看下圖

然后apply方法的實現(xiàn)和call方法差不多,只是apply方法的后面的參數(shù)是一個數(shù)組
暫時先把這些碼著,歡迎大家有問題一起交流 。文章不是很好,莫見怪。