【前端基礎】關於 JavaScript 的型別系統:基礎型別、物件型別

更新 發佈閱讀 15 分鐘

在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。

JavaScript 型別特別之處,源自於「弱型別」與「高階語言」的特性,前者會在遇到需要條件判斷時針對型別轉為真值(Truthy Value)與假值(Falsy Value),而後者意味著:JavaScript 無法直接針對硬體進行操作,會直接使用 JavaScript 所提供的介面操作對應環境(瀏覽器、伺服器)中的項目,這兩件事對於 JavaScript 的型別系統有兩大影響:

  1. 在一些條件下,JavaScript 部分型別的空值,會被自動轉型
  2. 我們無法針對 JavaScript 的記憶體位置進行操作,取而代之是相似的儲存機制,基礎型別會儲存在各自的記憶體位置,物件型別則會生成一個「記憶體參考位置」來進行其中的記憶體參考位置。

初學者可能會看到上方的敘述感到頭很痛,會想說:「這些記憶體、轉型到底跟 JavaScript 的型別有什麼直接關係?」

如果你也有這樣的疑惑,就跟我先從最基礎的型別開始了解吧!

JavaScript 中的型別

在 JavaScript 中主要會分為兩大型別,分別是:基礎型別與物件型別,兩者的差異有:

  1. 前者儲存方式單純(後續會更深入的聊到);後者則是以記憶體參考位置來儲存資料。
  2. 前者資料格式單一,不會同時存在多種型別;後者可以儲存複合的資料格式,一個變數內可以同時存在多種型別。

這邊我會以自己覺得好理解的資料格式順序介紹:

基礎型別:字串(string):

字串是一個在 JavaScript 非常重要的型別,在一些 API 資料格式,與 HTML Input 元素取出的值大部分都是以字串為主,字串型別通常會以單引號「’」或是「”」雙引號將文字包裹起來,例如:

const name = "Vivian";

const year = "2023";

只要是被引號包裹起來的,不論其中的內容物是數字、符號、字元,在 JavaScript 中都被視為字串型別。

針對字串 JavaScript 提供了一些可以用來處理字串的方法,這邊列舉一些常用的方法:

const name = "Vivian";

const year = "2023";

// string.length 可計算字元長度
const nameLength = name.length;
console.log(nameLength);
// 6

// string.toLowerCase() 可以將字串中的大寫字母轉為小寫
const nameLowerCase = name.toLowerCase();
console.log(nameLowerCase);
// vivian

// string.toUpperCase() 可以將字串中的小寫字母轉為大寫
const nameUpperCase = name.toUpperCase();
console.log(nameUpperCase);
// VIVIAN

//string.trim() 過濾字串前後的連續空白字元,在進行表單欄位驗證時非常方便
const trimName = `${name} `.trim();
console.log(trimName);
// Vivian

在實務上,字串的資料格式常常是在取得來自後台的文案、資料庫的使用者資料:信箱、電話號碼、姓名等,因為數字與符號都可以被使用者不小心輸入進去,因此字串方法五花八門,也會為了符合公司、業主需求,延伸出一些驗證手段,使用 trim 方法過濾掉連續空白字元,可以說是最基本一種表單驗證手段。


基礎型別:數字(number):

JavaScript 數字可以用來顯示整數與小數點位數,但要注意一點是,針對小數點的處理是使用浮點數計算法(非十進位),所以針對小數點的處理會有誤差,如果要針對小數點做運算,建議可以轉為整數做處理,或是可以使用一些函式庫做處理:

// 在 JavaScript 直接計算小數點會有誤差:
0.1 + 0.2 = 0.30000000000000004

// 轉為整數處理
let result = (0.1 * 10 + 0.2 * 10) / 10
// result = 0.3

接著我們來看一些常用的數字方法:

// 將字串轉為數字,常用在轉換表單資訊的數字
const num = Number('1234');
console.log(num);
// 1234

// 針對小數四捨五入
const num = Math.round(3.6);
console.log(num);
// 4

// 針對小數無條件捨去
const num = Math.floor(3.6);
console.log(num);
// 3

// 取得介於 0 與 1 之間的隨機小數,通常可以用來搭配一些運算方式讓 UI 依照這些亂數順序顯示
const randomNumber = Math.random()
console.log(randomNumber);
// 0.03365605210247358

在實務上,數字型別會用來儲存跟數量、時間有關的單位,要注意的是只有數字可以被拿來做數學上的運算,所以需要用到計算時,要特別注意自己拿到的資料,是否真的是數字型別。


基礎型別:布林(Boolean)

布林是一種用來顯示 true 或是 false 的資料格式,通常會用來進行條件判斷,我個人認為布林是基本型別中最容易令人誤解的資料型別,它看似很簡單,但卻會涉及複雜的真值、假值,與自動轉型的議題,由於這部分會需要完整理解 JavaScript 中的型別系統,才能有更清楚的理解,這部分我會獨立出一篇內容來做介紹。


基礎型別:NaN

NaN 是英文 not a number 的縮寫,這個型別可能會出現在字串數字混合運算時出現預期外錯誤,導致最後運算出來的結果因型別錯誤而產生的非數字的結果,型別有可能是 NaN。


物件型別:物件

在 JavaScript 中,只要不是「基本型別」,可以儲存多種複合資料格式的型別,都可以稱之為廣義的物件。

而狹義的物件會用大括號 { } 包裹鍵值(key value pairs),如果有多組鍵值的話會使用逗號來區隔,主要的用途為呈現多種複合的資料,舉一個常見使用者資料作為範例:

const user = {
name: 'Vivian',
age: 26,
gender: 'female',
email: 'vivien.enlife@gmail.com',
isEmailVerified: true,
};

假設我們寫一串假資料來模擬使用者行為,上方這個範例就是一個很常見的使用者資訊,譬如說:使用者的名稱、年齡、電子信箱以及電子信箱是否經過驗證等,可以看出來這樣的資料結構會是較為複合,甚至可以說能夠組成相對應更加複雜的資料結構。

與基本型別最大的不同的是,這些鍵值可以被視作物件的屬性,這些屬性可以被視作這個物件整體的小小器官、組織,各自象徵這個物件的一些特性,例如:一個網站的使用者身份是由許多不同的資料組成。

我們還可以針對物件屬性進行複寫、取值的的動作:

// 覆寫
user.name = 'vvn';

// 讀取物件
console.log(user);
/* {name: 'vvn', age: 26,
gender: 'female',
email: 'vivien.enlife@gmail.com',
isEmailVerified: true} */

// 讀取物件屬性
console.log(user.name);
// 'vvn'

不過這樣覆寫物件屬性的方式,並不是一個好的做法,原因後續我們會提到。

由於物件自己本身的方法並沒有很頻繁被使用到,會需要在特定的場景下才會派的上用場,原因我們後續會提到,所以這裡我們先不談廣義物件的方法。

或是可以參考我撰寫的系列文章:致 JavaScript 開發者的 Functional Programming 新手指南


物件型別:陣列

陣列是一種用來管例重複性資料的資料結構,也是物件型別的一種,與物件最大的不同是,陣列是有順序性的,通常會使用中括號 [ ] 並以逗號分隔資料單位,舉例來說:

let numbers = [1, 2, 3, 4, 5];
let fruits = ['apple', 'banana', 'orange'];

// 取用陣列資料
console.log(fruits[0])

// 修改陣列資料
fruits[0] = 'berry';
console.log(fruits);
// ['berry', 'banana', 'orange'];

在實務上,我們會用陣列來儲存更加複雜的資料格式,例如:商品列表、使用者列表、數據等,由於我們會需要針對這些複雜的資料格式進行重複的處理,有些甚至是跟使用者行為有關的 UI 行為,因此比起物件來說,前端工程師可能花更多的時間處理陣列這個資料格式,接著就讓我們來看看有哪一些常用的陣列方法吧!

  • forEach
// forEach 遍歷陣列,使用情境:直接針對陣列做操作(對新手來說較好理解,實務上非必要不太會使用)

function processElement(element) {
// 執行特定的邏輯
console.log(element);
}

let fruits = ['apple', 'banana', 'orange'];
fruits.forEach(processElement);

forEach 是一個藉由帶入 callback 函式來遍歷(從第一個到最後一個)陣列中元素的陣列方法,通常陣列方法的第一個參數會是遍歷當前元素,第二個參數會是元素的索引(index)。

由於 forEach 本身不會回傳值,所以通常要碼是直接更改陣列,或是要在新增一個空的陣列,搭配其他的陣列方法來進行處理。

由於直接修改陣列內容會因為物件本身的記憶體位置特性,導致污染原始資料,所以我們比較少用到,如果從 JavaScript 記憶體角度不好理解這件事的話,也可以從另外一個實務開發角度來看這件事。

假設我們撈取了一筆使用者資料的列表,我想要在 A 頁面進行資料的批次處理,B 頁面保持原始資料,為了不要頻繁的呼叫 API ,我們還是要將 A 頁面經處理的資料,與 B 頁面要使用的原始資料分隔開來,不然就會出現頁面資料彼此污染的狀況。

  • filter

在許多情境下我們會需要針對既有的資料,來進行內容的篩選來避免網路請求所需要的額外時間與流量,我們會在 filter 陣列方法中帶入一個 callback 函式,並針對回傳條件的布林值,回傳出一個全新的陣列,我們來看一個篩選一到十之間偶數的篩選方式:

// 假設有一個陣列包含數字資料
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 使用 filter 過濾偶數數字
let evenNumbers = numbers.filter(function(number) {
return number % 2 === 0;
});

console.log(evenNumbers); // 輸出: [2, 4, 6, 8, 10]

在實務上的應用可能會更加複雜一點,舉例來說:透過指定的類別、分類篩選出指定的商品列表。

  • map

map 的概念為「映射」,我們可以帶入一個 callback 函式針對陣列進行運算後回傳結構類似,但樣貌、規律、結果可能不同的列表,這樣說可能會有點抽象,讓我們來看簡單的範例:

// 假設有一個陣列包含數字資料
let numbers = [1, 2, 3, 4, 5];

// 使用 map 將每個數字平方
let squaredNumbers = numbers.map(function(number) {
return number ** 2;
});

console.log(squaredNumbers); // 輸出: [1, 4, 9, 16, 25]

上述的範例中,我們把一串數字陣列,套用了計算平方的邏輯,最終產出一串與原始資料結構有類似邏輯,但計算規律不同的陣列。

在實務上,前端工程師可能不太會處理到複雜數學的計算邏輯,但有可能拿一串原始資料整理出 UI 元件,例如:商品列表、使用者列表、選單之類的 UI 元件,此時 UI 元件如果有一些重複性的文案或是邏輯,就可以透過 map 一次性套用原始資料的內容。

mapfilter 的優勢很顯而易見,就是能做到遍歷陣列的目的,同時整理、處理資料,但又不會污染原始資料。

由於陣列時常用於處理重複性的資料,也常常會遇到一些來自使用者的客製化需求,掌握好陣列方法可以說是非常有效益的一件事,這裡簡單條列一些,會用到且容易了解的陣列方法。

  • push(element):向陣列末尾新增一個元素。
  • pop():移除並返回陣列末尾的元素。
  • shift():移除並返回陣列開頭的元素。
  • unshift(element):向陣列開頭新增一個或多個元素。
  • length:取得陣列的長度。
  • concat(array):合併多個陣列。
  • slice(startIndex, endIndex):回傳從起始索引到結束索引(不包括結束索引)的子陣列。
  • splice(startIndex, deleteCount, items):從指定索引位置開始刪除指定數量的元素,並可插入新的元素。
  • indexOf(element):返回指定元素在陣列中首次出現的索引,若不存在則返回 -1。
  • includes(element):判斷陣列是否包含指定元素,返回布林值。

如果你會對如何更好的使用陣列方法撰寫 JavaScript,我會推薦你來閱讀這一系列的文章:致 JavaScript 開發者的 Functional Programming 新手指南,其中會有一些更進階的陣列方法應用與一些前端的延伸套件介紹。

我是 Vivian,我們下次見。

留言
avatar-img
Vivian Yeh - 跨領域轉職的軟體工程師
460會員
103內容數
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
2024/05/23
與 cookie 相比,localStorage 與 sessionStorage 的機制相對單純,兩者皆是瀏覽器中的儲存空間,與 cookie 最大的不同在於:localStorage 與 ⋯⋯
Thumbnail
2024/05/23
與 cookie 相比,localStorage 與 sessionStorage 的機制相對單純,兩者皆是瀏覽器中的儲存空間,與 cookie 最大的不同在於:localStorage 與 ⋯⋯
Thumbnail
2024/05/22
在瀏覽器環境中有許多的儲存空間,想要查看這些空間的話,可以透過「chrome > Dev Tools > Application > Storage」即能進行查看。 瀏覽器內存空間的差異不僅常常被拿來被當作面試考題,在實務開發中更扮演舉足輕重的角色,今天就想透過這系列的文章深度了解這些瀏覽器內存⋯
Thumbnail
2024/05/22
在瀏覽器環境中有許多的儲存空間,想要查看這些空間的話,可以透過「chrome > Dev Tools > Application > Storage」即能進行查看。 瀏覽器內存空間的差異不僅常常被拿來被當作面試考題,在實務開發中更扮演舉足輕重的角色,今天就想透過這系列的文章深度了解這些瀏覽器內存⋯
Thumbnail
2024/02/20
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
2024/02/20
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
看更多
你可能也想看
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
本章節旨在介紹 TypeScript 的基本資料型別,包括內建型別、型別轉換、自訂型別、元組、集合、陣列、和字典型別。透過理解和使用這些型別,可以提高代碼的可讀性和可維護性。
Thumbnail
本章節旨在介紹 TypeScript 的基本資料型別,包括內建型別、型別轉換、自訂型別、元組、集合、陣列、和字典型別。透過理解和使用這些型別,可以提高代碼的可讀性和可維護性。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
Thumbnail
本章節旨在介紹TypeScript的基本語法,包括一般結構、程式進入點、註解以及變數的定義和賦值。這些知識將幫助讀者瞭解TypeScript的基本架構,並且可以開始使用TypeScript進行開發。
Thumbnail
TypeScript是一種由Microsoft開發和維護的開源編程語言。它是JavaScript的超集,主要擴展了JavaScript的語法,增加了靜態類型檢查和其他特性,使得開發大型應用程序更為方便和可靠。
Thumbnail
TypeScript是一種由Microsoft開發和維護的開源編程語言。它是JavaScript的超集,主要擴展了JavaScript的語法,增加了靜態類型檢查和其他特性,使得開發大型應用程序更為方便和可靠。
Thumbnail
本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
Thumbnail
本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
Thumbnail
這些章節的目的是為了介紹JavaScript中的各種數據類型,包括基礎類型和物件類型,以及如何將數據從一種類型轉換為另一種類型。此外,還介紹了如何創建自定義類型,以及如何使用JavaScript中的陣列、集合和字典。
Thumbnail
這些章節的目的是為了介紹JavaScript中的各種數據類型,包括基礎類型和物件類型,以及如何將數據從一種類型轉換為另一種類型。此外,還介紹了如何創建自定義類型,以及如何使用JavaScript中的陣列、集合和字典。
Thumbnail
JavaScript是一種具有動態型別、弱型別、原型繼承等特性的高級腳本語言,應用範圍廣泛,包括前端開發、後端開發、移動應用等。它被各種公司和開源社區廣泛使用。學習JavaScript需要掌握ECMAScript標準、異步編程、模塊系統等知識。
Thumbnail
JavaScript是一種具有動態型別、弱型別、原型繼承等特性的高級腳本語言,應用範圍廣泛,包括前端開發、後端開發、移動應用等。它被各種公司和開源社區廣泛使用。學習JavaScript需要掌握ECMAScript標準、異步編程、模塊系統等知識。
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News