成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

聊聊jQuery的反模式

CoderStudy / 2573人閱讀

摘要:如果我們認(rèn)為模式代表一個(gè)最佳的實(shí)踐,那么反模式將代表我們已經(jīng)學(xué)到一個(gè)教訓(xùn)。受啟發(fā)于的設(shè)計(jì)模式,在年的月的報(bào)告大會(huì)上首次提出反模式。參考鏈接反模式學(xué)用設(shè)計(jì)模式極客學(xué)院

如果我們認(rèn)為模式代表一個(gè)最佳的實(shí)踐,那么反模式將代表我們已經(jīng)學(xué)到一個(gè)教訓(xùn)。受啟發(fā)于Gof的《設(shè)計(jì)模式》,Andrew Koeing在1995年的11月的C++報(bào)告大會(huì)上首次提出反模式。在Koeing的報(bào)告中,反模式有著兩種觀念:

描述對(duì)于一個(gè)特殊的問題,提出了一個(gè)糟糕的解決方案,最終導(dǎo)致一個(gè)壞結(jié)果發(fā)生

描述如何擺脫上述解決方案并能提出一個(gè)好的解決方案

在如今這個(gè)前端發(fā)展如火如荼的時(shí)代,談及jq總是顯得非常的low,但實(shí)際上,在學(xué)校,在很多前端新人以及所謂“頁面仔 || 切圖工”之類的同行之間,jq的活力還是遠(yuǎn)超各種框架的時(shí)候,之所以想寫這樣一篇文章,一是因?yàn)橐姷搅松磉叺膉q爛代碼,二是因?yàn)槲以诎俣萰Query反模式的時(shí)候居然什么有價(jià)值的相關(guān)結(jié)果都沒有,所以覺得還是有必要聊聊的。

先從些簡(jiǎn)單的開始: 插入DOM節(jié)點(diǎn):
// 反模式
$.each(reallyLongArray, function(count, item) {
    var newLi = "
  • " + item + "
  • "; $("#ballers").append(newLi) }) // 更好的實(shí)踐 var frag = document.createDocumentFragment() $.each(reallyLongArray, function(count, item) { var newLi = "
  • " + item + "
  • "; frag.appendChild(newLi[0]) }) $("#ballers")[0].appendChild(frag) // 你也可以用字符串 var myHTML = "" $.each(reallyLongArray, function(count, item) { myHTML += "
  • " + item + "
  • "; }) $("#ballers").html(myHTML)

    DocumentFragment是瀏覽器為了減少DOM操作中的更新所使用的API,詳情請(qǐng)查閱MDN相關(guān)文檔。

    遵循DRY原則:
    if ($a.data("current") != "showing") {
        $a.stop()
    }
    if ($b.data("current") != "showing") {
        $b.stop()
    }
    if ($c.data("current") != "showing") {
        $c.stop()
    }
    
    // 用數(shù)組來保存不同的主體
    var elems = [$a, $b, $c]
    $.each(elems, function(k, v) {
        if (v.data("current") != "showing") {
            v.stop()
        }
    })

    用數(shù)組或?qū)ο髞肀4嬷貜?fù)片段的差異參數(shù)是一種很常見的方法。更多內(nèi)容可以參考常見的JavaScript設(shè)計(jì)模式中的“九、策略模式”

    地獄式回調(diào)(callback hell):
    $(document).ready(function() {
      $("#button").click(function() {
        $.get("http://api.github.com/repos/facebook/react/forks", function(data) {
          alert(data[0].owner.login)
        })
      })
    })
    
    // 以前有這么一種優(yōu)化的方法,使用對(duì)象字面量保存回調(diào)使其扁平化
    var cbContainer = {
      initApp: function() {
        $(document).ready(cbContainer.readCb)
      },
      readyCb: function() {
        $("#button").click(cbContainer.clickCb)
      },
      clickCb: function() {
        $.get("http://api.github.com/repos/facebook/react/forks", function(data) {
          cbContainer.getCb(data)
        })
      },
      getCb: function(data) {
        alert(data[0].owner.login)
      }
    }
    
    cbContainer.initApp()
    
    // 不過現(xiàn)在流行Promise
    
    var initApp = function() {
      return new Promise(function(resolve, reject) {
          $(document).ready(resolve)
      })
    }
    
    var readyCb = function() {
        return new Promise(function(resolve, reject) {
            $("#button").click(resolve)
        })
    }
    
    var clickCb = function() {
        return new Promise(function(resolve, reject) {
            $.get("http://api.github.com/repos/facebook/react/forks", function(data) {
          resolve(data)
        })
        })
    }
    
    var getCb = function(data) {
        alert(data[0].owner.login)
    }
    
    initApp()
      .then(readyCb)
      .then(clickCb)
      .then(getCb)
    

    用對(duì)象將回調(diào)扁平還好,Promise是什么鬼。不是比回調(diào)還惡心,好吧,示例確實(shí)是這樣。其實(shí)之所以用Promise除了將回調(diào)轉(zhuǎn)成鏈?zhǔn)秸{(diào)用以外,主要還是為了用它的reject函數(shù)獲取回調(diào)中的錯(cuò)誤。像示例這種一路resolve的,沒必要這么用。這里只是提一句。

    如果希望了解更多關(guān)于回調(diào)相關(guān)的知識(shí),可以看看Promise, generator, async與ES6這篇文章。

    重復(fù)查詢:
    $(document.body).append("
    ") $(".baaron").click(function() {}) // 更好的方式 $("
    ") .appendTo(document.body) .click(function() {})
    選擇器:

    對(duì)于jq的選擇器還有許多要注意的問題,因?yàn)閖q的選擇器是從右向左查詢,所以請(qǐng)記住一個(gè)“左輕右重”的原則:

    // 請(qǐng)看下面兩個(gè)選擇器
    $("div.foo .bar")
    $(".foo span.bar")        //右邊更明確一點(diǎn),會(huì)好不少
    
    // 當(dāng)左邊確實(shí)要比右邊明確的時(shí)候這么干
    $("#foo .bar")
    $("#foo").find(".bar")
    
    // 尤其避免使用通配符
    $("#foo > *")
    $("#foo").children()
    
    // 有些通配符是隱式的
    $(".foo :radio")
    $(".foo *:radio")        //和上邊一樣的
    $(".foo input:radio")    //改成這樣
    聊聊依賴:

    接下來,讓我們從優(yōu)化一段jq代碼開始,聊聊js中的依賴

    $("#button").click(function() {
        $.get("http://xxxx", function(data) {
            $("#page").html(data.abc)
        })
    })

    這段代碼有以下問題:

    click事件綁定的匿名函數(shù)難以重復(fù)利用,也很難測(cè)試

    click回調(diào)的匿名函數(shù)中的$是全局變量,ajax請(qǐng)求回調(diào)的匿名函數(shù)中的$("#page")也是用到了$這一全局變量,全局變量應(yīng)該是要避免的

    回調(diào)的問題前面也說過了,這里的回調(diào)還很清楚不至于說到地獄的程度

    現(xiàn)在我們把代碼這樣改寫:

    var downJSON = function() {
        $.get("http://xxxx", function(data) {
            $("#page").html(data.abc)
        })
    }
    
    $("#button").click(downJSON)

    現(xiàn)在匿名函數(shù)被我們拿出來了,可以重用了,但還是難以測(cè)試,且涵蓋全局變量。

    繼續(xù):

    var downJSON = function($, $el) {
        $.get("http://xxxx", function(data) {
            $el.html(data.abc)
        })
    }
    
    $("#button").click(function() {
        downJSON($, $("#page"))
    })

    這樣改寫以后,沒有了全局變量,函數(shù)已經(jīng)獨(dú)立出去。換一種說法就是,我們?nèi)コ撕瘮?shù)中的隱式依賴(前面例子中的函數(shù)要運(yùn)行需要全局變量$,但沒有從函數(shù)聲明中表現(xiàn)出來,我們稱其為隱式依賴),現(xiàn)在,函數(shù)執(zhí)行所需要的依賴被顯示聲明,使其具有更好的可控性。前端的依賴管理如今是一個(gè)很流行的話題,不過在這里就不廢話了。

    奇技淫巧:

    最后,對(duì)于幾種比較常見的寫法,我們也可以使用一些奇技淫巧,或能使代碼更短,或能使代碼更為易讀:

    簡(jiǎn)化條件語句:
    // 常見的寫法
    if(!data) {
        data = {}
    }
    
    // 簡(jiǎn)化
    data = data || {}

    你可能覺得這不值一提,但可能有些時(shí)候你寫著寫著就忽視了。比如,js數(shù)組去重的4個(gè)方法中的第二個(gè)方法,就可以應(yīng)用這個(gè)技巧:

    // 原來的代碼
    Array.prototype.unique2 = function()
    {
        var hashTable = {},res=[];                //n為hash表,r為臨時(shí)數(shù)組
        for(var i = 0; i < this.length; i++) {    //遍歷當(dāng)前數(shù)組
            if (!hashTable[this[i]]) {            //如果hash表中沒有當(dāng)前項(xiàng)
                res.push(this[i]);                //把當(dāng)前數(shù)組的當(dāng)前項(xiàng)push到臨時(shí)數(shù)組里面
                hashTable[this[i]] = true;        //存入hash表
            }
        }
        return res;
    }
    
    // 應(yīng)用此技巧
    Array.prototype.unique2 = function()
    {
        var hashTable = {}, res = []
        for(var i = 0; i < this.length; i++) {
            !hashTable[this[i]] ? res.push(this[i]) : null
            hashTable[this[i]] = hashTable[this[i]] || true
        }
        return res
    }

    寫成這樣也未必說是優(yōu)化,目測(cè)判斷邏輯還多了一個(gè)哈哈,但是嵌套少了一層,怎么說呢,自行決定吧。

    下面展示的一個(gè)技巧和上面這個(gè)也差不多:

    // 正常寫法
    if(type === "foo" || type === "bar") {}
    
    // 用對(duì)象有三種方法
    // 方法1
    if(({foo: 1, bar: 1})[type]) {}                    // type === "toString"可以繞過驗(yàn)證
    
    // 方法2
    if(type in ({foo: 1, bar: 1})) {}                // 和上一種等價(jià)但是慢點(diǎn)
    
    // 方法3
    if(({foo: 1, bar: 1}).hasOwnProperty(type)) {}    // 最嚴(yán)密,也最慢
    
    // 用正則
    if(/^(foo|bar)$/.test(type)) {}

    這種技巧的話,使用與否同樣是自己決定。很多有意思的東西,都是自己想著玩的,有些情況,我們倒不如好好寫成switch - case,都看的懂,也挺清晰。

    總結(jié)兩句,雖說jQuery庫和新式的框架相比老了,但我覺得它在DOM操作上真的做到了一個(gè)極致。我相信很長(zhǎng)一段時(shí)間,前端開發(fā)人員入門,還是要從它開始的。個(gè)人認(rèn)為jq不適應(yīng)時(shí)代的原因,是因?yàn)樗旧硪矁H僅限于DOM操作,沒有其他限制,以至于當(dāng)應(yīng)用復(fù)雜時(shí),你完全控制不住你的頁面。當(dāng)你用上流行的框架,按照他們的Best Practice去組織代碼,我想你剛剛開始的時(shí)候,一定會(huì)懷念jQuery這個(gè)溺愛你的老朋友的。

    參考鏈接:

    反模式 - 學(xué)用 JavaScript 設(shè)計(jì)模式 - 極客學(xué)院
    jQuery Anti-Patterns for Performance & Compression
    Patterns of Large-Scale JavaScript Applications

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78818.html

    相關(guān)文章

    • php資料集

      摘要:簡(jiǎn)單字符串緩存實(shí)戰(zhàn)完整實(shí)戰(zhàn)種設(shè)計(jì)模式設(shè)計(jì)模式是面向?qū)ο蟮淖罴褜?shí)踐成為專業(yè)程序員路上用到的各種優(yōu)秀資料神器及框架成為一名專業(yè)程序員的道路上,需要堅(jiān)持練習(xí)學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 微型新聞系統(tǒng)的開發(fā)(PHP 5.4 + MySQL 5.5) 微型新聞系統(tǒng)的開發(fā)(PHP 5.4 + MySQL 5.5) 九個(gè)很有用的 PHP 代碼 php 代碼 國(guó)內(nèi)值得關(guān)注的...

      RobinQu 評(píng)論0 收藏0
    • 聊聊技術(shù)寫作的個(gè)人體會(huì)

      摘要:由此看來,的官方文檔就把當(dāng)成內(nèi)置函數(shù),這個(gè)認(rèn)識(shí)錯(cuò)誤是有根源的等到的時(shí)候,官方把錯(cuò)誤改正過來了,然而改得并不徹底。使用進(jìn)行判斷,結(jié)果為的才是內(nèi)置函數(shù)。 showImg(https://segmentfault.com/img/bVbm3Bu?w=5184&h=3456);有群友問過,是什么原因使我開始寫技術(shù)公眾號(hào),又是什么動(dòng)力讓我堅(jiān)持寫的。 在我看來,寫作是一件不能敷衍的事,通過寫作來學(xué)...

      madthumb 評(píng)論0 收藏0
    • 從命令式到響應(yīng)式 (二)

      摘要:知識(shí)點(diǎn)回顧,上次主要說了函數(shù)式和面向?qū)ο螅钍胶晚憫?yīng)式,系統(tǒng)和系統(tǒng)的差別。以內(nèi)聯(lián)的形式使用。響應(yīng)式中的設(shè)計(jì)模式觀察者模式在這種模式中,一個(gè)對(duì)象維持一系列依賴于它的對(duì)象,將有關(guān)的狀態(tài)變更自動(dòng)的通知給它們。 知識(shí)點(diǎn)回顧,上次主要說了函數(shù)式和面向?qū)ο?,命令式和響?yīng)式,push 系統(tǒng)和 pull 系統(tǒng)的差別。在編程范式,風(fēng)格之外,設(shè)計(jì)模式也是在程序設(shè)計(jì)中時(shí)時(shí)刻刻都在使用的東西,今天主要就討論...

      DataPipeline 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <