不要使用匿名函數

来源:http://www.cnblogs.com/fejs/archive/2017/06/29/7096145.html
-Advertisement-
Play Games

作為函數式編程語言,函數在JavaScript中的重要地位和巨大作用你盡可想象。但在其提供巨大便利的同時,也不可避免的帶來巨大的問題。 匿名函數則更是一把雙刃劍,它讓函數式編程語言更加完美,也讓代碼更加難於閱讀。你應該知道匿名函數是以犧牲語義化為巨大代價的。 如果一個函數沒有名字,它可能無關緊要,在 ...


作為函數式編程語言,函數在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能夠從容應付。

想都不要想過度設計這個詞,大部分人沒有這個能力,不必杞人憂天。

 

你從一開始就是高級架構師只不過兼職寫代碼

你可以清楚的看到,大量使用命名函數讓代碼結構非常清晰,任何人都能容易的獨懂主流程,任何人都可以容易的去實現每一個命名函數,要實現什麼已經清楚的寫在了函數名上了。

這些命名函數就像房屋的骨架,再往上堆疊就是一棟樓的骨架,你見過建築設計師自己砌牆澆水泥的嗎?寫代碼也一樣,用函數堆疊成骨架,至於每個函數怎麼實現,請幫我實現(在你初學的時候就是請你自己幫你自己實現)。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 針對 “js判斷字元串是否為JSON格式” 這個問題,在網上查了許多資料,都沒找到自己想要的答案。 但是看到這個帖子《js判斷字元串是否為JSON格式》後,突然靈光一閃,想到一種很簡單的解決方案。 如果你對這個方法有異議,歡迎留言探討。 解決方案 分析 就像之前的帖子所說,只是單純的用JSON ...
  • 2017高德地圖API WEB開發(key申請,地圖搭建)簡約教程 ...
  • 前言 一個vue的demo 源碼說明 項目目錄說明 . |-- config // 項目開發環境配置 | |-- index.js // 項目打包部署配置 |-- src // 源碼目錄 | |-- components // 公共組件 | |-- header.vue // 頁面頭部公共組件 | ...
  • nodejs的package.json定義了一個模塊,包括其依賴關係的一個簡單的JSON文件,該文件可以包含多個不同的指令來告訴Node包管理器如何處理模塊。 dependencies則表示此模塊依賴的模塊和版本,其中常常可以看到類似 ^1.2.0 或 ~1.2.0 這樣的版本範圍指示。 首先,一個 ...
  • 距離上次寫博客有很長時間了,這段時間中也一直想堅持寫博客,但是遲遲未動,一方面是因為剛換工作並適應新的環境導致工作比較忙碌,一直沒有抽出時間來,其實說白了就是給自己的懶惰找藉口,但是本人在園子里也有一段時間了,也一直堅持關註園子里的大神們的文章,感觸頗多。最近也一直計劃堅持寫博客,並把工作中遇到問題 ...
  • 1.if條件語句相關 對於 if 語句括弧里的表達式,ECMAScript 會自動調用 Boolean()轉型函數將這個表達式的結果轉換成一個布爾值。如果值為 true,執行後面的一條語句,否則不執行。 2.arguments相關 通過arguments 對象的length屬性,來智能的判斷有多少參 ...
  • DOM 一個參數 兩個參數 對象 css() 獲取指定樣式屬性值 設置屬性值 設置多個屬性值 attr 獲取指定屬性值 設置屬性值 設置多個屬性值 Prop 獲取指定屬性值 設置屬性值 設置多個屬性值 attr與prop區別 attr用於自定義屬性值 prop自帶屬性 刪除屬性 removeAttr ...
  • <!DOCTYPE html><html lang="en"><head><meta name="viewport" content="width=device-width,user-scalable=no" /><meta charset="UTF-8"><script type="text/ja ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...