2016-03-29 108 views
0

我遇到this stackoverflow question關於遞歸平展JS數組。這裏是公認的答案:遞歸Function.prototype.apply概念理解

function flatten() { 
    var flat = []; 
    for (var i = 0; i < arguments.length; i++) { 
     if (arguments[i] instanceof Array) { 
      flat.push.apply(flat, flatten.apply(this, arguments[i])); 
     } else { 
      flat.push(arguments[i]); 
     } 
    } 
    return flat; 
} 

flatten([[1], 2, [3, 4]]); // returns [1, 2, 3, 4] 

我無法理解如何flat.push.apply(...)flatten.apply(...)工作。

據我所知,該函數只有在數組中的項爲時纔會退出。我也明白Function.prototype.apply()允許你使用一個參數數組來調用一個函數。

我不明白的是,爲什麼你使用flat.push...如果flat將被設置爲[]在每個函數迭代。另外,設置flat作爲this上下文有什麼意義?

有人可以幫忙解釋flat.push.apply(flat, flatten.apply(this, arguments[i]));的執行是如何工作的嗎?

+0

「* if'flat'將在每個函數迭代中設置爲'[]'*」 - 它不是迭代,它是遞歸。每個調用都有自己的局部變量。 – Bergi

+0

「*設置'flat'作爲這個上下文有什麼意義?*」 - 這是'push' *方法的上下文,它是將被推入的數組。就像您經常在'flat' *上調用'flat.push(...)'*一樣。 – Bergi

+0

'flat'每次迭代都沒有設置,它只在循環之前設置一次。 – dandavis

回答

2

他安全地使用了flat.push,因爲push實際上每次都在不同的數組上調用。每次執行flatten時,它都會創建一個新的數組,並在flat變量中存儲不同的參考,因此每個遞歸都與不同的flat數組相關聯。

設置flat作爲this上下文提供了一個名爲push的數組。嘗試將其設置爲null,由於非法操作,您可能會獲得TypeError - 嘗試撥打push,null

現在爲更復雜的部分。 push接受要添加到數組的參數列表,對嗎?但是,有時候不方便逐一提供這些參數,尤其是,如果您不知道,有多少個push應該接收,就像在您的情況中一樣,陣列的扁平尺寸會有所不同。

這就是爲什麼該代碼的作者經由apply調用push與數組引用作爲第二個參數 - 它是flatten.apply(this, arguments[i])返回值 - 參照由該時間只包含數字陣列。該陣列的每個數字被推送到flat,因爲apply調用push並通過參數傳遞給該陣列的整個數字列表push

flatten.apply(this, arguments[i])部分由於類似的原因被調用apply - 它利用了arguments(每個函數都有類似數組的對象)來輕鬆地處理函數參數。在apply的第一個參數中移交this在這裏並不重要,因爲thisflattenthis指向代碼示例中的全局對象)中沒有用處。