自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?

新聞 前端
隨著 JavaScript 本身的完善,越來(lái)越多的人開(kāi)始喜歡使用原生 JavaScript 開(kāi)發(fā)代替各種庫(kù),其中不少人發(fā)出了用原生 JavaScript 代替 jQuery 的聲音。

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

[[209101]]

首先 jQuery 是一個(gè)第三方庫(kù)。庫(kù)存在的價(jià)值之一在于它能極大地簡(jiǎn)化開(kāi)發(fā)。一般情況下,第三方庫(kù)都是由原生語(yǔ)言特性和基礎(chǔ) API 庫(kù)實(shí)現(xiàn)的。因此,理論上來(lái)說(shuō),任何庫(kù)第三方庫(kù)都是可以用原生語(yǔ)言特性代替的,問(wèn)題在于是否值得?

jQuery 的作用

引用一段 jQuery 官網(wǎng)的話(huà):

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.

這一段話(huà)很謙虛的介紹了 jQuery 在處理 DOM 和跨瀏覽器方面做出的貢獻(xiàn)。而事實(shí)上,這也正是我們選用 jQuery 的主要原因,并順帶使用了它帶來(lái)的一些工具,比如數(shù)組工具,Deferred 等。

對(duì)于我來(lái)說(shuō),最常用的功能包括

  • 在 DOM 樹(shù)中進(jìn)行查詢(xún)

  • 修改 DOM 樹(shù)及 DOM 相關(guān)操作

  • 事件處理

  • Ajax

  • Deferred 和 Promise

  • 對(duì)象和數(shù)組處理

  • 還有一個(gè)一直在用卻很難在列清單時(shí)想到的——跨瀏覽器

到底是誰(shuí)在替代誰(shuí)?

上面提到的所有功能都能用原生代碼來(lái)實(shí)現(xiàn)。從本質(zhì)上來(lái)說(shuō),jQuery 就是用來(lái)代替原生實(shí)現(xiàn),以達(dá)到減少代碼,增強(qiáng)可讀性的目的的——所以,到底是用 jQuery 代替原生代碼,還是用原生代碼代替 jQuery?這個(gè)先后因果關(guān)系可否搞明白?

我看到說(shuō)用 querySelectorAll() 代替 $() 的時(shí)候,不禁在想,用 jQuery 一個(gè)字符就能解決的,為什么要寫(xiě)十六個(gè)字符?大部分瀏覽器是有實(shí)現(xiàn) $(),但是寫(xiě)原生代碼的時(shí)候你會(huì)考慮 $() 的瀏覽器兼容性嗎?jQuery 已經(jīng)考慮了!

我看到一大堆創(chuàng)建 DOM 結(jié)構(gòu)的原生 JavaScript 代碼的時(shí)候,不禁在想,用 jQuery 只需要一個(gè)方法鏈就解決了,我甚至可以用和 HTML 結(jié)構(gòu)類(lèi)似的代碼(包含縮進(jìn)),比如

程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?

這段代碼用 document.createElement() 來(lái)實(shí)現(xiàn)完全沒(méi)有問(wèn)題,只不過(guò)代碼量要大得多,而且會(huì)出現(xiàn)大量重復(fù)(或類(lèi)似)的代碼。當(dāng)然是可以把這些重復(fù)代碼提取出來(lái)寫(xiě)成函數(shù)的……不過(guò) jQuery 已經(jīng)做了。

注,拼 HTML 的方法實(shí)在弱爆了,既容易出錯(cuò),又不易閱讀。如果有 ES6 的字符串模板之后,用它來(lái)寫(xiě) HTML 也是個(gè)不錯(cuò)的主意。

就 DOM 操作這一部分來(lái)說(shuō),jQuery 仍然是一個(gè)非常好用的工具。這是 jQuery 替代了原生 JavaScript,以前如此,現(xiàn)在仍然如此。

沒(méi)落的 jQuery 工具函數(shù)

jQuery 2006 年被發(fā)明出來(lái)的時(shí)候,還沒(méi)有 ES5(2011年6月發(fā)布)。即使在 ES5 發(fā)布之后很長(zhǎng)一段時(shí)間里,也不是所有瀏覽器都支持。因此在這一時(shí)期,除 DOM 操作外,jQuery 的巨大貢獻(xiàn)在于解決跨瀏覽器的問(wèn)題,以及提供了方便的對(duì)象和數(shù)組操作工具,比如 each()、 index() 和 filter 等。

如今 ECMAScript 剛剛發(fā)布了 2017 的標(biāo)準(zhǔn),瀏覽器標(biāo)準(zhǔn)混亂的問(wèn)題也已經(jīng)得到了很好的解決,前端界還出現(xiàn)了 Babel 這樣的轉(zhuǎn)譯工具和 TypeScript 之類(lèi)的新語(yǔ)言。所以現(xiàn)在大家都盡可放心的使用各種新的語(yǔ)言特性,哪怕 ECMAScript 的相關(guān)標(biāo)準(zhǔn)還在制定中。在這一時(shí)期,jQuery 提供的大量工具方法都已經(jīng)有了原生替代品——在使用上差別不大的情況下,確實(shí)寧愿用原生實(shí)現(xiàn)。

事實(shí)上,jQuery 也在極盡可能地采用原生實(shí)現(xiàn),以提高執(zhí)行效率。jQuery 沒(méi)有放棄這些已有原生實(shí)現(xiàn)的工具函數(shù)/方法,主要還是因?yàn)橄蛳录嫒荩约耙蝗缂韧奶峁g覽器兼容性——畢竟不是每一個(gè)使用 jQuery 的開(kāi)發(fā)者都會(huì)使用轉(zhuǎn)譯工具。

那么,對(duì)于 JavaScript 開(kāi)發(fā)者而言,jQuery 確實(shí)有很多工具方法可以被原生 JavaScript 函數(shù)/方法替代。比如

  • $.parseJSON() 可以用 JSON.parse() 替代,而且 JSON.stringify() 還彌補(bǔ)了 jQuery 沒(méi)有 $.toJSON() 的不足;

  • $.extend() 的部分功能可以由 Object.assign() 替代`

  • $.fn 的一些數(shù)據(jù)處理工具方法,比如 each()、 index() 等都可以用 Array.prototype 中相應(yīng)的工具方法替代,比如 forEach()、 indexOf() 等。

  • $.Deferred() 和 jQuery Promise 在某些情況下可以用原生 Promise 替代。它們?cè)跊](méi)有 ES6 之前也算是個(gè)不錯(cuò)的 Promise 實(shí)現(xiàn)。

  • ......

$.fn 就是 jQuery.prototype,也就是 jQuery 對(duì)象的原型。所以在其上定義的方法就是 jQuery 對(duì)象的方法。

這些工具方法在原生 JavaScript 中已經(jīng)逐漸補(bǔ)充完善,但它們?nèi)匀恢皇窃谀承┣闆r下可以被替代……因?yàn)?jQuery 對(duì)象是一個(gè)特有的數(shù)據(jù)結(jié)構(gòu),針對(duì) jQuery 自身創(chuàng)建的工具方法在作用于 jQuery 對(duì)象的時(shí)候會(huì)有一些針對(duì)性的實(shí)現(xiàn)——既然 DOM 操作仍然不能把 jQuery 拋開(kāi),那這些方法也就不可能被完全替換掉。

jQuery 與原生 JavaScript 的結(jié)合

有時(shí)候需要用 jQuery,有時(shí)候不需要用,該如何分辨?

jQuery 的優(yōu)勢(shì)在于它的 DOM 處理、Ajax,以及跨瀏覽器。如果在項(xiàng)目中引入 jQuery,多半是因?yàn)閷?duì)這些功能的需求。而對(duì)于不操作 DOM,也不需要考慮跨瀏覽器(比如用于轉(zhuǎn)譯工具)的部分,則考慮盡可能的用原生 JavaScript 實(shí)現(xiàn)。

如此以來(lái),一定會(huì)存在 jQuery 和原生 JavaScript 的交集,那么,就不得不說(shuō)說(shuō)需要注意的地方。

jQuery 對(duì)象實(shí)現(xiàn)了部分?jǐn)?shù)組功能的偽數(shù)組

首先要注意的一點(diǎn),就是 jQuery 對(duì)象是一個(gè)偽數(shù)組,它是對(duì)原生數(shù)組或偽數(shù)組(比如 DOM 節(jié)點(diǎn)列表)的封裝。

如果要獲得某個(gè)元素,可以用 [] 運(yùn)算符或 get(index) 方法;如果要獲得包含所有元素的數(shù)組,可以使用 toArray() 方法,或者通過(guò) ES6 中引入的 Array.from() 來(lái)轉(zhuǎn)換。

程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?

注意 each/map 和 forEach/map 回調(diào)函數(shù)的參數(shù)順序

jQuery 定義在 $.fn 上的 each() 和 map() 方法與定義在 Array.prototype 上的原生方法 forEach() 和 map() 對(duì)應(yīng),它們的參數(shù)都是回調(diào)函數(shù),但它們的回調(diào)函數(shù)定義有一些細(xì)節(jié)上的差別。

$.fn.each() 的回調(diào)定義如下:

Function(Integerindex,Elementelement)

回調(diào)的第一個(gè)參數(shù)是數(shù)組元素所在的位置(序號(hào),從 0 開(kāi)始),第二個(gè)參數(shù)是元素本身。

而 Array.prototype.forEach() 的回調(diào)定義是

Function(currentValue,index,array)

回調(diào)的第一個(gè)參數(shù)是數(shù)組元素本身,第二個(gè)參數(shù)才是元素所有的位置(序號(hào))。而且這個(gè)回調(diào)有第三個(gè)參數(shù),即整個(gè)數(shù)組的引用。

請(qǐng)?zhí)貏e注意這兩個(gè)回調(diào)定義的第一個(gè)參數(shù)和第二個(gè)參數(shù),所表示的意義正好交換,這在混用 jQuery 和原生代碼的時(shí)候很容易發(fā)生失誤。

對(duì)于 $.fn.map() 和 Array.prototype.map() 的回調(diào)也是如此,而且由于這兩個(gè)方法同名,發(fā)生失誤的概率會(huì)更大。

注意 each()/map() 中的 this

$.fn.each() 和 $.fn.map() 回調(diào)中經(jīng)常會(huì)使用 this,這個(gè) this 指向的就是當(dāng)前數(shù)組元素。正是因?yàn)橛羞@個(gè)便利,所以 jQuery 在定義回請(qǐng)販時(shí)候沒(méi)有把元素本身作為第一個(gè)參數(shù),而是把序號(hào)作為第一個(gè)參數(shù)。

不過(guò) ES6 帶來(lái)了箭頭函數(shù)。箭頭函數(shù)最常見(jiàn)的作用就是用于回調(diào)。箭頭函數(shù)中的 this 與箭頭函數(shù)定義的上下文相關(guān),而不像普通函數(shù)中的 this 是與調(diào)用者相關(guān)。

現(xiàn)在問(wèn)題來(lái)了,如果把箭頭函數(shù)作為 $.fn.each() 或 $.fn.map() 的回調(diào),需要特別注意 this 的使用——箭頭函數(shù)中的 this 不再是元素本身。鑒于這個(gè)問(wèn)題,建議若非必要,仍然使用函數(shù)表達(dá)式作為 $.fn.each() 和 $.fn.map() 的回調(diào),以保持原有的 jQuery 編程習(xí)慣。實(shí)在需要使用箭頭函數(shù)來(lái)引用上下文 this 的情況下,千萬(wàn)記得用其回調(diào)定義的第二個(gè)參數(shù)作為元素引用,而不是 this。

程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?

$.fn.map() 返回的并不是數(shù)組

與 Array.prototype.map() 不同, $.fn.map() 返回的不是數(shù)組,而是 jQuery 對(duì)象,是偽數(shù)組。如果需要得到原生數(shù)組,可以采用 toArray() 或 Array.from() 輸出。

程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?

jQuery Promise

jQuery 是通過(guò) $.Deferred() 來(lái)實(shí)現(xiàn)的 Promise 功能。在 ES6 以前,如果引用了 jQuery,基本上不需要再專(zhuān)門(mén)引用一個(gè) Promise 庫(kù),jQuery 已經(jīng)實(shí)現(xiàn)了 Promise 的基本功能。

不過(guò) jQuery Promise 雖然實(shí)現(xiàn)了 then(),卻沒(méi)有實(shí)現(xiàn) catch(),所以它不能兼容原生的 Promise,不過(guò)用于 co 或者 ES2017 的 async/await 毫無(wú)壓力。

程序員總結(jié)分析:為什么要用原生 JavaScript 代替 jQuery?

雖然 jQuery 的 Promise 沒(méi)有 catch(),但是提供了 fail 事件處理,這個(gè)事件在 Deferred reject() 的時(shí)候觸發(fā)。相應(yīng)的還有 done 事件,在 Deferred resovle() 的時(shí)候觸發(fā),以及 always 事件,不論什么情況都會(huì)觸發(fā)。

與一次性的 then() 不同,事件可以注冊(cè)多個(gè)處理函數(shù),在事件觸發(fā)的時(shí)候,相應(yīng)的處理函數(shù)會(huì)依次執(zhí)行。另外,事件不具備傳遞性,所以 fail() 不能在寫(xiě)在 then() 鏈的最后。

結(jié)語(yǔ)

總的來(lái)說(shuō),在大量操作 DOM 的前端代碼中使用 jQuery 可以帶來(lái)極大的便利,也使 DOM 操作的相關(guān)代碼更易讀。另一方面,原生 JavaScript 帶來(lái)的新特性確實(shí)可以替代 jQuery 的部分工具函數(shù)/方法,以降低項(xiàng)目對(duì) jQuery 的依賴(lài)程序。

jQuery 和原生 JavaScript 應(yīng)該是共生關(guān)系,而不是互斥關(guān)系。應(yīng)該在合適的時(shí)候選用合適的方法,而不是那么絕對(duì)的非要用誰(shuí)代替誰(shuí)。

責(zé)任編輯:張燕妮 來(lái)源: 頭條科技
相關(guān)推薦

2018-08-24 09:02:26

2015-11-02 09:19:10

程序員JavaScript

2011-08-11 14:52:59

2015-09-24 09:04:36

程序員

2011-09-18 09:42:08

程序員

2013-10-29 10:24:31

程序員漫畫(huà)

2015-06-05 14:15:13

程序員難升職

2014-08-15 11:07:09

程序員

2011-12-20 09:01:25

.NET

2012-09-06 10:30:58

2016-03-15 08:51:12

程序員生活怪異

2015-09-15 09:08:58

前端程序員高薪

2019-11-08 13:57:53

程序員Excel軟件

2011-04-19 09:59:47

工資程序員

2020-02-25 15:14:13

程序員人生第一份工作睡眠

2021-10-08 06:42:59

程序員社會(huì)性缺陷

2010-10-09 09:20:08

.NET

2013-09-26 09:34:56

女程序員

2012-08-07 09:34:31

程序員

2023-03-30 09:10:38

Linux打包
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)