匿名函數是一把雙面刃,有利也有弊
作為函數式程式語言,函數在JavaScript中的重要地位和巨大作用你盡可想像。但在其提供巨大便利的同時,也不可避免的帶來巨大的問題。
匿名函數則更是一把雙面刃,它讓函數式程式語言更加完美,也讓程式碼更難於閱讀。你應該知道匿名函數是以犧牲語意化為巨大代價的。
如果一個函數沒有名字,它可能無關緊要,在大部分場景中它都會失去意義。函數的名字跟你的名字,你朋友的名字,你家小寵物的名字一樣,是重要關鍵的,否則你寫它幹嘛。
即使在看起來最沒有必要的位置使用命名函數也有巨大價值
你可能隨手就能列舉許多場景來證明匿名函數的便利性,不可否認有些場景無疑是有些道理的,但大多數人以此為起點,以善小而不為。例如
Array.some, Array.forEach, String.replace
這樣的例子能舉出不少,我們也可以理直氣壯的說他們不需要使用命名函數,使用匿名函數更方便,而且大家都是這麼做的。但別忘了,some,forEach,replace本身已經有寬泛的語意了。但仍然可以更近一步:
1.Array.some, 廣泛的語義是找出數組中是否有一些,但究竟有一些什麼呢?
2.Array.forEach, 廣泛的語義是遍歷,Array提供無數的函數用於遍歷,你為什麼選擇forEach, 而不是map,every等等?
3.String.replace, 廣泛的語意是替換,但究竟是將什麼替換成什麼呢?
程式碼是寫給人看的,
1.能不能不要讓我去讀你的程式碼猜或推理出來你要從陣列中找出一些什麼,是不是有整數,是不是有空值?
2.能不能直接透過函數名稱告訴我你遍歷這個陣列是想幹嘛?
3.能不能直接透過函數名稱告訴我你想將什麼替換成什麼?
舉個簡單的例子,找出價格數組中是否存在整數價格。 isInteger可能是已經有的公共函數,如果沒有的話,經過你就有了。簡潔易讀,在閱讀主流程的時候,有些程式碼是不需要閱讀的,isInteger就是這樣一些程式碼,萬一有錯呢? isInteger是可測易測的,如果你不放心,就對它執行單元測試。你可能已經注意到,一個小小的改變,有一部分程式碼已經具有可測性了。即使這裡不是一個公用函數,寫成命名函數也更整潔更可測。
var isAnyInteger = priceArr.some(Common.isInteger.bind(Common));
這些都是非常極端的被認為是可以直接寫匿名函數的例子,但很明顯可以看到,他們也可以作為命名函數的邊界處理,也就是都寫命名函數百利而無一害,只會更好。
再簡單的程式碼也要區分架構和實作
另外一個重災區是then 函數,匿名函數的程式碼不能更醜陋,即使大家都這麼寫,你也應該明白,你不能這麼寫,正確的姿勢應該寫成這樣, 以展示訂單為例:
/* * name : getOrder * description : 获取订单数据 */function getOrder() {//{{{var url = 'https://www.qunar.com/getOrder';//假如收集参数比较费劲,应该用一个函数专门去收集参数var params = getOrderParams();//假如参数体比较庞大,应该先将其赋予一个变量var params = { orderNo:'248663058'};//无论如何,现将参数赋予变量你都将获得在这里打印变量方便调试的便利console.log('getOrder url & params:', url, params);return $.post(url, params); }//}}}/* * name : renderOrder * description : 拿订单,拿到就在页面上展示出来,拿不到就告诉用户为什么没拿到 */function renderOrder() {//{{{//高级函数,只安排工作,不自己实现//getOrder() 对该函数来说是不可见的,它要的只是订单数据,偷得抢的都可以 getOrder().then(render, remindUser); }//}}}function render() {//{{{}//}}}function remindUser() {//{{{}//}}}
當然,你可能覺得renderOrder 就是雞肋,跟只拿工資不干活的領導簡直一毛一樣,把then寫在$.post 後面不就行了?
不行,如果有一天獲取訂單既可以從本地獲取,又可以從本地快取獲取,那麼getOrder就升級為次高級函數,它管理兩個函數getOrderFromServer, getOrderFromCache
如果在取得訂單之前或之後還要做一些事情,那之後renderOrder能夠從容應付。
想都不要想過度設計這個詞,大部分人沒有這個能力,不必杞人憂天。
你從一開始就是高階架構師只不過兼職寫程式碼
你可以清楚的看到,大量使用命名函數讓程式碼結構非常清晰,任何人都能容易的獨懂主流程,任何人都可以容易的去實現每一個命名函數,要實現什麼已經清楚的寫在了函數名上了。
這些命名函數就像房屋的骨架,再往上堆疊就是一棟大樓的骨架,你有看過建築設計師自己砌牆澆水泥的嗎?寫程式碼也是一樣,用函數堆疊成骨架,至於每個函數怎麼實現,請幫我實現(在你初學的時候就是請你自己幫你自己實現)。
以上是匿名函數是一把雙面刃,有利也有弊的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MetaMask(中文也叫小狐狸錢包)是一款免費的、廣受好評的加密錢包軟體。目前,BTCC已支援綁定MetaMask錢包,綁定後可使用MetaMask錢包進行快速登錄,儲值、買幣等,且首次綁定還可獲得20USDT體驗金。在BTCCMetaMask錢包教學中,我們將詳細介紹如何註冊和使用MetaMask,以及如何在BTCC綁定並使用小狐狸錢包。 MetaMask錢包是什麼? MetaMask小狐狸錢包擁有超過3,000萬用戶,是當今最受歡迎的加密貨幣錢包之一。它可免費使用,可作為擴充功能安裝在網絡

Go語言提供了兩種動態函數創建技術:closures和反射。 closures允許存取閉包作用域內的變量,而反射可使用FuncOf函數建立新函數。這些技術在自訂HTTP路由器、實現高度可自訂的系統和建置可插拔的元件方面非常有用。

在C++函數命名中,考慮參數順序至關重要,可提高可讀性、減少錯誤並促進重構。常見的參數順序約定包括:動作-物件、物件-動作、語意意義和遵循標準函式庫。最佳順序取決於函數目的、參數類型、潛在混淆和語言慣例。

1. SUM函數,用於對一列或一組單元格中的數字進行求和,例如:=SUM(A1:J10)。 2、AVERAGE函數,用於計算一列或一組儲存格中的數字的平均值,例如:=AVERAGE(A1:A10)。 3.COUNT函數,用於計算一列或一組單元格中的數字或文字的數量,例如:=COUNT(A1:A10)4、IF函數,用於根據指定的條件進行邏輯判斷,並返回相應的結果。

C++函數中預設參數的優點包括簡化呼叫、增強可讀性、避免錯誤。缺點是限制靈活性、命名限制。可變參數的優點包括無限彈性、動態綁定。缺點包括複雜性更高、隱式型別轉換、除錯困難。

C++中的函數傳回參考類型的好處包括:效能提升:引用傳遞避免了物件複製,從而節省了記憶體和時間。直接修改:呼叫方可以直接修改傳回的參考對象,而無需重新賦值。程式碼簡潔:引用傳遞簡化了程式碼,無需額外的賦值操作。

自訂PHP函數與預定義函數的差異在於:作用域:自訂函數僅限於其定義範圍,而預定義函數可在整個腳本中存取。定義方式:自訂函數使用function關鍵字定義,而預先定義函數則由PHP核心定義。參數傳遞:自訂函數接收參數,而預先定義函數可能不需要參數。擴充性:自訂函數可以根據需要創建,而預定義函數是內建的且無法修改。
