js裏對call的定義:數組
調用一個對象的一個方法,以另外一個對象替換當前對象。call方法接受如下參數(obj,argument1,argument2,...)。bash
咱們用call寫一個小demo:函數
如上圖咱們就能夠很直觀的理解js對call的定義。調用window對象下的fn方法,用obj對象替換了window對象。可能這句話理解仍是有些歧義,咱們以後再解釋。ui
爲何說obj對象替換了window對象?見圖:this
咱們從代碼裏看到直接調用fn
輸出window
下的name
。由於fn
在window
對象下,kack
也在window
下。 當咱們用call
的時候,把window
對象替換成了obj
,因此輸出了obj的name:'tom'
。spa
對於call的實現分析:prototype
問題一:咱們如何改變一個方法的this的指向呢? 問題二:如何去改變this指向,有去調用這個方法? 問題三:如何接受多個參數?再去執行? code
能夠看到咱們給一個對象添加一個fn1屬性,並把fn方法賦給這個屬性,就至關於改變了fn裏的this指向!而後再調用obj.fn1這個屬性,不就執行了fn方法嗎?是否是很簡單~ 那多出來的fn1屬性怎麼辦?也很簡單,把這個對象的屬性刪除不就能夠麼。。。那多個參數怎麼辦?咱們獲取一個方法的參數能夠經過arguments來獲取,arguments是一個僞數組對象。而後遍歷這個對象把屬性再放到一個數組裏,這樣就能夠取出來了。 最後一個問題:獲得參數數組後怎麼放到方法裏去執行呢?咱們要用到eval()
函數,eval()
函數可計算某個字符串,並執行其中的的 JavaScript 代碼。cdn
咱們先按上面的分析實現call:對象
Function.prototype._call = function(){
var args = [];
var obj = arguments[0] || window; // call 若是第一個參數傳null,則這個對象是window
for(var i=1, len = arguments.length; i < len; i++){
// 由於執行一個函數傳參通常都是傳string類型,因此此處須要用字符串拼接,以後用eval去解析這個字符串。
args.push('arguments['+ i +']''); } obj.fn = this; // this就是調用_call的函數 // args = ['arguments[1]', 'arguments[2]', 'arguments[3]', ...]; // 此處執行eval時,會先調用args.toString(),而後執行eval時會從對應的arguments對象中取參數。 eval('obj.fn(' + args +')'); delete obj.fn; }; 複製代碼
運行以上代碼:
大功告成,能夠看出咱們實現了call方法!