是 Ray 不是 Array

整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ

Advertisement
2025-12-08 JavaScript

一個時代的王者 jQuery,為什麼沒落了?

一個時代的王者 jQuery,為什麼沒落了?

前言

前陣子有人問了我一下,為什麼業界都比較多推薦使用 Vue、React、Angular 這些前端框架,而不是 jQuery 了?而他實際工作上還是會使用 jQuery,所以他很好奇這個現象背後的原因是什麼?於是我就寫了這篇文章來聊聊這個話題。

jQuery 的崛起

首先我們要先了解一下 jQuery 的時代背景,jQuery 在 2006 年被推出,以當時的時代背景來講,許多 JavaScript 語法都沒有被各大瀏覽器支援,導致 Web 開發者在開發網頁時,常常需要針對不同的瀏覽器(Chrome、Firefox、IE、Safari 等)寫不同的程式碼,這讓開發者非常的頭痛。

jQuery 最主要的第一個目標就是 「解決跨瀏覽器相容性問題」 ,它將許多繁瑣的 JavaScript 語法封裝成簡單易用的 API,讓開發者可以更輕鬆地操作 DOM、處理事件、進行動畫效果等。這大大提升了開發效率,讓 jQuery 很快就成為了當時最受歡迎的 JavaScript 函式庫。

其中最知名的語法莫過於 $('element')

1
2
// 選取 class 為 box 的元素,並且設定背景顏色為紅色
$('.box').css('background-color', 'red');

我們可以看到一個簡單的 $('.box') 就可以選取到所有 class 為 box 的元素,並且使用 css 方法來設定背景顏色,這樣的語法簡潔且易於理解,讓許多開發者都愛上了 jQuery。

畢竟早期瀏覽器其選取元素時,僅有 getElementByIdgetElementsByClassNamegetElementsByTagName 這些方法,使用起來相當不便。

你可能會覺得 $('.box') 實作應該很簡單吧?其實不然,jQuery 在背後做了很多事情來確保這個語法能夠在各大瀏覽器上正常運作,這一點我們可以透過翻閱 jQuery 的原始碼來了解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// jQuery 1.x 的核心選取器實作
var rootjQuery,
// 用來區分是字串「HTML 標籤」(如:'<div>')還是「ID 選取器」(如:'#id')
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
init = jQuery.fn.init = function( selector, context ) {
var match, elem;
// 情況一:如果選擇的元素為空,則回傳空的 jQuery 物件
// 例如: $('') 或 $(null) 或 $(undefined) 等情況
if ( !selector ) {
return this;
}
// 情況二:如果已經是 DOM 元素,那就直接將這個 DOM 元素包裝成 jQuery 物件並回傳
// 例如: $(document.body) 或 $(someDomElement) 等情況
if ( selector.nodeType ) {
this[ 0 ] = selector;
this.length = 1;
return this;
// 情況三:如果傳入的是一個函式
// 例如: $(function() { ... }),這表示當 DOM 準備好後要執行的程式碼
} else if ( typeof selector === "function" ) {
// 接著判斷 rootjQuery.ready 是否存在,如果存在就呼叫它並傳入 selector,否則直接呼叫 selector 並傳入 jQuery 物件
return rootjQuery.ready !== undefined ?
rootjQuery.ready( selector ) :
selector( jQuery );
} else {
// 情況四:其他情況,代表傳入的是一個字串(可能是 HTML 或 CSS 選取器)等其他東西
match = selector + ""; // 強制轉成字串,這邊使用的是 JavaScript 的隱含轉型技巧,例如:1+"1" 會變成 "11"

// 檢查是否為明顯的 HTML 字串,例如: "<div>Hello</div>",這種就稱為明顯的 HTML 字串,那就會直接跳過正規表達式的檢查
if ( isObviousHtml( match ) ) {
match = [ null, selector, null ];
// 如果不是明顯的 HTML 字串,那就使用 rquickExpr 正規表達式來檢查,這邊就會判斷它到底是一個 HTML 標籤還是 ID 選取器
} else if ( typeof selector === "string" ) {
match = rquickExpr.exec( selector );
} else {
// 如果不是字串也不是 DOM 元素,那就把它轉成陣列並回傳
return jQuery.makeArray( selector, this );
}
// ...後續還有很多情況的處理,這邊就不一一贅述了

透過上述的程式碼,我們可以看到 jQuery 光在選取元素時,為了避免各種奇怪的錯誤以及瀏覽器相容性問題,做了非常多的檢查與處理。

如果真的要簡單講的話,$('element') 這個語法背後其實是做了以下幾件事:

  • 檢查是不是空的值
  • 檢查是不是一個 DOM 元素
  • 檢查是不是一個函式
  • 是不是一個 HTML 字串
  • 是不是一個 ID 選取器

直到最後,如果都不是的話,就會跑去執行一段 return this.constructor( context ).find( selector ); 的程式碼。

所以 jQuery 之所以可以稱霸當時的前端開發市場並不是沒有原因的。

jQuery 的沒落

講完了崛起,當然要講講沒落。

我們不得不承認 jQuery 在當時的確解決了許多開發者的痛點,提供了許多很好用的方法,可以讓我們更輕鬆地操作 DOM、處理事件、進行動畫效果,例如:

  • $('selector'):簡單易用的元素選取器
  • $.ajax():方便的 AJAX 請求方法
  • $(element).on('event', handler):統一的事件處理方法
  • $(element).animate():簡單的動畫效果實現
  • $(element).css():輕鬆操作 CSS 樣式
  • $(element).addClass()/removeClass():方便的類別操作方法
  • $(element).html()/text():輕鬆取得或設定元素內容
  • $(element).append()/prepend():簡單的 DOM 操作方法
  • $.each():方便的迴圈處理方法
  • $.extend():物件合併與擴展方法
  • $(element).fadeIn()/fadeOut():簡單的淡入淡出效果
  • $(element).slideUp()/slideDown():簡單的滑動效果
  • $(element).width()/height():輕鬆取得或設定元素的寬高

當然這些只是 jQuery 眾多 API 的一小部分,但足以看出 jQuery 在當時提供了非常多實用的功能,讓開發者能夠更專注於業務邏輯,而不是被繁瑣的 DOM 操作所困擾。

隨著時代的演進,許多瀏覽器開始遵守標準化開發,盡可能地支援 ECMAScript 標準,這讓原本 jQuery 解決的跨瀏覽器相容性問題逐漸變得不那麼嚴重了。

此外,現代 JavaScript 也引入了許多新的語法和功能,例如:

  • querySelectorquerySelectorAll:原生的元素選取方法,語法與 jQuery 類似。
  • fetch API:現代的 AJAX 請求方法,取代了 jQuery 的 $.ajax()
  • classList:方便的類別操作方法,取代了 jQuery 的 addClassremoveClass
  • Promises:現代的非同步處理方式,讓程式碼更易讀。
  • async/await:更簡潔的非同步程式碼撰寫方式。

這些都讓開發者可以更輕鬆地使用原生 JavaScript 來完成過去需要 jQuery 才能做到的事情,什麼意思呢?簡單來講,你不用再去額外引入 jQuery 這個函式庫,就能夠達成過去 jQuery 幫你解決的問題。

這邊我也提供 Table 來做一個比較:

功能 jQuery 方法 原生 JavaScript 方法
元素選取 $('selector') document.querySelectorAll('selector')
AJAX 請求 $.ajax() fetch()
類別操作 $(element).addClass() element.classList.add()
事件處理 $(element).on() element.addEventListener()
動畫效果 $(element).animate() CSS 動畫或 requestAnimationFrame
取得/設定內容 $(element).html() element.innerHTML
迴圈處理 $.each() Array.prototype.forEach()
物件合併與擴展 $.extend() Object.assign()

儘管原生 JavaScript 的語法可能沒有 jQuery 那麼簡潔,但使用原生語法終究可以減少對外部函式庫的依賴,這對於專案的維護和效能來說是有益的。

儘管 jQuery 有提供 minified(壓縮版) 的檔案,但對於現代的前端開發來說,載入一個額外的函式庫仍然會增加網頁的載入時間和資源消耗,這在追求效能和速度的時代顯得尤為重要。

另外,隨著前端複雜度越來越高,前端開始需要做更多的狀態管理、元件化開發等,這些都是 jQuery 無法很好解決的問題。這也促使了 Vue、React、Angular 等前端框架的興起,這些框架提供了更完整的解決方案,讓開發者可以更有效率地構建複雜的前端應用程式。

而且 jQuery 的設計上是以「操作 DOM」為核心,但是現代化前端框架則是以「資料驅動」為核心,什麼意思呢?舉例來講,當 jQuery 要改變 <p>1</p> 這個元素的內容時,通常會直接操作 DOM,例如:

1
$('p').text('2');

但如果是使用 Vue 或 React,則是透過改變資料來驅動 DOM 的更新,例如:

1
2
3
4
5
6
7
8
9
10
// Vue 範例
<template>
<p>{{ message }}</p>
</template>

<script setup>
import { ref } from 'vue';
const message = ref('1');
message.value = '2'; // 改變資料,DOM 自動更新
</script>

可以看到從頭到尾都沒有直接操作 DOM。

Note
儘管很多人會說直接操作 DOM 的渲染成本很重,但在 Svelte 這個框架中,仍然是採用直接操作 DOM 的方式來進行更新,只不過 Svelte 在編譯階段就已經將這些操作優化好了,所以效能上並不會比虛擬 DOM 差。引入虛擬 DOM 並不是為了解決效能問題,而是為了解決開發者體驗問題,讓開發者可以更專注於撰寫程式碼,而不是擔心 DOM 操作的細節。

所以,綜合以上原因,jQuery 在現代前端開發中的地位逐漸被取代,成為了一個歷史的產物。

儘管 jQuery 已經不再是前端開發的主流,但它仍然在許多舊有專案中被廣泛使用,甚至還是世界之冠(來源:W3Techs):

jQuery 市佔率

Note
這邊也要小提一件事情,jQuery 市佔率之所以可以這麼高也要歸功於 WordPress,全世界有超過 40% 的網站是使用 WordPress 架設的,而 WordPress 內建就提供了 jQuery,所以這也是 jQuery 市佔率高的一個重要原因。

並且對於初學者來說,jQuery 依然是一個很好的學習工具,甚至想要做一些小專案,但你不想花太多時間學習現代前端框架的話,jQuery 仍然是一個不錯的選擇。

整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ

Advertisement

你的支持會直接轉換成更多技術筆記

如果我的筆記讓你少踩一個坑、節省 Debug 的時間,
也許你可以請我喝杯咖啡,讓我繼續當個不是 Array 的 Ray ☕

buymeacoffee | line | portaly

Terminal

分享這篇文章

留言

© 2025 Ray. All rights reserved.

Powered by Ray Theme