2014-03-30 39 views
2

我正在閱讀pallet.js的源代碼,並且遇到了這個問題。爲什麼這個javascript是必需的?

var ret = (function(proto) { 
    return { 
    slice: function(arr, opt_begin, opt_end) { 
     return proto.slice.apply(arr, proto.slice.call(arguments, 1)); 
    }, 
    extend: function(arr, arr2) { 
     proto.push.apply(arr, arr2); 
    } 
    }; 
})(Array.prototype); 
var slice = ret.slice; 
var extend = ret.extend; 

爲什麼這是必要的?爲什麼他們能不能簡單地寫:

var slice = function(arr,opt_begin,opt_end) { 
    return Array.prototype.slice.apply(arr,[opt_begin,opt_end])); 
} 
var extend = function(arr,arr2) { 
    return Array.prototype.push.apply(arr,arr2); 
} 

編輯1:

在回答重複的問題。我不認爲這是重複的,但是這個問題肯定會解決我的問題。所以這是一個優化。但是每個人都不會被評估一次嗎?那麼對於兩個函數調用,是否真的有重大改進?

另外,如果我們擔心性能,爲什麼我們調用proto.slice.call(arguments,1)而不是手動構建兩個元素的數組[opt_begin,opt_end],是切片更快?

+1

可能重複[是解引用變量有用封閉?](http://stackoverflow.com/questions/8288664/is-a-closure-for-dereferencing-variables-useful) – Bergi

回答

0

我不能確定那是什麼代碼背後的最初理由(只有作者知道),但我可以看到一些不同之處:

  • proto是一個封閉的,在局部變量,而不是Array是一個全球性的。有足夠智能的Javascript引擎可以優化訪問權限,因爲proto從不改變,因此甚至可以通過價值獲取,而不是參考。 proto.slice可能會比Array.prototype.slice更快,因爲需要更少的查找。

  • 通過opt_beginopt_end因爲undefined與通過它們不一樣。被調用的函數可以知道一個參數是否被傳遞,並且恰好是undefined,或者如果它沒有被傳遞。使用proto.slice.call(arguments, 1)可確保僅當參數實際傳遞給閉包時纔將參數傳遞給slice

+0

啊!調用slice而不是自己定義它現在變得非常有意義。 但是'Array.prototype.slice' vs'proto.slice'保存了一次查找(不知道這是否是正確的單詞),因爲我們首先必須先傳遞'Array.prototype'作爲參數。然後我們調用'ret.slice'和'ret.extend'它們本身就是兩個查找...所以這段代碼運行得慢嗎? – retrohacker

+1

創建閉包的查找只完成一次。在您的示例中,每次調用該函數時都會執行該操作。 – 6502

+0

最後的問題......如果我們將原生變量作爲局部變量,那麼在這個測試中我的邏輯有什麼問題嗎? http://jsperf.com/palette-js-perf-test – retrohacker

3

因爲語法太酷了。另外,您可以通過告訴自己它更乾燥來合理使用它。您不必輸入Array.prototype兩次。

+0

它贏得了」無論如何,關閉會添加1個屬性查找,從而爲您節省一個屬性查找。 –