Skip to content

clone

深度克隆一個對象或數組。

基礎用法

typescript
import { clone } from 'radash'

const original = {
  name: 'Alice',
  age: 25,
  hobbies: ['reading', 'swimming'],
  address: {
    city: 'Beijing',
    country: 'China'
  }
}

const cloned = clone(original)
// 現在 cloned 是 original 的深度副本
// 修改 cloned 不會影響 original

語法

typescript
function clone<T>(value: T): T

參數

  • value (T): 要克隆的值,可以是任何類型

返回值

返回一個深度克隆的值,與原值完全獨立。

示例

克隆簡單對象

typescript
import { clone } from 'radash'

const original = { name: 'Alice', age: 25 }
const cloned = clone(original)

cloned.age = 30
console.log(original.age) // 25 (原對象未改變)
console.log(cloned.age)   // 30

克隆嵌套對象

typescript
import { clone } from 'radash'

const original = {
  user: {
    name: 'Bob',
    preferences: {
      theme: 'dark',
      language: 'en'
    }
  },
  settings: {
    notifications: true
  }
}

const cloned = clone(original)

cloned.user.preferences.theme = 'light'
console.log(original.user.preferences.theme) // 'dark' (原對象未改變)
console.log(cloned.user.preferences.theme)   // 'light'

克隆數組

typescript
import { clone } from 'radash'

const original = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  [1, 2, 3]
]

const cloned = clone(original)

cloned[0].name = 'Charlie'
cloned[2][0] = 999

console.log(original[0].name) // 'Alice' (原數組未改變)
console.log(original[2][0])   // 1 (原數組未改變)
console.log(cloned[0].name)   // 'Charlie'
console.log(cloned[2][0])     // 999

克隆基本類型

typescript
import { clone } from 'radash'

// 數字
const num = 42
const clonedNum = clone(num)
console.log(clonedNum) // 42

// 字符串
const str = 'hello'
const clonedStr = clone(str)
console.log(clonedStr) // 'hello'

// 布爾值
const bool = true
const clonedBool = clone(bool)
console.log(clonedBool) // true

// null
const nullValue = null
const clonedNull = clone(nullValue)
console.log(clonedNull) // null

克隆日期對象

typescript
import { clone } from 'radash'

const original = new Date('2023-01-01')
const cloned = clone(original)

cloned.setFullYear(2024)

console.log(original.getFullYear()) // 2023 (原日期未改變)
console.log(cloned.getFullYear())   // 2024

克隆正則表達式

typescript
import { clone } from 'radash'

const original = /hello/g
const cloned = clone(original)

console.log(original.source) // 'hello'
console.log(cloned.source)   // 'hello'
console.log(original.flags)  // 'g'
console.log(cloned.flags)    // 'g'

克隆函數

typescript
import { clone } from 'radash'

const original = (x: number) => x * 2
const cloned = clone(original)

console.log(original(5)) // 10
console.log(cloned(5))   // 10

克隆Map和Set

typescript
import { clone } from 'radash'

// Map
const originalMap = new Map([
  ['key1', 'value1'],
  ['key2', { nested: 'value2' }]
])
const clonedMap = clone(originalMap)

clonedMap.get('key2').nested = 'new value'

console.log(originalMap.get('key2').nested) // 'value2' (原Map未改變)
console.log(clonedMap.get('key2').nested)   // 'new value'

// Set
const originalSet = new Set([1, 2, { value: 3 }])
const clonedSet = clone(originalSet)

for (const item of clonedSet) {
  if (typeof item === 'object') {
    item.value = 999
  }
}

console.log([...originalSet]) // [1, 2, { value: 3 }] (原Set未改變)
console.log([...clonedSet])   // [1, 2, { value: 999 }]

處理循環引用

typescript
import { clone } from 'radash'

const original: any = { name: 'Alice' }
original.self = original // 循環引用

const cloned = clone(original)

console.log(cloned.name)        // 'Alice'
console.log(cloned.self === cloned) // true (循環引用被保持)

注意事項

  1. 深度克隆: clone 會遞歸地克隆所有嵌套的對象和數組
  2. 保持引用: 循環引用會被正確處理
  3. 性能: 對於大型對象,克隆操作可能比較耗時
  4. 函數克隆: 函數會被直接復制,而不是重新創建
  5. 原型鏈: 原型鏈信息會被保持

與其他方法的區別

  • Object.assign(): 只進行淺拷貝
  • {...obj}: 只進行淺拷貝
  • JSON.parse(JSON.stringify()): 無法處理函數、undefined、循環引用等
  • clone(): 進行深度克隆,處理所有類型

實際應用場景

  1. 狀態管理: 克隆狀態對象以避免直接修改
  2. 數據備份: 創建數據的備份副本
  3. 測試: 在測試中創建獨立的測試數據
  4. 緩存: 克隆緩存數據以避免污染
  5. 配置: 克隆配置對象以進行本地修改

Released under the MIT License.