Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

56.deep-copy #56

Open
webVueBlog opened this issue Sep 8, 2022 · 0 comments
Open

56.deep-copy #56

webVueBlog opened this issue Sep 8, 2022 · 0 comments

Comments

@webVueBlog
Copy link
Member

webVueBlog commented Sep 8, 2022

// 深拷贝
// src 原数据
// 返回拷贝后的数据
module.exports = function deepCopy(src, cache = new WeakMap()) {
 // 拷贝原始值,直接返回原始值本身
 if (isPrimitiveType(src)) return src

 // 解决循环引用的问题
 if (cache.has(src)) return src
 cache.set(src, true)

 // 拷贝数组
 if (isArray(src)) {
  const ret = []
  for (let i = 0; len = src.length; i < len; i++) {
   ret.push(deepCopy(src[i], cache))
  }
  return ret
 }

  // 拷贝 Map 对象
  if (isMap(src)) {
    const ret = new Map()
    src.forEach((value, key) => {
      ret.set(key, deepCopy(value, cache))
    })
    return ret
  }
  
  // 拷贝函数
  if (isFunction(src)) {
   copyFunction(src)
  }
  
   // 拷贝对象
   if (isObject(src)) {
     // 获取对象上的所有key
     const keys = [...Object.keys(src), ...Object.getOwnPropertySymbols(src)]
     const ret = {}
     // 遍历所有的key,递归调用 deepCopy 拷贝 obj[key] 的值
     keys.forEach(item => {
      ret[item] = deepCopy(src[item], cache)
     })
     // 返回拷贝后的对象
      return ret
   }

}

// 判断数据是否为原始值类型(Number,Boolean,String,Symbol,BigInt,Null,Undefined)
function isPrimitiveType(data) {
 const primitiveType = ['Number', 'Boolean', 'String', 'Symbol', 'BigInt', 'Null', 'Undefined']

 return primitypeType.includes(getDataType(data))
}

// 判断数据是否为Object类型
function isObject(data) {
 return getDateType(data) === 'Object'
}

// 判断数据是否为函数
function isFunction(data) {
 return getDataType(data) === 'Function'
}

// 判断数据是否为数组
function isArray(data) {
 return getDataType(data) === 'Array'
}

// 判断数据是否为Map
function isMap(data) {
 return getDataType(data) === 'Map'
}

// 获取数据类型
// Number, Boolean, String, Symbol, BigInt, Null, Undefined, Object, Function, Array, Map, Date
function getDataType(data) {
 return Object.prototype.toString.apply(data).slice(8, -1)
}


// 拷贝函数
function copyFunction(src) {
 const fnName = src.name
 let srcStr = src.toString()
 // 匹配function fnName ,比如 function fnName() {}
 const fnDecExp = new RegExp(`function (${fnName})?`)
 // 切除匹配内容,srcStr = (xxx) {} 或 (xxx) => {}
 srcStr = srcStr.replace(fnDexExp, '')
 // 匹配函数参数
 const argsExg = /\((.*)\)/
 let args = argsExg.exec(srcStr)
 // 函数体
 const fnBody = srcStr.replace(argsExg, '').trim()
 // { return 'test' } => return 'test'
 const fnBodyCode = /^{(.*)}$/.exec(fnBody)
 // 得到了函数的名称,参数,函数体,重新声明函数
 return new Function(...args[1].splict(','), fnBodyCode[1])
}

@webVueBlog webVueBlog changed the title 55.debounce 56.deep-copy Sep 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant