亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

簡單了解JavaScript中常見的反模式

2024-05-06 16:52:35
字體:
來源:轉載
供稿:網友

前言

反模式 是指對反復出現的設計問題的常見的無力而低效的設計模式,俗話說就是重蹈覆轍。 這篇文章描述了 JavaScript 中常見的一些反模式,以及避免它們的辦法。

硬編碼

硬編碼(Hard-Coding)的字符串、數字、日期…… 所有能寫死的東西都會被人寫死。 這是一個婦孺皆知的反模式,同時也是最廣泛使用的反模式。 硬編碼中最為典型的大概是 平臺相關代碼(Platform-Related), 這是指特定的機器或環境下才可以正常運行的代碼, 可能是只在你的機器上可以運行,也可能是只在 Windows 下可以運行。

例如在 npm script 中寫死腳本路徑 /Users/harttle/bin/fis3, 原因可能是安裝一次非常困難,可能是為了避免重復安裝,也可能僅僅是因為這樣好使。 不管怎樣,這會讓所有同事來找你問“為什么我這里會報錯”。 解決辦法就是把它放到依賴管理,如果有特定的版本要求可以使用 package-lock,如果實在搞不定可以視為外部依賴可以放到本地配置文件并從版本控制(比如 Git) 移除。

例如在 cli 工具中寫死特殊文件夾 /tmp, ~/.cache,或者路徑分隔符 // 或 /。 這類字符串一般可以通過 Node.js 內置模塊(或其他運行時 API)來得到, 比如使用 os.homedir, os.tmpdir, path.sep 等。

重復代碼

重復代碼(Duplication)在業務代碼中尤為常見,初衷幾乎都是維護業務的穩定性。 舉個例子:在頁面 A 中需要一個漂亮的搜索框,而頁面 B 中恰好有一個。 這時程序員小哥面臨一個艱難的選擇(如果直接拷貝還會有些許感到不安的話):

  • 把 B 拷貝一份,改成 A 想要的樣子。
  • 把 B 中的搜索框重構到 C,B 和 A 引用這份代碼。

由于時間緊迫希望早點下班,或者由于改壞 B 需要承擔責任 (PM:讓你做 A 為啥 B 壞了?回答這個問題比較復雜,這里先跳過), 經過一番思考后決定采取方案 2。

至此整個故事進行地很自然也很順利,這大概就是重復代碼被廣泛使用的原因。 這個故事中有幾點需要質疑:

  • B 這么容易被改壞,說明 B 的作者 并未考慮復用。這時不應復用 B 的代碼,除非決定接手維護它。
  • B 改壞的責任不止程序員小哥:B 的作者是否有 編寫測試,測試人員是否 回歸測試 B 頁面?
  • 時間緊迫不必然導致反模式的出現,不可作為說服自己的原因。短期方案也存在優雅實現。

解決辦法就是:抽取 B 的代碼重新開發形成搜索框組件 C,在 A 頁面使用它。 同時提供給日后的小伙伴使用,包括敦促 B 的作者也遷移到 C 統一維護。

假 AMD

模塊化本意是指把軟件的各功能分離到獨立的模塊中,每個模塊包含完整的一個細分功能。 在 JavaScript 中則是特指把腳本切分為獨立上下文的,可復用的代碼單元。

由于 JavaScript 最初作為頁面腳本,存在很多引用全局作用域的語法,以及不少基于全局變量的實踐方式。 比如 jQuery 的 $, BOM 提供的 window,省略 var 來定義變量等。 AMD 是 JavaScript 社區較早的模塊化規范。這是一個君子協定,問題就出在這里。 有無數種方式寫出假的 AMD 模塊:

  • 沒有返回值。對,要的就是副作用。
  • define 后直接 require。對,要的就是立即執行。
  • 產生副作用。修改 window 或其他共享變量,比如其他模塊的靜態屬性。
  • 并發問題。依賴關系不明容易引發并發問題。

全局副作用的影響完全等同于全局變量,幾乎有全局變量的所有缺點: 執行邏輯不容易理解;隱式的耦合關系;編寫測試困難。下面來一個具體的例子:

// file: login.jsdefine('login', function () {fetch('/account/login').then(x => {window.login = true})})require(['login'])

這個 AMD 模塊與直接寫在一個 <script> 并無區別,準確地說是更不可控(requirejs 實現是異步的)。 也無法被其他模塊使用(比如要實現注銷后再次登錄),因為它沒返回任何接口。 此外這個模塊存在并發問題(Race Condition):使用 window.login 判斷是否登錄不靠譜。

解決辦法就是把它抽象為模塊,由外部來控制它的執行并獲得登錄結果。 在一個模塊化良好的項目中,所有狀態最終由 APP 入口產生, 模塊間共享的狀態都被抽取到最近的公共上級。

define(function () {return fetch('/account/login').then(() => true).catch(e => {console.error(e)return false}})

注釋膨脹

注釋的初衷是讓讀者更好的理解代碼意圖,但實踐中可能恰好相反。直接舉一個生活中的例子:

// 判斷手機百度版本大于 15if (navigator.userAgent.match(/Chrome:(/d+))[1] < 15) {// ...}

哈哈當你讀到這一段時,相信上述注釋已經成功地消耗了你的時間。 如果你第一次看到這樣的注釋可能會不可思議,但真實的項目中多數注釋都是這個狀態。 因為維護代碼不一定總是記得維護注釋,況且維護代碼的通常不止一人。 C 語言課程的后遺癥不止變量命名,“常寫注釋”也是一個很壞的教導。

解決辦法就是用清晰的邏輯來代替注釋,上述例子重新編寫后的代碼如下:

if (isHttpsSupported()) {// 通過函數抽取 + 命名,避免了添加注釋}function isHttpsSupported() {return navigator.userAgent.match(/Chrome:(/d+))[1] < 15}

函數體膨脹

“通常”認為函數體膨脹和全局變量都是算法課的后遺癥。 但復雜的業務和算法的場景確實不同,前者有更多的概念和操作需要解釋和整理。 整理業務邏輯最有效的手段莫過于變量命名和方法抽?。ó斎?,還要有相應的閉包或對象)。

但在真實的業務維護中,保持理性并不容易。 當你幾十次進入同一個文件添加業務邏輯后,你的函數一定會像懶婆娘的裹腳布一樣又臭又長:

function submitForm() {var username = $('form input#username').val()if (username === 'harttle') {username = 'God'} else {username = 'Mortal'if ($('form input#words').val().indexOf('harttle')) {username = 'prophet'}}$('form input#username').val(username)$('form').submit()}

這只是用來示例,十幾行還遠遠沒有達到“又臭又長”的地步。 但已經可以看到各種目的的修改讓 submitForm() 的職責遠不止提交一個表單。 一個可能的重構方案是這樣的:

function submitForm() {normalize()$('form').submit()}function normalize() {var username = parseUsername($('form input#username').val(),$('form input#words').val())$('form input#username').val(username)}function parseUsername(username, words)if (username === 'harttle') {return 'God'}return words.indexOf('harttle') ? 'prophet' : 'Mortal'}

在重構后的版本中,我們把原始輸入解析、數據歸一化等操作分離到了不同的函數, 這些抽離不僅讓 submitForm() 更容易理解,也讓進一步擴展業務更為方便。 比如在 normalize() 方法中對 input#password 字段也進行檢查, 比如新增一個 parseWords() 方法對 input#words 字段進行解析等等。

總結

常見的反模式還有許多,比如 == 和 != 的使用;擴展原生對象;還有 Promise 相關的 等等。

== 要提一下。這是語言的設計缺陷通常使用 Lint 工具來避免使用。與其他 Lint 錯誤不同的是一旦開始大面積使用后續改正十分困難(因為與 === 確實不等價)。因此強烈建議項目初始化時就添加 Lint。

這些反模式的流行背后都存在很有說服力的原因, 但反模式對可維護性和軟件的長期發展有著更為嚴重的影響。 按照 技術債務 的說法, 每次選擇捷徑都會產生隱含的代價,而這些代價在將來的某一時刻總要償還。 那些推遲的重構不僅會影響下一次變更,而且會像經濟債務一樣持續地疊加利息。

雖然不存在一種具體的考核方法來計算債務大小, 但可以肯定的是如果你能熟練使用 Harttle 博客中總結的各種反模式, 一定能達到每次代碼提交債務大于收益的境界。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩人体视频一二区| 欧美精品精品精品精品免费| 久久久亚洲精品视频| 欧美日韩国产va另类| 欧美日韩午夜剧场| 日韩欧美成人区| 国产视频精品在线| 色综合天天狠天天透天天伊人| 精品欧美aⅴ在线网站| 亚洲影院色无极综合| 国产精品白嫩初高中害羞小美女| 激情懂色av一区av二区av| 美日韩精品免费视频| 国产精品视频在线播放| 乱亲女秽乱长久久久| 日韩精品中文字幕视频在线| 亚洲欧美国产精品久久久久久久| 日本三级韩国三级久久| 中文日韩在线视频| 日韩欧美极品在线观看| 日韩在线观看免费高清完整版| 日韩av最新在线观看| 在线观看亚洲视频| 亚洲一区二区三区四区视频| 91精品国产高清| 国产精品成人av性教育| 91亚洲精品在线观看| 国产91在线高潮白浆在线观看| 欧美在线视频网站| 成人国产在线视频| 亚洲性线免费观看视频成熟| 夜夜嗨av一区二区三区四区| 久久久久国产精品一区| 精品国产乱码久久久久酒店| 色综合天天综合网国产成人网| 性欧美长视频免费观看不卡| 中文字幕少妇一区二区三区| 亚洲日韩中文字幕在线播放| 国产精品久久电影观看| 亚洲第一精品电影| 欧美肥臀大乳一区二区免费视频| 欧美激情网站在线观看| 色香阁99久久精品久久久| 青青草精品毛片| 日韩理论片久久| 国产69精品99久久久久久宅男| 亚洲白拍色综合图区| 久久精品91久久久久久再现| 欧美激情第三页| 欧美性xxxx在线播放| 久久男人av资源网站| 国产精品无码专区在线观看| 九九精品在线播放| 国产精品欧美久久久| 亚洲加勒比久久88色综合| 欧美最猛性xxxx| 成人午夜在线影院| 国产一区二区丝袜高跟鞋图片| 美女啪啪无遮挡免费久久网站| 中文字幕精品久久久久| 中文字幕最新精品| 亚洲自拍另类欧美丝袜| 亚洲综合最新在线| 欧美有码在线视频| 久久免费在线观看| 国产欧美日韩中文字幕| 国产精品2018| 国产成人精品一区二区三区| 日韩激情第一页| 91精品国产高清自在线看超| 日韩欧美亚洲成人| 亚洲欧美成人网| 亚洲美女精品久久| 在线播放日韩欧美| 成人在线激情视频| 久久99久久久久久久噜噜| 91亚洲精品视频| 久久久国产精品亚洲一区| 国产精品91久久久久久| 久久精品国产一区二区电影| 国产成人精品av在线| 亚洲激情成人网| 激情懂色av一区av二区av| 欧美精品国产精品日韩精品| 国产成人久久精品| 亚洲综合大片69999| 日韩欧美在线中文字幕| 日韩欧美亚洲国产一区| 亚洲成人激情在线观看| 国产一区二区三区在线播放免费观看| 日韩在线视频网站| 国产精品久久久久7777婷婷| 欧美电影在线免费观看网站| 91理论片午午论夜理片久久| 日韩成人av在线| 国产成人一区二区在线| 亚洲自拍偷拍视频| 亚洲精品欧美一区二区三区| 国产精品第一视频| 日韩a**中文字幕| 亚洲国产中文字幕久久网| 97超级碰在线看视频免费在线看| 国产精品7m视频| 亚洲国产成人在线视频| 欧美一级淫片videoshd| 久久精品亚洲热| 97在线观看免费高清| 日韩av在线网页| www国产91| 96pao国产成视频永久免费| 影音先锋欧美在线资源| 国产视频久久网| www.欧美视频| 一区二区成人av| 欧美日韩国产第一页| 国产99久久精品一区二区 夜夜躁日日躁| 91在线高清免费观看| 亚洲欧美日韩第一区| 国产精品欧美日韩一区二区| 一本色道久久88综合日韩精品| 欧美激情在线狂野欧美精品| 日韩乱码在线视频| 不卡av电影院| 国产精品久久久久一区二区| 中文日韩在线观看| 欧美日韩一区二区三区| 成人激情免费在线| 久久精品国产亚洲| 国产91精品高潮白浆喷水| 日韩av在线一区二区| 97久久国产精品| 美女av一区二区三区| 91香蕉亚洲精品| 精品美女久久久久久免费| 曰本色欧美视频在线| 久久久999精品免费| 成人深夜直播免费观看| 91精品国产综合久久香蕉的用户体验| 亚洲va男人天堂| 亚洲欧洲视频在线| 久久久女人电视剧免费播放下载| 欧美黄色免费网站| 高清一区二区三区四区五区| 国产亚洲精品久久久久久777| 国产亚洲欧美日韩美女| 亚洲精品第一国产综合精品| 91久久综合亚洲鲁鲁五月天| 亚洲已满18点击进入在线看片| 九九久久综合网站| 亚洲视频在线免费看| 久久国产精品久久久久久| 午夜精品久久久久久久男人的天堂| 亚洲美女性生活视频| 成人午夜在线影院| 欧美福利小视频| 久久91超碰青草是什么| 国产精品成人在线| 精品欧美一区二区三区| 日本19禁啪啪免费观看www| 成人免费网站在线| 久久精品国产亚洲精品2020| 国产精品第1页| 这里只有视频精品| 亚洲国产精品va在线|