摘要:匿名函數訪問和則是典型的閉包的應用,并沒有把函數存儲在任何典型的數據結構中。另外,每添加一個函數,就會增加一層嵌套,調用深度過深的話性能開銷也會比較大,使用的時候要進行權衡。
本文同步自我的 GitHub
假設現在有這樣一個場景,一個下單頁面,需要根據特定的條件去計算購物車商品的總價,特定的條件包括但不限于選中的商品、是否選擇折扣、是否疊加套餐和運費險等。這時我們通常需要寫一個用來計算總價的函數getTotalPrice(),然而,函數的參數是不確定的,同時函數內的邏輯也會根據參數的不同而有所變化,最簡單的方法是在函數內部對參數進行判斷:
如果參數分開傳入,那么函數的偽代碼可能寫成這樣:
function getTotalPrice(selectedGoods, isDiscounted, pacakge) { var totalPrice = 0; if (selectedGoods) { totalPrice = ...; if (isDiscounted) { // 計算折扣 if (package) {...} } else if (pacakge) {...} return totalPrice; } else { return 0; } }
有的人可能覺得將參數分開傳入函數看起來比較亂,會習慣用一個參數對象包裹一下,在函數內部再對這個對象進行解析。看起來確實有一定的改進,但我認為并沒有什么本質上的區別。
現在希望能夠做到針對不同參數的情況,在函數內部只書寫針對特定個數參數的邏輯,不去寫亂七八糟的if-else語句或是參數對象的解析邏輯。同時,這些函數共用一個函數名,并且該邏輯可擴展,即可以隨時根據需要,添加函數。
通過對需求的分析,應該會有這樣的一個工具函數:
var methods = {}; addFunction(methods, "getTotalPrice", function(selectedGoods) {...}); addFunction(methods, "getTotalPrice", function(selectedGoods, isDiscounted) {...}); addFunction(methods, "getTotalPrice", function(selectedGoods, isDiscounted, pacakge) {...});
這樣,在添加每個函數的時候,只需要寫針對特定參數的邏輯,調用getTotalPrice的時候,自動根據參數長度實際調用不同的函數。
很容易想到要對不同的函數進行緩存,同時為了公用同一個函數名,緩存的函數需要匿名,進而聯想到閉包可以保存局部變量的引用的特性,以下是addFunction的實現:
function addFunction(object, funcName, fn) { var oldFunc = object[funcName]; object[funcName] = function() { return (fn.length === arguments.length ? fn : oldFunc).apply(this, arguments); } }
在addFunction方法的作用域中,保存了原方法的引用,通過對參數長度的比較確定最終執行哪個匿名函數,要注意的是一個函數的length屬性表示改函數接受的形參數量,而arguments.length表示實際傳入的參數數量。匿名函數訪問oldFunc和fn則是典型的閉包的應用,并沒有把函數存儲在任何典型的數據結構中。
addFunction(methods, "getTotalPrice", function(total) { console.log(total); }); addFunction(methods, "getTotalPrice", function(total, discount) { console.log(total * discount); }); methods.getTotalPrice(20); // 輸出20 methods.getTotalPrice(20, 0.8); // 輸出16
要注意的是,這種方式只能針對不同數量的參數,不能判斷參數的名稱或類型,如果要判斷的話,勢必會犧牲addFunction方法的通用性。另外,每添加一個函數,就會增加一層嵌套,調用深度過深的話性能開銷也會比較大,使用的時候要進行權衡。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86140.html
摘要:我們就有了組訓練數據我們將其進化前的值和進化后的值畫在一個二維坐標圖上橫軸為進化前的值,那每個藍色的點都代表一只寶可夢現在我們有了和,但是我們還需要一個函數來將它們連接起來,這個函數就是接下來要講的第三步中間藍色的塊就是誤差函數。 前言 如果遇到排版問題,請點擊 閱讀原文 這個課程是來自于 YouTube 上 NTU 李宏毅老師的視頻課程,老師的課講得非常有趣,通過引入 Pokémon...
摘要:友盟朋新宇在開場演講中,友盟朋新宇表示,在數據化智能化的今天,進化是一種態度,更是一種選擇。在朋新宇看來,數據加工有三大過程過程第一層是采集,友盟技術平臺每天能夠支撐萬億級的采集能力。 10月16日,友盟+主辦的2018UBDC全域大數據峰會在北京舉辦。峰會以DI·進化為主題——8小時,10余家黑科技企業,超40位國內頂級專家主題分享,近3500位數據從業者共同見證,旨在讓更多企業會用...
摘要:生成器用于定義生成器函數只要存在該函數必定是一個生成器調用該函數返回一個生成器讓一個生成器前進使用使一個生成器前進到下一個語句處,并將產出值作為其返回值。 前言 這篇文章大部分來自 David Beazley 在 PyCon 2014 的 PPT 《Generators: The Final Frontier》。這個PPT很長而且非常燒腦,建議在閱讀前應了解 Python 的生成器與攜...
摘要:和的得分均未超過右遺傳算法在也表現得很好。深度遺傳算法成功演化了有著萬自由參數的網絡,這是通過一個傳統的進化算法演化的較大的神經網絡。 Uber 涉及領域廣泛,其中許多領域都可以利用機器學習改進其運作。開發包括神經進化在內的各種有力的學習方法將幫助 Uber 發展更安全、更可靠的運輸方案。遺傳算法——訓練深度學習網絡的有力競爭者我們驚訝地發現,通過使用我們發明的一種新技術來高效演化 DNN,...
閱讀 3577·2021-10-11 10:59
閱讀 1595·2021-09-29 09:35
閱讀 2264·2021-09-26 09:46
閱讀 3776·2021-09-10 10:50
閱讀 957·2019-08-29 12:17
閱讀 826·2019-08-26 13:40
閱讀 2440·2019-08-26 11:44
閱讀 2107·2019-08-26 11:22