> ## Content Index
> Fetch the complete content index at: https://blog.anthea.day/llms.txt
> Use this file to discover other available public pages before exploring further.

# 好用的 JavaScript Library 使用筆記（1）：Lodash — flow
- URL: https://blog.anthea.day/e5-a5-bd-e7-94-a8-e7-9a-84-javascript-library-e4-bd-bf-e7-94-a8-e7-ad-86-e8-a8-98-1/
- Published: 2025-08-15T17:28:17.000Z
- Updated: 2026-11-07T19:59:22.000Z
- Author: Anthea / 芫荽
- Tags: #Migrated-1792241843742, #Import 2026-10-17 12:57, Coding

`_.flow()` 是 Lodash 提供的一個函數組合方法，類似 chain 的概念，可以將多個函數串聯起來，形成一個新的函數。這個新函數會按照從左到右的順序執行傳入的函數，前一個函數的輸出會成為下一個函數的輸入。

### 實際應用場景：購物車結算

讓我們以購物車結算為例，比較傳統寫法與使用 `flow` 的差異。假設我們已經有以下幾個購物車結算時需要用到的函式了：

```javascript
// 步驟 1: 計算商品總價 
function calculateSubtotal(cart) { 
  // ... 
} 
 
// 步驟 2: 處理折扣 
function applyDiscounts(subtotal, user) { 
  // ... 
} 
 
// 步驟 3: 處理折價券 
function applyCoupon(afterDiscount, coupon) { 
  // ... 
} 
 
// 步驟 4: 處理點數折抵 
function redeemPoints(afterCoupon, userPoints) { 
  // ... 
} 
 
// 步驟 5: 計算運費 
function calculateShipping(finalAmount) { 
  // ... 
}
```

#### 傳統寫法（不使用 Flow）

```php
function processCheckout(cart) { 
  const subtotal = calculateSubtotal(cart); 
   
  const discount = applyDiscounts(subtotal, cart.user); 
  const afterDiscount = subtotal - discount; 
   
  const couponDiscount = applyCoupon(afterDiscount, cart.coupon); 
  const afterCoupon = afterDiscount - couponDiscount; 
   
  const pointsUsed = redeemPoints(afterCoupon, cart.user.points); 
  const finalAmount = afterCoupon - pointsUsed; 
  const remainingPoints = cart.user.points - pointsUsed; 
   
  const shippingFee = calculateShipping(finalAmount); 
  const totalAmount = finalAmount + shippingFee; 
   
  return { 
    ...cart, 
    subtotal, 
    discount, 
    afterDiscount, 
    couponDiscount, 
    afterCoupon, 
    pointsUsed, 
    finalAmount, 
    remainingPoints, 
    shippingFee, 
    totalAmount 
  }; 
}
```

#### 使用 Flow 的優雅寫法

```cpp
// 購物車結算處理函數 
const processCheckout = _.flow([ 
  calculateSubtotal, 
  applyDiscounts, 
  applyCoupon, 
  redeemPoints, 
  calculateShipping 
]);
```

是不是看起來簡單很多呢？

#### 兩種寫法的比較

**傳統寫法的問題：**

- 所有邏輯都混在一個大函數裡
- 變數名容易重複或混淆
- 難以單獨測試某個步驟
- 修改某個步驟可能影響其他部分
- 可讀性較差，需要仔細閱讀才能理解流程

**Flow 寫法的優勢：**

- 每個步驟都是獨立的函數，職責清晰
- 函數名具有表達力，一眼就能看懂流程
- 容易單獨測試每個步驟
- 修改某個步驟不會影響其他部分
- 可重用性高，函數可以在其他地方使用
- 讀起來就像在描述業務流程

#### Flow vs FlowRight

Lodash 還提供了 `flowRight` 方法，它與 `flow` 的區別在於執行順序：

```cpp
// flow: 從左到右執行 
const leftToRight = _.flow([addOne, multiplyByTwo]); 
console.log(leftToRight(3)); // (3 + 1) * 2 = 8 
 
// flowRight: 從右到左執行 
const rightToLeft = _.flowRight([addOne, multiplyByTwo]); 
console.log(rightToLeft(3)); // (3 * 2) + 1 = 7
```