原文:http://lea.verou.me/2015/04/jquery-considered-harmful/**
(第一次翻譯,望大家多批評指正)
jQuery是有害的
嗨,我總想寫一個“X”是有害的帖子。
在開始寫前,我想說jquery 很大程度上促進了前端的發展。它讓開發人員實現了以前不敢想象的事情,並促使瀏覽器開發商做他們本來就該做的事。(沒有jquery我們估計現在還不可能用到document.querySelectorAll)對於那些不支持現有新技術的IE8及其以下瀏覽器jQuery依然很有必要。
但無論怎么說那些低端瀏覽器畢竟是少數,很多開發人員不需要支持只占很小份額的老版本瀏覽器。別忘了還有那些非專業開發人員:學生和研究人員,他們不僅不需要支持低版本瀏覽器,而且只需一個瀏覽器支持就夠了。如您所願,在學術界人人都津津樂道於使用網絡開放平台的新技術,對吧?然而我卻從未見過jQuery在業界這么突出。為什么?因為眾所周知,他們沒有時間或興趣追隨網絡開放平台的最新動態。他們不知道他們需要什么樣的jquery,導致他們只是單純的使用jquery。然而這並不是我拋棄jquery的唯一理由。
是的,你可能真的不需要它
我當然不是第一個指出jQuery的依賴程度影響你原生js的能力,因此我不想浪費時間重復別人之前所寫,你只需訪問以下鏈接:
...還有很多,你只需谷歌一下“you don’t need jQuery”你將發現更多。我也不再花時間贅述jQuery文件大小以及原生js方法有多高效,這些我之前都講過。今天,我想說一個不常被提及的要點。
但那並不是放棄它的最大原因
為了避免擴展本地元素的原型,jquery使用它自己的包裝對象,擴展本地對象在過去是一個龐大的 不,不。不僅因為潛在沖突,還有低版本IE瀏覽器內存泄漏。因此當你運行$(“div”)時返回的並不是一個元素引用或一個節點集合而是一個jQuery對象。這意味着對於,jquery對象的實現方式完全不同於一個DOM元素的引用、一個數組或其他類型的節點列表。然而,對於這些本地對象,就像jquery試圖提取出他們一樣,你總要不得不處理他們,哪怕他們包裝在$()中。例如:當回掉函數通過jQuery的bind()方法調用時上下文就是一個對HTML元素的引用而不是jquery的一組對象。更別提你的代碼還是多源的,有些想當然是jQuery代碼,有些則不是,最終代碼總會混淆着jQuery對象、本地對象、節點列表,而這正是地獄的開始。
如果開發人員遵循一個命名規則:用變量包裹jQuery對象(我認為在變量名頭部添加一個$是常見的一種)和本地元素,這將不再是個問題(但人們總是記不住規則,這里就先假定一個理想世界)然而,現實中並沒有那么多規則被遵守,結果就是對於不熟悉代碼的人來說代碼變得極其難懂。現在每一次編寫代碼都需要很多嘗試和錯誤(“哦!這不是一個jQuery對象,我要用$()來包裹它”或者“哦!這不是一個元素,我要用[0]來獲取其中的元素”) 為了避免混淆,開發人員編碼時常防御性的用$()包裹所有東西,因此總覽代碼,相同的變量經過$()的多重包裹,同樣的原因,這會變得很難重構其他jQuery代碼,你完全被困住了。
即使遵循了命名規則,也不能只用在jQuery對象上,你經常需要用到本地DOM方法或調用不屬於jQuery而來自其於他腳本中的函數。很快,多次折騰jQuery對象弄得到處都是,把你的代碼搞的很亂。
除此之外,當你往代碼庫中添加代碼的時候,你往往會用$()來包裹每個元素或節點列表。因為你不知道你得到了什么樣的輸入。所以被困住的不僅僅是你自己,你以后為同一個代碼庫所寫的代碼也被困住了。
獲得任何帶有jQuery依賴性的隨機腳本,你沒有自己寫並試圖重構它,這樣它就不需要jQuery。我敢說,你會發現你的主要問題將不會是如何轉換功能使用本地APIs, 而是理解這到底是怎么一回事。
一個通往原生JS的可靠途徑
當然,現在許多函數庫需要jQuery,就像最近我在推特上所說的那樣,如果你回避jQuery那么感覺你像是個數碼素食者。當然,這並不意味着你必須要使用它。當好的非jQuery代替品可用的時候,函數庫也將會被取代。
同樣的,大多數函數庫的寫法不需要用$作為jQuery的別名。用jQuery.noConflict()方法可更改默認的$並且你也可改成其他你看着順眼的符號,例如,受命令行API的啟發,我經常定義這些幫助函數:
//返回匹配到expr的第一個元素 //查詢范圍限制在container的后代中 function $(expr, container) { return typeof expr === "string"? (container || document).querySelector(expr) : expr || null; } //以數組的形式返回所有匹配到的expr //查詢范圍限制在container的后代中 function $$(expr, container) { return [].slice.call((container || document).querySelectorAll(expr)); }
此外,我認為在你每次敲出jQuery來代替$時你會考慮如果真的不需要,是否還要這么過度的使用它,或許我猜錯了 。
同時,如果你喜歡jquery API 但又不喜歡他的臃腫,那么你可以考慮使用Zepto。
很明顯,我們的標題顯而易見帶有開玩笑的意味,但是,這是互聯網,沒有什么是顯而易見的。所以在這里我很清楚Eric的經典文章會很反對這種標題。
