成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

編寫更加穩定、可讀性強的JavaScript代碼

開發 前端
每個人都有自己的編程風 格,也無可避免的要去感受別人的編程風格——修改別人的代碼?!毙薷膭e人的代碼”對于我們來說的一件很痛苦的事情。因為有些代碼并不是那么容易閱讀、可維 護的,讓另一個人來修改別人的代碼,或許最終只會修改一個變量,調整一個函數的調用時機,卻需要花上1個小時甚至更多的時間來閱讀、縷清別人的代碼。本文 一步步帶你重構一段獲取位置的”組件”——提升你的javascript代碼的可讀性和穩定性。

每個人都有自己的編程風 格,也無可避免的要去感受別人的編程風格——修改別人的代碼。”修改別人的代碼”對于我們來說的一件很痛苦的事情。因為有些代碼并不是那么容易閱讀、可維 護的,讓另一個人來修改別人的代碼,或許最終只會修改一個變量,調整一個函數的調用時機,卻需要花上1個小時甚至更多的時間來閱讀、縷清別人的代碼。本文 一步步帶你重構一段獲取位置的”組件”——提升你的javascript代碼的可讀性和穩定性。

  本文內容如下:

  • 分離你的javascript代碼

  • 函數不應該過分依賴外部環境

  • 語義化和復用

  • 組件應該關注邏輯,行為只是封裝

  • 形成自己的風格的代碼

 分離你的javascript代碼

  下面一段代碼演示了難以閱讀/修改的代碼:

  1. (function (window, namespace) { 
  2.     var $ = window.jQuery; 
  3.     window[namespace] = function (targetId, textId) { //一個嘗試復用的獲取位置的"組件" var $target = $('#' + targetId),//按鈕 $text = $('#' + textId);//顯示文本 $target.on('click', function () { $text.html('獲取中'); var data = '北京市';//balabala很多邏輯,偽代碼,獲取得到位置中 
  4.             if (data) { 
  5.                 $text.html(data); 
  6.             } else 
  7.                 $text.html('獲取失敗'); 
  8.         }); 
  9.     } 
  10. })(window, 'linkFly'); 

  這一段代碼,我們暫且認可它已經構成一個”組件”。
上面的代碼就是典型的一個方法搞定所有事情,一旦填充上內部的邏輯就會變得生活不能自理,而一旦增加需求,例如獲取位置返回的數據格式需要加工,那么就要去里面尋找處理數據的代碼然后修改。

  我們分離一下邏輯,得到代碼如下:

  1. (function (window, namespace) { 
  2.     var $ = window.jQuery, 
  3.         $target, 
  4.         $text, 
  5.         states= ['獲取中''獲取失敗']; 
  6.     function done(address) {//獲取位置成功 
  7.         $text.html(address); 
  8.     } 
  9.     function fail() { 
  10.         $text.html(states[1]); 
  11.     } 
  12.     function checkData(data) { 
  13.         //檢查位置信息是否正確 
  14.         return !!data; 
  15.     } 
  16.     function loadPosition() { 
  17.         var data = '北京市';//獲取位置中 
  18.         if (checkData(data)) { 
  19.             done(data); 
  20.         } else 
  21.             fail(); 
  22.     } 
  23.     var init = function () { 
  24.         $target.on('click'function () { 
  25.             $text.html(states[0]); 
  26.             loadPosition(); 
  27.         }); 
  28.     }; 
  29.     window[namespace] = function (targetId, textId) { 
  30.         $target = $('#' + targetId); 
  31.         $text = $('#' + textId); 
  32.         initData(); 
  33.         setData(); 
  34.     } 
  35. })(window, 'linkFly'); 

 函數不應該過分依賴外部環境

  上面的代碼中,我們已經把整個組件,切割成了各種函數(注意這里我說的是函數,不是方法),這里常出現一個新的問題:函數過分依賴不可控的變量。

  變量$target和$text身為環境中的全局變量,從組件初始化便賦值,而我們切割后的代碼大多數的操作方法都依賴$text,尤其是$text和done()、fail()之間曖昧的關系,一旦$text相關的結構、邏輯改變,那么我們的代碼將會進行不小的改動。

  和頁面/DOM相關的都是不可信賴的(例如$target和$text),一旦頁面結構發生改變,它的行為很大程度上也會隨之改變。而函數也不應該依賴外部的環境。
在不可控的變量上,我們應該解開函數和依賴變量上的關系,讓函數變得更加專注自己區域的邏輯,更加的純粹。簡單的說:函數所依賴的外部變量,都應該通過參數傳遞到函數內部。
新的代碼如下:

  1. (function (window, namespace) { 
  2.     var $ = window.jQuery; 
  3.     //檢查位置信息是否正確 
  4.     function checkData(data) { 
  5.         return !!data; 
  6.     } 
  7.     //獲取位置中 
  8.     function loadPosition(done, fail) { 
  9.         var data = '北京市';//獲取位置中 
  10.         if (checkData(data)) { 
  11.             done(data); 
  12.         } else 
  13.             fail(); 
  14.     } 
  15.     window[namespace] = function (targetId, textId) { 
  16.        var  $target = $('#' + targetId), 
  17.             $text = $('#' + textId); 
  18.         var states = ['獲取中''獲取失敗']; 
  19.         $target.on('click', function () { 
  20.             $text.html(states[0]); 
  21.             loadPosition(function (address) {//獲取位置成功 
  22.                 $text.html(address); 
  23.             }, function () {//獲取位置失敗 
  24.                 $text.html(states[1]); 
  25.             }); 
  26.         }); 
  27.     } 
  28. })(window, 'linkFly'); 

 語義化和復用

  變量states是一個數組,它描述的行為難以閱讀,每次看到states[0]都有一種分分鐘想捏死原作者的沖動,因為我們總是要記住變量states的值,在代碼上,我們應該盡可能讓它可以很好的被閱讀。

  另外,上面的代碼中$text.html就是典型的代碼重復,我們再一次的修改代碼,請注意這一次修改的代碼中,我們所抽離的changeStateText()的代碼位置,它并沒有被提升到上一層環境中(也就是整個大閉包的環境)。

  1. (function (window, namespace) { 
  2.     var $ = window.jQuery; 
  3.     function checkData(data) { 
  4.         return !!data; 
  5.     } 
  6.     function loadPosition(done, fail) { 
  7.         var data = '北京市';//獲取位置中 
  8.         if (checkData(data)) { 
  9.             done(data); 
  10.         } else 
  11.             fail(); 
  12.     } 
  13.     window[namespace] = function (targetId, textId) { 
  14.         var $target = $('#' + targetId), 
  15.             $text = $('#' + textId), 
  16.             changeEnum = { LOADING: '獲取中', FAIL: '獲取失敗' }, 
  17.             changeStateText = function (text) { 
  18.                 $text.html(text); 
  19.             }; 
  20.         $target.on('click'function () { 
  21.             changeStateText(changeEnum.LOADING); 
  22.             loadPosition(function (address) { 
  23.                 changeStateText(address); 
  24.             }, function () { 
  25.                 changeStateText(changeEnum.FAIL); 
  26.             }); 
  27.         }); 
  28.     } 
  29. })(window, 'linkFly'); 

  提及語義化,我們必須要知道當前整個代碼的邏輯和語義:

  在這整個組件中,所有的函數模塊可以分為:工具和工具提供者。

  上一層環境(整個大閉包)在我們的業務中扮演著工具的身份,它的任務是締造一套和獲取位置邏輯相關的工具,而在window[namespace])函數中,則是工具提供者的身份,它是唯一的入口,負責提供組件完整的業務給工具的使用者。
這里的$text.html()在邏輯上并不屬于工具,而是屬于工具提供者使用工具后所得到的反饋,所以changeStateText()函數置于工具提供者window[namespace]()中。

 組件應該關注邏輯,行為只是封裝

  到此為止,我們分離了函數,并讓這個組件擁有了良好的語義。但這時候來了新的需求:當沒有獲取到位置的時候,需要進行一些其他的操作。這時候會發現,我們需要window[namespace]()上加上新的參數。

  當我們加上新的參數之后,又被告知新的需求:當獲取位置失敗了之后,需要修改一些信息,然后再次嘗試獲取位置信息。

  不過幸好,我們的代碼已經把大部分的邏輯抽離到了工具提供者中了,對整個工具的邏輯影響并不大。

  同時我們再看看代碼就會發現我們的組件除了工具提供者之外,沒有方法(依賴在對象上的函數)。也就是說,我們的組件并沒有對象。

  我見過很多人的代碼總是喜歡打造工具提供者,而忽略了工具的本質。迎合上面的增加的需求,那么我們的工具提供者將會變得越來越重,這時候我們應該思考到:是不是應該把工具提供出去?

  讓我們回到最初的需求——僅僅只是一個獲取位置的組件,沒錯,它的核心業務就是獲取位置——它不應該被組件化。它的本質應該是個工具對象,而不應該和頁面相關,我們從一開始就不應該關注頁面上的變化,讓我們重構代碼如下:

  1. (function (window, namespace) { 
  2.     var Gps = { 
  3.         load: function (fone, fail) { 
  4.             var data = '北京市';//獲取位置偽代碼 
  5.             this.check(data) ? 
  6.                 done(data, Gps.state.OK) : 
  7.                 fail(Gps.state.FAIL); 
  8.         }, 
  9.         check: function (data) { 
  10.             return !!data; 
  11.         }, 
  12.         state: { OK: 1, FAIL: 0 } 
  13.     }; 
  14.     window[namespace] = Gps; 
  15. })(window, 'Gps'); 

  在這里,我們直接捏死了工具提供者,我們直接將工具提供給外面的工具使用者,讓工具使用者直接使用我們的工具,這里的代碼無關狀態、無關頁面。

  至此,重構完成。

 形成自己風格的代碼

  之所以講這個是因為大家都有自己的編程風格。有些人的編程風格就是開篇那種代碼的…

  我覺得形成自己的編程風格,是建立在良好代碼的和結構/語義上的。否則只會讓你的代碼變得越來越難讀,越來越難寫。

  ****

  單var和多var

  我個人是喜歡單var風格的,不過我覺得代碼還是盡可能在使用某一方法/函數使用前進行var,有時候甚至于為了單var而變得喪心病狂:由于我又過分的喜愛函數表達式聲明,函數表達式聲明并不會在var語句中執行,于是偶爾會出現這種邊聲明邊執行的代碼,為了不教壞小朋友就不貼代碼了(我不會告訴你們其實是我找不到了)。

  對象屬性的屏蔽

  下面的代碼演示了兩種對象的構建,后一種通過閉包把內部屬性隱藏,同樣,兩種方法都實現了無new化,我個人…是不喜歡看見很多this的..但還是推薦前者。

  1. (function () { 
  2.     //第一種,曝露了_name屬性 
  3.     var Demo = function () { 
  4.         if (!(this instanceof Demo)) 
  5.             return new Demo(); 
  6.         this._name = 'linkFly'
  7.     }; 
  8.     Demo.prototype.getName = function () { 
  9.         return this._name; 
  10.     } 
  11.  
  12.     //第二種,多一層閉包意味內存消耗更大,但是屏蔽了_name屬性 
  13.     var Demo = function () { 
  14.         var name = 'linkFly'
  15.         return { 
  16.             getName: function () { 
  17.                 return name; 
  18.             } 
  19.         } 
  20.     } 
  21. }); 

  巧用變量置頂[hoisting]

  巧用函數聲明的變量置頂特性意味著處女座心態的你放棄單var,但卻可以讓你的函數在代碼結構上十分清晰,例如下面的代碼:

 

  1. (function () { 
  2.     var names = []; 
  3.     return function (name) { 
  4.         addName(name); 
  5.     } 
  6.     function addName(name) { 
  7.         if (!~names.indexOf(name))//如果存在則不添加 
  8.             names.push(name); 
  9.         console.log(names);// ["linkFly"] 
  10.     } 
  11. }())('linkFly'); 
  12.  
  13.   if和&& 

  這種代碼,在幾個群里都見過討論:

  1. (function () { 
  2.     var key = 'linkFly'
  3.         cache = { 'linkFly''http://www.cnblogs.com/silin6/' }, 
  4.         value; 
  5.     //&&到底 
  6.     key && cache && cache[key] && (value = cache[key]); 
  7.     //來個if 
  8.     if (key && cache && cache[key]) 
  9.         value = cache[key]; 
  10. })(); 

  大概就想到這么些了,我突然發現我不太推薦的代碼,都是我寫的代碼,囧。如果各位也還有更多有趣的代碼,希望各位看官能掏出來讓小弟見識見識。

責任編輯:王雪燕 來源: linkFly的博客
相關推薦

2024-04-23 08:01:20

面向對象C 語言代碼

2021-10-09 10:24:53

Java 代碼可讀性

2019-12-03 09:32:32

JavaScript代碼開發

2021-04-01 16:43:05

代碼可讀性開發

2017-10-30 15:22:29

代碼可讀性技巧

2022-08-23 14:57:43

Python技巧函數

2022-08-29 00:37:53

Python技巧代碼

2020-11-08 14:36:27

pandas數據分析pipe()

2025-05-12 10:00:00

JavaScript代碼編碼

2024-08-02 16:20:06

2014-07-28 10:28:25

程序員

2014-07-29 09:55:33

程序員代碼可讀性

2024-10-11 06:00:00

Python代碼編程

2024-10-07 10:00:00

Python代碼編碼

2022-11-04 11:18:16

代碼優化可讀性

2024-01-31 08:04:43

PygmentsPython

2023-10-30 18:05:55

Python類型

2013-03-22 16:43:03

可讀代碼代碼的藝術代碼編寫

2012-07-11 10:51:37

編程

2021-01-26 09:18:27

Shell腳本網站
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一区二区三区 | 老牛影视av一区二区在线观看 | www.天天操.com | 亚洲午夜电影 | 亚洲 精品 综合 精品 自拍 | 国产午夜精品一区二区三区 | 搞黄网站在线观看 | 成人在线免费电影 | 欧美日韩国产在线观看 | 日本在线中文 | 中文字幕二区 | 欧美激情综合五月色丁香小说 | 久久一区二区三区四区 | 国产欧美二区 | 成人区精品一区二区婷婷 | 91人人澡人人爽 | 国产一级特黄aaa大片评分 | 黄视频网址 | www.色综合 | 国产一区二 | 久热国产在线 | 91视视频在线观看入口直接观看 | 欧美视频二区 | 波多野吉衣在线播放 | 久久一区二区三区电影 | 日韩成人在线播放 | 成人午夜免费在线视频 | 日本不卡视频 | 中文字幕在线一区二区三区 | 欧美日韩亚洲一区二区 | 日韩在线一区二区 | 天天射网站 | 欧美一级黄视频 | 日韩免费一区二区 | 日韩电影免费在线观看中文字幕 | 九九综合九九 | 伊人激情综合网 | 一级大片免费 | 国产 日韩 欧美 中文 在线播放 | 欧美 视频 | 天天干狠狠操 |