【前端基礎】關於 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,我們下次見。

為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
在前端開發中,很常會有需要轉址的需求,且處理的手法滿因人而異的,所以今天就想要來整理一些常見的 JavaScript 頁面轉址方式,以及各自的差異。
Functional Programming 中文譯作函式程式設計,或是功能性程式設計,常簡稱為:FP,是一種透過使用純函式(Pure Funciton)進行軟體開發,且避免副作用的程式設計典範,比起宣告式的流程控制,在 FP 採用主要以表達式的方式撰寫程式碼。
Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
在初學程式的時候,我曾經看室友開發專案到一半時,突然坐在那發呆,於是我好奇一問,室友說:「我在等程式編譯完成啊。」 還記得當初還是程式小菜雞的我,懞懂無知的說:「編譯?哈哈哈,我們 JavaScript 都不需要編譯耶,可以直接跑在瀏覽器上。」 室友一臉莫名其妙地回我:「噢,是嗎⋯⋯」
在前端開發中,很常會有需要轉址的需求,且處理的手法滿因人而異的,所以今天就想要來整理一些常見的 JavaScript 頁面轉址方式,以及各自的差異。
Functional Programming 中文譯作函式程式設計,或是功能性程式設計,常簡稱為:FP,是一種透過使用純函式(Pure Funciton)進行軟體開發,且避免副作用的程式設計典範,比起宣告式的流程控制,在 FP 採用主要以表達式的方式撰寫程式碼。
Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
在初學程式的時候,我曾經看室友開發專案到一半時,突然坐在那發呆,於是我好奇一問,室友說:「我在等程式編譯完成啊。」 還記得當初還是程式小菜雞的我,懞懂無知的說:「編譯?哈哈哈,我們 JavaScript 都不需要編譯耶,可以直接跑在瀏覽器上。」 室友一臉莫名其妙地回我:「噢,是嗎⋯⋯」
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
這篇文章更偏向純紀錄性質,方便日後有需要時直接複製相同指令來完成 Bootstrap 與 Sass 的引入,也會做成一個專案起手式的模板放在 Github ,未來在建置新專案時可以透過直接複製專案,來省去前面重複的這過程。
Thumbnail
微前端是一種現代前端架構,旨在將大型前端應用拆分為獨立、可獨立部署的小模組。這與微服務在後端的策略相似。 本文將探討微前端的基本概念,以及如何在基於Gin的後端系統中實施它,從而實現真正的全棧模組化。
Thumbnail
let 和 const 是 JavaScript 在 ES6 版本中新的變數宣告方式。使用 let 宣告的變數可以重新賦值,而使用 const 宣告的變數賦值後則不能改變。這兩種新的宣告方式提供了比 var 更嚴格和清晰的變數作用域管理。
Thumbnail
JavaScript 陣列的操作方法,forEach() 是用於遍歷陣列的每個元素,並對每個元素執行提供的函數,map() 是創建一個新陣列,其結果是對原陣列中的每個元素調用提供的函數後返回的結果。
Thumbnail
本文將介紹陣列的基本操作方法,包括建立陣列、存取元素、陣列遍歷和修改陣列等,接下來將逐一介紹這些操作,並附上程式碼範例,讓你更易於理解和運用。。
Thumbnail
JavaScript 陣列的操作方法,push() 可以將值加入到陣列的最後一個位置 ,pop() 會移除(取出)陣列的最後一個元素,shift() 會移除陣列的第一個元素,unshift() 則會將指定的元素添加到第一個位置。
Thumbnail
JavaScript 的命名規則相當重要,它有些特定的慣例和限制。例如,變數和函式通常使用小駝峰式(firstName)命名。然後 JavaScript 對大小寫敏感,所以lastName和lastname是不同的變數。
Thumbnail
npm 是一個套件管理工具,開發中經常需要使用第三方套件,npm 是可以用來管理很多套件的工具,這邊指的套件可能是 Library, 框架, 工具等,例如 Bootstrap, jQuery, Vue.js, babel 都可以統一由它管理。
Thumbnail
本文題目來自網站codesignal,它是個可依自己選取的程式語言進行測驗,測驗難易程度會逐題增加,可透過解題來獲得分數以及徽章,相當有趣味性。在sumbit後可在左欄看到票選最高的解法,這些解法來自不同語言,當然你可以在上面篩選自己撰寫的程式語言。沒有所謂的最好的解法,只有最適合的方式。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
這篇文章更偏向純紀錄性質,方便日後有需要時直接複製相同指令來完成 Bootstrap 與 Sass 的引入,也會做成一個專案起手式的模板放在 Github ,未來在建置新專案時可以透過直接複製專案,來省去前面重複的這過程。
Thumbnail
微前端是一種現代前端架構,旨在將大型前端應用拆分為獨立、可獨立部署的小模組。這與微服務在後端的策略相似。 本文將探討微前端的基本概念,以及如何在基於Gin的後端系統中實施它,從而實現真正的全棧模組化。
Thumbnail
let 和 const 是 JavaScript 在 ES6 版本中新的變數宣告方式。使用 let 宣告的變數可以重新賦值,而使用 const 宣告的變數賦值後則不能改變。這兩種新的宣告方式提供了比 var 更嚴格和清晰的變數作用域管理。
Thumbnail
JavaScript 陣列的操作方法,forEach() 是用於遍歷陣列的每個元素,並對每個元素執行提供的函數,map() 是創建一個新陣列,其結果是對原陣列中的每個元素調用提供的函數後返回的結果。
Thumbnail
本文將介紹陣列的基本操作方法,包括建立陣列、存取元素、陣列遍歷和修改陣列等,接下來將逐一介紹這些操作,並附上程式碼範例,讓你更易於理解和運用。。
Thumbnail
JavaScript 陣列的操作方法,push() 可以將值加入到陣列的最後一個位置 ,pop() 會移除(取出)陣列的最後一個元素,shift() 會移除陣列的第一個元素,unshift() 則會將指定的元素添加到第一個位置。
Thumbnail
JavaScript 的命名規則相當重要,它有些特定的慣例和限制。例如,變數和函式通常使用小駝峰式(firstName)命名。然後 JavaScript 對大小寫敏感,所以lastName和lastname是不同的變數。
Thumbnail
npm 是一個套件管理工具,開發中經常需要使用第三方套件,npm 是可以用來管理很多套件的工具,這邊指的套件可能是 Library, 框架, 工具等,例如 Bootstrap, jQuery, Vue.js, babel 都可以統一由它管理。
Thumbnail
本文題目來自網站codesignal,它是個可依自己選取的程式語言進行測驗,測驗難易程度會逐題增加,可透過解題來獲得分數以及徽章,相當有趣味性。在sumbit後可在左欄看到票選最高的解法,這些解法來自不同語言,當然你可以在上面篩選自己撰寫的程式語言。沒有所謂的最好的解法,只有最適合的方式。