国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

聊聊jQuery的反模式

CoderStudy / 2566人閱讀

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

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

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

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

在如今這個前端發(fā)展如火如荼的時代,談及jq總是顯得非常的low,但實際上,在學校,在很多前端新人以及所謂“頁面仔 || 切圖工”之類的同行之間,jq的活力還是遠超各種框架的時候,之所以想寫這樣一篇文章,一是因為見到了身邊的jq爛代碼,二是因為我在百度jQuery反模式的時候居然什么有價值的相關(guān)結(jié)果都沒有,所以覺得還是有必要聊聊的。

先從些簡單的開始: 插入DOM節(jié)點:
// 反模式
$.each(reallyLongArray, function(count, item) {
    var newLi = "
  • " + item + "
  • "; $("#ballers").append(newLi) }) // 更好的實踐 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,詳情請查閱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嬷貜推蔚牟町悈?shù)是一種很常見的方法。更多內(nèi)容可以參考常見的JavaScript設計模式中的“九、策略模式”

    地獄式回調(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)化的方法,使用對象字面量保存回調(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)
    

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

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

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

    對于jq的選擇器還有許多要注意的問題,因為jq的選擇器是從右向左查詢,所以請記住一個“左輕右重”的原則:

    // 請看下面兩個選擇器
    $("div.foo .bar")
    $(".foo span.bar")        //右邊更明確一點,會好不少
    
    // 當左邊確實要比右邊明確的時候這么干
    $("#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ù)難以重復利用,也很難測試

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

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

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

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

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

    繼續(xù):

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

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

    奇技淫巧:

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

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

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

    // 原來的代碼
    Array.prototype.unique2 = function()
    {
        var hashTable = {},res=[];                //n為hash表,r為臨時數(shù)組
        for(var i = 0; i < this.length; i++) {    //遍歷當前數(shù)組
            if (!hashTable[this[i]]) {            //如果hash表中沒有當前項
                res.push(this[i]);                //把當前數(shù)組的當前項push到臨時數(shù)組里面
                hashTable[this[i]] = true;        //存入hash表
            }
        }
        return res;
    }
    
    // 應用此技巧
    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)化,目測判斷邏輯還多了一個哈哈,但是嵌套少了一層,怎么說呢,自行決定吧。

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

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

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

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

    參考鏈接:

    反模式 - 學用 JavaScript 設計模式 - 極客學院
    jQuery Anti-Patterns for Performance & Compression
    Patterns of Large-Scale JavaScript Applications

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

    轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/78818.html

    相關(guān)文章

    • php資料集

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

      RobinQu 評論0 收藏0
    • 聊聊技術(shù)寫作的個人體會

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

      madthumb 評論0 收藏0
    • 從命令式到響應式 (二)

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

      DataPipeline 評論0 收藏0

    發(fā)表評論

    0條評論

    最新活動
    閱讀需要支付1元查看
    <