# JavaScript - 讓我容易搞混的 () **Published by:** [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/) **Published on:** 2025-12-13 **URL:** https://paragraph.com/@gcake/javascript-parentheses ## Content 這次 code review 時,花了一些時間釐清觀念,討論「()」在陣列方法或測試方法語法裡面的箭頭函式的意思,reviewer 分享 () 有兩個意思:// 1. 用來定義函式接收的參數 function hello(name){ // do something console.log(`Hello, ${name}!`); return } // 2. 用來表示要執行 () 前的函式 hello(); // 函式表達式和箭頭函式 // 當作一般函式使用時,可以視為同義寫法 const hello = function (name){...}; const hello = (name) => {...}; // 3. 除了上述跟函式相關的用法,還可以用來改變運算優先順序,跟數學算式的用法類似 // 1.、2. 是函式語法的一部分,3. 是群組運算子 2 + 3 * 4; // 先乘除後加減 (2 + 3) * 4; // 括號算完才由左到右運算 目前練習過程遇到容易搞混的情境(容易弄錯括號要包的範圍)// 陣列方法 arr.filter((item) => item.active); arr.map((item) => item.name); arr.reduce((sum, item) => sum + item.price, 0); // 陣列方法的同語意寫法 arr.filter(function (item) { return item.active; }); arr.map(function (item) { return item.name; }); arr.reduce(function (sum, item) { return sum + item.price; }, 0); // Vitest 測試語法 test('adds', () => { expect(add(1, 2)).toBe(3); }); test.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ])('add(%i, %i) -> %i', (a, b, expected) => { expect(add(a, b)).toBe(expected); }); // Vitest 測試語法的同語意寫法 test('adds', function () { expect(add(1, 2)).toBe(3); }); test.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ])('add(%i, %i) -> %i', function (a, b, expected) { expect(add(a, b)).toBe(expected); }); 看到一長串 () ,可以練習的拆解思考方法先用一般函式表達式理解箭頭函式在「不使用 this / arguments、也不拿來 new」的情境下,可以把這兩種寫法視為同語意。目前練習還沒碰到。// 這兩個在「當作一般函式使用」時,語意可以視為相同 const hello = function (name) { // ... }; const hello = (name) => { // ... }; ():定義函式接收的參數=> 或 function:定義函式的內容// 箭頭函式 (item) => item.active; // 從定義拆解箭頭函式 function (item) { return item.active; } // 回到陣列方法中拆解 arr.filter((item) => item.active); arr.filter(function (item) { return item.active; }); 分層拆解陣列方法 () 思路:arr.filter(...):filter 是 HOF 高階函式,() 要放一個函式當作判斷條件(item) => item.active:定義一個匿名函式參數:(item) 表示函式接收自訂名稱為 item 的參數,在這裡會是陣列中的每個元素函式內容:item.active 表示函式處理運算參數的內容和回傳值不同陣列方法的參數數量和回傳值內容不同// Vitest 測試語法中的箭頭函式 // 單一測試 test('adds', () => { expect(add(1, 2)).toBe(3); }); // 從定義拆解單一測試方法中的箭頭函式 test('adds', function () { expect(add(1, 2)).toBe(3); }); // 參數化測試(巢狀陣列) test.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ])('add(%i, %i) -> %i', (a, b, expected) => { expect(add(a, b)).toBe(expected); }); // 結構是 const eachFn = test.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ]); eachFn( 'add(%i, %i) -> %i', (a, b, expected) => { expect(add(a, b)).toBe(expected); }, ); // 從定義拆解參數化測試方法中的箭頭函式 // (a, b, expected) => {...} 同語意寫法 function (a, b, expected) { expect(add(a, b)).toBe(expected); } 分層拆解測試方法 () 思路:單一測試test('測試描述句', ...) : test 是一個函式,第一個參數是描述測試內容的字串,第二個參數是測試內容的函式(在這裡是() => {...} )() => {...} : 定義一個「不接收任何參數」的函式參數:() 表示沒有參數函式內容:{expect(add(1, 2)).toBe(3);} 表示測試步驟expect():接收實際算出來的值,所以常常會在裡面直接呼叫被測試函式 add(1, 2) 拿回傳值toBe() :斷言,接收預期的測試函式輸出結果參數化測試1.test.each([...])('測試描述句', 這個函式) : 整體語意是「把這個匿名函式交給 Vitest,請 Vitest 依照前面那個資料表,重複呼叫它很多次」。 1. 相當於 eachFn('測試描述句', 這個函式) 這個對照單一測試函式的語法 2. test.each([...]) : 把測試資料表(巢狀陣列)給 Vitest,回傳一個函式,內層陣列每一組代表一組測資 3. (a, b, expected) => {...} : 被 Vitest 多次呼叫的匿名函式從語意定義判斷 () 在做什麼大部分搞混「括號要包到哪裡」的問題,其實是在搞清楚:「這裡是在『定義函式』,還是在『呼叫函式』,還是在『包一坨運算式』」 ## Publication Information - [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/): Publication homepage - [All Posts](https://paragraph.com/@gcake/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@gcake): Subscribe to updates