前端工具包之深淺拷貝

前言

咱們在開發過程當中,總會封裝一些公共函數來做爲咱們的工具來簡化代碼或者複用代碼,爲此,我打算整理一下我平常工做中經常使用的一些封裝的工具函數,本篇文章爲對象、數組的deepClone函數封裝。javascript

系列文章

1.前端工具包之深淺拷貝前端

2.前端工具包之日期格式化java

3.前端工具包之防抖函數git

4.前端工具包之小工具web

5.前端工具包之log美化數組

背景

let a = {
    age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2
複製代碼

從上述例子中咱們能夠發現,若是給一個變量賦值一個對象,那麼二者的值會是同一個引用,其中一方改變,另外一方也會相應改變。bash

可是一般在開發中咱們不但願出現這樣的問題,咱們可使用淺拷貝來解決這個問題。ide

解析

淺拷貝函數

首先能夠經過 Object.assign 或 展開運算符 ... 來解決這個問題。工具

let a = {
    age: 1
}
let b = Object.assign({}, a) // or {...a}
a.age = 2
console.log(b.age) // 1
複製代碼

一般淺拷貝就能解決大部分問題了,可是當咱們遇到以下狀況就須要使用到深拷貝了

let a = {
    age: 1,
    jobs: {
        first: 'FE'
    }
}
let b = {...a}
a.jobs.first = 'native'
console.log(b.jobs.first) // native
複製代碼

淺拷貝只解決了第一層的問題,若是接下去的值中還有對象的話,那麼就又回到剛開始

深拷貝

let a = {
    age: 1,
    jobs: {
        first: 'FE'
    }
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
複製代碼

可是該方法也是有侷限性的:

  • 會忽略 undefined
  • 會忽略 symbol
  • 不能序列化函數
  • 不能解決循環引用的對象

在遇到functionundefined 或者 symbol 的時候,該對象也不能正常的序列化

let a = {
    age: undefined,
    sex: Symbol('male'),
    jobs: function() {},
    name: 'wb'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "wb"}
複製代碼

你會發如今上述狀況中,該方法會忽略掉函數和 undefined 。

可是在一般狀況下,複雜數據都是能夠序列化的,因此這個函數能夠解決大部分問題,而且該函數是內置函數中處理深拷貝性能最快的。固然若是你的數據中含有以上三種狀況下,可使用遞歸來實現一個深拷貝方法,所以,這裏就封裝一個工具函數來供實現深拷貝。

工具封裝

首先使用 Object.prototype.toString.call 實現一個精準判斷類型的輔助函數,再借助遞歸實現深拷貝

// 精準判斷類型函數
function  typeOf (obj) {
  const  toString = Object.prototype.toString
  const  map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  }
  return map[toString.call(obj)]
}
// util 深拷貝函數
export function deepClone (data) {
  const t = typeOf(data)
  let o
  if (t === 'array') {
    o = []
  } else if (t === 'object') {
    o = {}
  } else {
    return data
  }
  if (t === 'array') {
    for (let i = 0; i < data.length; i++) {
      o.push(deepCopy(data[i]))
    }
  } else if (t === 'object') {
    for (let i in data) {
      o[i] = deepCopy(data[i])
    }
  }
  return o
}
複製代碼

開源庫

我的主頁 | bin-ui | bin-admin

相關文章
相關標籤/搜索