新聞中心
隨著 JavaScript 本身的完善,越來越多的人開始喜歡使用原生 JavaScript 開發(fā)代替各種庫,其中不少人發(fā)出了用原生 JavaScript 代替 jQuery 的聲音。這并不是什么壞事,但也不見得就是好事。如果你真的想把 jQuery 從前端依賴庫中移除掉,我建議你慎重考慮。

淮濱網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。成都創(chuàng)新互聯(lián)從2013年開始到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。
首先 jQuery 是一個第三方庫。庫存在的價(jià)值之一在于它能極大地簡化開發(fā)。一般情況下,第三方庫都是由原生語言特性和基礎(chǔ) API 庫實(shí)現(xiàn)的。因此,理論上來說,任何庫第三方庫都是可以用原生語言特性代替的,問題在于是否值得?
jQuery 的作用
引用一段 jQuery 官網(wǎng)的話:
jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers.
這一段話很謙虛的介紹了 jQuery 在處理 DOM 和跨瀏覽器方面做出的貢獻(xiàn)。而事實(shí)上,這也正是我們選用 jQuery 的主要原因,并順帶使用了它帶來的一些工具,比如數(shù)組工具,Deferred 等。
對于我來說,最常用的功能包括
在 DOM 樹中進(jìn)行查詢
修改 DOM 樹及 DOM 相關(guān)操作
事件處理
Ajax
Deferred 和 Promise
對象和數(shù)組處理
還有一個一直在用卻很難在列清單時想到的——跨瀏覽器
到底是誰在替代誰?
上面提到的所有功能都能用原生代碼來實(shí)現(xiàn)。從本質(zhì)上來說,jQuery 就是用來代替原生實(shí)現(xiàn),以達(dá)到減少代碼,增強(qiáng)可讀性的目的的——所以,到底是用 jQuery 代替原生代碼,還是用原生代碼代替 jQuery?這個先后因果關(guān)系可否搞明白?
我看到說用 querySelectorAll() 代替 $() 的時候,不禁在想,用 jQuery 一個字符就能解決的,為什么要寫十六個字符?大部分瀏覽器是有實(shí)現(xiàn) $(),但是寫原生代碼的時候你會考慮 $() 的瀏覽器兼容性嗎?jQuery 已經(jīng)考慮了!
我看到一大堆創(chuàng)建 DOM 結(jié)構(gòu)的原生 JavaScript 代碼的時候,不禁在想,用 jQuery 只需要一個方法鏈就解決了,我甚至可以用和 HTML 結(jié)構(gòu)類似的代碼(包含縮進(jìn)),比如
這段代碼用 document.createElement() 來實(shí)現(xiàn)完全沒有問題,只不過代碼量要大得多,而且會出現(xiàn)大量重復(fù)(或類似)的代碼。當(dāng)然是可以把這些重復(fù)代碼提取出來寫成函數(shù)的……不過 jQuery 已經(jīng)做了。
注,拼 HTML 的方法實(shí)在弱爆了,既容易出錯,又不易閱讀。如果有 ES6 的字符串模板之后,用它來寫 HTML 也是個不錯的主意。
就 DOM 操作這一部分來說,jQuery 仍然是一個非常好用的工具。這是 jQuery 替代了原生 JavaScript,以前如此,現(xiàn)在仍然如此。
沒落的 jQuery 工具函數(shù)
jQuery 2006 年被發(fā)明出來的時候,還沒有 ES5(2011年6月發(fā)布)。即使在 ES5 發(fā)布之后很長一段時間里,也不是所有瀏覽器都支持。因此在這一時期,除 DOM 操作外,jQuery 的巨大貢獻(xiàn)在于解決跨瀏覽器的問題,以及提供了方便的對象和數(shù)組操作工具,比如 each()、 index() 和 filter 等。
如今 ECMAScript 剛剛發(fā)布了 2017 的標(biāo)準(zhǔn),瀏覽器標(biāo)準(zhǔn)混亂的問題也已經(jīng)得到了很好的解決,前端界還出現(xiàn)了 Babel 這樣的轉(zhuǎn)譯工具和 TypeScript 之類的新語言。所以現(xiàn)在大家都盡可放心的使用各種新的語言特性,哪怕 ECMAScript 的相關(guān)標(biāo)準(zhǔn)還在制定中。在這一時期,jQuery 提供的大量工具方法都已經(jīng)有了原生替代品——在使用上差別不大的情況下,確實(shí)寧愿用原生實(shí)現(xiàn)。
事實(shí)上,jQuery 也在極盡可能地采用原生實(shí)現(xiàn),以提高執(zhí)行效率。jQuery 沒有放棄這些已有原生實(shí)現(xiàn)的工具函數(shù)/方法,主要還是因?yàn)橄蛳录嫒?,以及一如既往的提供瀏覽器兼容性——畢竟不是每一個使用 jQuery 的開發(fā)者都會使用轉(zhuǎn)譯工具。
那么,對于 JavaScript 開發(fā)者而言,jQuery 確實(shí)有很多工具方法可以被原生 JavaScript 函數(shù)/方法替代。比如
$.parseJSON() 可以用 JSON.parse() 替代,而且 JSON.stringify() 還彌補(bǔ)了 jQuery 沒有 $.toJSON() 的不足;
$.extend() 的部分功能可以由 Object.assign() 替代`
$.fn 的一些數(shù)據(jù)處理工具方法,比如 each()、 index() 等都可以用 Array.prototype 中相應(yīng)的工具方法替代,比如 forEach()、 indexOf() 等。
$.Deferred() 和 jQuery Promise 在某些情況下可以用原生 Promise 替代。它們在沒有 ES6 之前也算是個不錯的 Promise 實(shí)現(xiàn)。
......
$.fn 就是 jQuery.prototype,也就是 jQuery 對象的原型。所以在其上定義的方法就是 jQuery 對象的方法。
這些工具方法在原生 JavaScript 中已經(jīng)逐漸補(bǔ)充完善,但它們?nèi)匀恢皇窃谀承┣闆r下可以被替代……因?yàn)?jQuery 對象是一個特有的數(shù)據(jù)結(jié)構(gòu),針對 jQuery 自身創(chuàng)建的工具方法在作用于 jQuery 對象的時候會有一些針對性的實(shí)現(xiàn)——既然 DOM 操作仍然不能把 jQuery 拋開,那這些方法也就不可能被完全替換掉。
jQuery 與原生 JavaScript 的結(jié)合
有時候需要用 jQuery,有時候不需要用,該如何分辨?
jQuery 的優(yōu)勢在于它的 DOM 處理、Ajax,以及跨瀏覽器。如果在項(xiàng)目中引入 jQuery,多半是因?yàn)閷@些功能的需求。而對于不操作 DOM,也不需要考慮跨瀏覽器(比如用于轉(zhuǎn)譯工具)的部分,則考慮盡可能的用原生 JavaScript 實(shí)現(xiàn)。
如此以來,一定會存在 jQuery 和原生 JavaScript 的交集,那么,就不得不說說需要注意的地方。
jQuery 對象實(shí)現(xiàn)了部分?jǐn)?shù)組功能的偽數(shù)組
首先要注意的一點(diǎn),就是 jQuery 對象是一個偽數(shù)組,它是對原生數(shù)組或偽數(shù)組(比如 DOM 節(jié)點(diǎn)列表)的封裝。
如果要獲得某個元素,可以用 [] 運(yùn)算符或 get(index) 方法;如果要獲得包含所有元素的數(shù)組,可以使用 toArray() 方法,或者通過 ES6 中引入的 Array.from() 來轉(zhuǎn)換。
注意 each/map 和 forEach/map 回調(diào)函數(shù)的參數(shù)順序
jQuery 定義在 $.fn 上的 each() 和 map() 方法與定義在 Array.prototype 上的原生方法 forEach() 和 map() 對應(yīng),它們的參數(shù)都是回調(diào)函數(shù),但它們的回調(diào)函數(shù)定義有一些細(xì)節(jié)上的差別。
$.fn.each() 的回調(diào)定義如下:
Function(Integerindex,Elementelement)
回調(diào)的第一個參數(shù)是數(shù)組元素所在的位置(序號,從 0 開始),第二個參數(shù)是元素本身。
而 Array.prototype.forEach() 的回調(diào)定義是
Function(currentValue,index,array)
回調(diào)的第一個參數(shù)是數(shù)組元素本身,第二個參數(shù)才是元素所有的位置(序號)。而且這個回調(diào)有第三個參數(shù),即整個數(shù)組的引用。
請?zhí)貏e注意這兩個回調(diào)定義的第一個參數(shù)和第二個參數(shù),所表示的意義正好交換,這在混用 jQuery 和原生代碼的時候很容易發(fā)生失誤。
對于 $.fn.map() 和 Array.prototype.map() 的回調(diào)也是如此,而且由于這兩個方法同名,發(fā)生失誤的概率會更大。
注意 each()/map() 中的 this
$.fn.each() 和 $.fn.map() 回調(diào)中經(jīng)常會使用 this,這個 this 指向的就是當(dāng)前數(shù)組元素。正是因?yàn)橛羞@個便利,所以 jQuery 在定義回請販時候沒有把元素本身作為第一個參數(shù),而是把序號作為第一個參數(shù)。
不過 ES6 帶來了箭頭函數(shù)。箭頭函數(shù)最常見的作用就是用于回調(diào)。箭頭函數(shù)中的 this 與箭頭函數(shù)定義的上下文相關(guān),而不像普通函數(shù)中的 this 是與調(diào)用者相關(guān)。
現(xiàn)在問題來了,如果把箭頭函數(shù)作為 $.fn.each() 或 $.fn.map() 的回調(diào),需要特別注意 this 的使用——箭頭函數(shù)中的 this 不再是元素本身。鑒于這個問題,建議若非必要,仍然使用函數(shù)表達(dá)式作為 $.fn.each() 和 $.fn.map() 的回調(diào),以保持原有的 jQuery 編程習(xí)慣。實(shí)在需要使用箭頭函數(shù)來引用上下文 this 的情況下,千萬記得用其回調(diào)定義的第二個參數(shù)作為元素引用,而不是 this。
$.fn.map() 返回的并不是數(shù)組
與 Array.prototype.map() 不同, $.fn.map() 返回的不是數(shù)組,而是 jQuery 對象,是偽數(shù)組。如果需要得到原生數(shù)組,可以采用 toArray() 或 Array.from() 輸出。
jQuery Promise
jQuery 是通過 $.Deferred() 來實(shí)現(xiàn)的 Promise 功能。在 ES6 以前,如果引用了 jQuery,基本上不需要再專門引用一個 Promise 庫,jQuery 已經(jīng)實(shí)現(xiàn)了 Promise 的基本功能。
不過 jQuery Promise 雖然實(shí)現(xiàn)了 then(),卻沒有實(shí)現(xiàn) catch(),所以它不能兼容原生的 Promise,不過用于 co 或者 ES2017 的 async/await 毫無壓力。
雖然 jQuery 的 Promise 沒有 catch(),但是提供了 fail 事件處理,這個事件在 Deferred reject() 的時候觸發(fā)。相應(yīng)的還有 done 事件,在 Deferred resovle() 的時候觸發(fā),以及 always 事件,不論什么情況都會觸發(fā)。
與一次性的 then() 不同,事件可以注冊多個處理函數(shù),在事件觸發(fā)的時候,相應(yīng)的處理函數(shù)會依次執(zhí)行。另外,事件不具備傳遞性,所以 fail() 不能在寫在 then() 鏈的最后。
結(jié)語
總的來說,在大量操作 DOM 的前端代碼中使用 jQuery 可以帶來極大的便利,也使 DOM 操作的相關(guān)代碼更易讀。另一方面,原生 JavaScript 帶來的新特性確實(shí)可以替代 jQuery 的部分工具函數(shù)/方法,以降低項(xiàng)目對 jQuery 的依賴程序。
jQuery 和原生 JavaScript 應(yīng)該是共生關(guān)系,而不是互斥關(guān)系。應(yīng)該在合適的時候選用合適的方法,而不是那么絕對的非要用誰代替誰。
網(wǎng)頁標(biāo)題:程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?
網(wǎng)站路徑:http://www.5511xx.com/article/dpieoip.html


咨詢
建站咨詢
