@iusername/js-deep-clone
TypeScript icon, indicating that this package has built-in type declarations

1.3.2 • Public • Published

deepClone

介绍

deepClone 是一个 javascript 深拷贝函数

支持几乎常见以及绝大多数 javascript 数据类型的数据的深度复制, 默认支持 ES6+ 环境,如果想要支持 ES3、ES5 的话需要在项目中添加 pollfill。

如果有您想要支持但尚未支持的类型,或是现有支持的类型存在问题,欢迎您提一个Issues

支持类型

  • 基础类型:null、undefined、String、Number、Symbol、Boolean、BigInt、NaN
  • Object (包含 js对象、数字对象:Number(1)、字符串对象:String('string')、布尔对象:new Boolean(false))
  • Function(尚不支持原型链复制)
  • Array
  • Date
  • RegExp
  • Blob(blob属于数据类型,不属于 js 类型,node 中运行的话没法直接 new Blob(), 但浏览器中可以,注意运行环境)
  • Set
  • Map
  • ArrayBuffer、DataView
  • TypeArray(Int8Array、Int16Array、Int32Array、Uint8Array、Uint16Array、Uint32Array、Float32Array、Float64Array、Uint8ClampedArray)
  • BigArray(BigInt64Array、BigUint64Array)
  • 支持对象的循环引用(看下面示例中的 obj.d)

PS: WeakSet 和 WeakMap 由于其内部数据的不计数引用这一特殊性无法复制内部数据,也就不具有复制的能力

使用

# npm
npm i @iusername/js-deep-clone

# yarn
yarn add @iusername/js-deep-clone
import deepClone from 'deepClone';

const source = {}
const target = deepClone(source)

示例

import deepClone from 'deepClone';

const symbolName = Symbol();
const arrbuf = new ArrayBuffer(12)
const obj = {
  objNumber: new Number(1),
  number: 1,
  objString: new String('ss'),
  string: 'stirng',
  objRegexp: new RegExp('\\w'),
  regexp: /w+/g,
  date: new Date(),
  set: new Set(),
  map: new Map(),
  function: function (value) {
    return this.number + value
  },
  // blob: new Blob([1, 12]),
  int8Array: new Int8Array(10),
  int16Array: new Int16Array(10),
  int32Array: new Int32Array(10),
  uint8Array: new Uint8Array(8),
  uint16Array: new Uint16Array(8),
  uint32Array: new Uint32Array(8),
  arrBuffer: new ArrayBuffer(10),
  dataView: new DataView(arrbuf.slice(), 0, 8),
  uint8ClampedArray: new Uint8ClampedArray(10),
  bigInt: 12n,
  bigIntArray: new BigInt64Array(12),
  bigUintArray: new BigUint64Array(12),
  array: [{ a: 1 }, 2],
  [symbolName]: 111,
  sym: symbolName
}

obj.d = obj;
Object.defineProperty(obj, 'number', {
  writable: false,
  enumerable: true,
  configurable: false,
  value: 2,
})

const o = deepClone(obj)
console.log('number: ', o.number === obj.number);             // number:  true
console.log('string: ', o.string === obj.string);             // string:  true
console.log('objNumber: ', o.objNumber === obj.objNumber);    // objNumber:  false
console.log('objString: ', o.objString === obj.objString);    // objString:  false
console.log('sym: ', o.sym === obj.sym);                      // sym:  true
console.log('objRegexp: ', o.objRegexp === obj.objRegexp);    // objRegexp:  false
console.log('regexp: ', o.regexp === obj.regexp);             // regexp:  false
console.log('date: ', o.date === obj.date);                   // date:  false
console.log('set: ', o.set === obj.set);                      // set:  false
console.log('map: ', o.map === obj.map);                      // map:  false
console.log('function: ', o.function === obj.function);       // function:  false
console.log('int8Array: ', o.int8Array === obj.int8Array);    // int8Array:  false
console.log('int16Array: ', o.int16Array === obj.int16Array); // int16Array:  false
console.log('int32Array: ', o.int32Array === obj.int32Array); // int32Array:  false
console.log('uint8Array: ', o.uint8Array === obj.uint8Array);    // uint8Array:  false
console.log('uint16Array: ', o.uint16Array === obj.uint16Array); // uint16Array:  false
console.log('uint32Array: ', o.uint32Array === obj.uint32Array); // uint32Array:  false
console.log('uint8ClampedArray: ', o.uint8ClampedArray === obj.uint8ClampedArray); // uint32Array:  false
console.log('dataView: ', o.dataView === obj.dataView);         // dataView:  false
console.log('arrBuffer: ', o.arrBuffer === obj.arrBuffer);      // arrBuffer:  false
console.log('array: ', o.array === obj.array);                  // array:  false
console.log('array item: ', o.array[0] === obj.array[0], o.array[1] === obj.array[1]);  // array items:  false true
console.log('symbolName: ', o[symbolName] === obj[symbolName]);   // symbolName:  false
console.log('d: ', o.d === o, o.d === obj.d)                       // d:  true false
obj.function(2)   // 4
o.function(2)     // 4
console.log(o)    // { objNumber: [Number: 1], number: 2, ... , d: [Circular], [Symbol()]: 111 }
console.log(o.d)  // { objNumber: [Number: 1], number: 2, ... , d: [Circular], [Symbol()]: 111 }
console.log(obj)  // { objNumber: [Number: 1], number: 2, ... , d: [Circular], [Symbol()]: 111 }
console.log(Object.getOwnPropertyDescriptor(newObj, 'number')) // { writable: false, enumerable: true, configurable: false, value: 2 }

console.log(deepClone(null))      // null
console.log(deepClone(undefined)) // undefined
console.log(deepClone('123'))     // '123'
console.log(deepClone({}))        // {}
console.log(deepClone(12))        // 12
console.log(deepClone(new ArrayBuffer(20))) // ArrayBuffer{ [Uint8Contents]: <00, 00, ...>, byteLength: 20 }
console.log(deepClone(/abc/))       // /abc/

const date = new Date()
const cloneDate = deepClone(date)
console.log(date, cloneDate, date == cloneDate, date === cloneDate)    // 2020-05-09T05:42:54.818Z 2020-05-09T05:42:54.818Z false false

TODO

  • Function 原型链复制
  • Proxy 对象(暂且不作为必须功能看待)

LICENSE

MIT

Dependents (0)

Package Sidebar

Install

npm i @iusername/js-deep-clone

Weekly Downloads

7

Version

1.3.2

License

MIT

Unpacked Size

43.3 kB

Total Files

20

Last publish

Collaborators

  • iusername