UNPKG

@gby/deep-copy

Version:

deep-copy 深拷贝,可对任意数据进行深度拷贝,包括 函数 function、正则 RegExp、Map、Set、Date、Array、URL 等等;支持含循环引用对象的拷贝,并且不会丢失成员的引用关系 和 类型信息,支持扩展,可根据数据类型定制拷贝逻辑,也可指定拷贝深度;所以,通过它可实现对任意类型的数据进行任意想要的拷贝

318 lines (305 loc) 13.5 kB
/* @gby/deep-copy v4.0.0 author: { "name": "郭斌勇", "email": "guobinyong@qq.com" } license: MIT homepage: https://github.com/GuoBinyong/deep-copy#readme repository: { "type": "git", "url": "https://github.com/GuoBinyong/deep-copy" } description: deep-copy 深拷贝,可对任意数据进行深度拷贝,包括 函数 function、正则 RegExp、Map、Set、Date、Array、URL 等等;支持含循环引用对象的拷贝,并且不会丢失成员的引用关系 和 类型信息,支持扩展,可根据数据类型定制拷贝逻辑,也可指定拷贝深度;所以,通过它可实现对任意类型的数据进行任意想要的拷贝 */ define(['exports', 'type-reviver', 'type-tls', 'com-tools'], function (exports, typeReviver, typeTls, comTools) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } // Date ---------- var Date_Copier = function (value) { return new Date(value.getTime()); }; // Array ---------- var Array_Copier = function (value, copyMember) { return value.reduce(function (valCopy, item, index) { valCopy.push(undefined); copyMember(item, function (itemCopy) { valCopy.splice(index, 1, itemCopy); }, index); return valCopy; }, []); }; // Map ---------- var Map_Copier = function (value, copyMember) { var valCopy = new Map(); value.forEach(function (item, key) { copyMember(item, function (itemCopy) { valCopy.set(key, itemCopy); }, key); }); return valCopy; }; // Set ---------- var Set_Copier = function (value, copyMember) { var e_1, _a; var valCopy = new Set(); var index = 0; try { for (var value_1 = __values(value), value_1_1 = value_1.next(); !value_1_1.done; value_1_1 = value_1.next()) { var item = value_1_1.value; copyMember(item, function (itemCopy) { valCopy.add(itemCopy); }, index); ++index; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (value_1_1 && !value_1_1.done && (_a = value_1.return)) _a.call(value_1); } finally { if (e_1) throw e_1.error; } } return valCopy; }; // URL ---------- var URL_Copier = function (value) { return new URL(value.href); }; // RegExp ---------- var RegExp_Copier = function (value) { return new RegExp(value); }; // Function ---------- var Function_Copier = function (value) { return comTools.copyConstructor(value); }; var presetTypeCopierArray = [ [Date, Date_Copier], [Array, Array_Copier], [Map, Map_Copier], [Set, Set_Copier], [URL, URL_Copier], [RegExp, RegExp_Copier], [Function, Function_Copier], ["AsyncFunction", Function_Copier], ["GeneratorFunction", Function_Copier] ]; /** * 默认 Copier 的 TypeName */ var typeNameOfDefaultCopier = "default"; /** * 深拷贝的核心函数 */ function deepCopyByRecursive(options) { var e_1, _a, e_2, _b; var value = options.value, typeReviverObject = options.typeReviverObject, allOwnProperties = options.allOwnProps, copyFun = options.copyFun, maxDepth = options.maxDepth, startDepth = options.startDepth, rawCopyMap = options.rawCopyMap, complete = options.completeCB, key = options.key, host = options.host; var completeCB = complete || function () { }; /** * 这里 用的是 maxDepth < depth 而不是 maxDepth <= depth ,原因如下: * 当 maxDepth === depth 时,当前的 value 还是需要被拷贝的,所以还是要生成 value 的副本,如果直接返回 value ,则是没有拷贝 value */ if (maxDepth < startDepth || (!copyFun && typeof value === "function") || typeTls.isBaseType(value)) { completeCB(value); return value; } var decide = rawCopyMap.get(value); if (decide) { decide.then(completeCB); return decide.value; } decide = new comTools.Decide(); decide.then(completeCB); rawCopyMap.set(value, decide); var nextDepth = startDepth + 1; function copyMember(member, compCB, key, host, options) { var finalHost = host == null ? value : host; if (options) { var allOwnProps = options.allOwnProps, depth = options.depth, copyFunction = options.copyFun; } var allOwnProps_Bool = allOwnProps == null ? allOwnProperties : allOwnProps; var copyFun_Bool = copyFunction == null ? copyFun : copyFunction; var memDepth = depth == null ? nextDepth : depth; return deepCopyByRecursive({ value: member, typeReviverObject: typeReviverObject, allOwnProps: allOwnProps_Bool, copyFun: copyFun_Bool, maxDepth: maxDepth, startDepth: memDepth, rawCopyMap: rawCopyMap, completeCB: compCB, key: key, host: finalHost }); } var typeName = typeTls.getExactTypeNameOf(value); var copier = typeReviverObject[typeName]; if (typeof copier === "function") { var valCopy_1 = copier.call(value, value, copyMember, { allOwnProps: allOwnProperties, key: key, host: host, type: typeName, depth: startDepth, copyFun: copyFun }); decide.value = valCopy_1; return valCopy_1; } if (typeof value.getCopy === "function") { var valCopy_2 = value.getCopy(value, copyMember, { allOwnProps: allOwnProperties, key: key, host: host, type: typeName, depth: startDepth, copyFun: copyFun }); decide.value = valCopy_2; return valCopy_2; } var defaultTypeName = typeNameOfDefaultCopier; var defaultCopier = typeReviverObject[defaultTypeName]; if (typeof defaultCopier === "function") { var valCopy_3 = defaultCopier.call(value, value, copyMember, { allOwnProps: allOwnProperties, key: key, host: host, type: defaultTypeName, depth: startDepth, copyFun: copyFun }); decide.value = valCopy_3; return valCopy_3; } if (typeof value[Symbol.iterator] === "function") { var valCopy_4 = []; var index = 0; var _loop_1 = function (item) { var itemIndex = index; /** * 因为接下来要往通过 splice 往 valCopy 中插入元素,必须要保证当插入元素时 valCopy 的长度一定要包含被插入元素的开始位置; * 否则,splice 会从元素末尾插入元素,这样有可能会打乱 itemCopy 的原始顺序 */ valCopy_4.push(undefined); deepCopyByRecursive({ value: item, typeReviverObject: typeReviverObject, allOwnProps: allOwnProperties, copyFun: copyFun, maxDepth: maxDepth, startDepth: nextDepth, rawCopyMap: rawCopyMap, completeCB: function (itemCopy) { valCopy_4.splice(itemIndex, 1, itemCopy); }, key: index, host: value }); ++index; }; try { // @ts-ignore for (var value_1 = __values(value), value_1_1 = value_1.next(); !value_1_1.done; value_1_1 = value_1.next()) { var item = value_1_1.value; _loop_1(item); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (value_1_1 && !value_1_1.done && (_a = value_1.return)) _a.call(value_1); } finally { if (e_1) throw e_1.error; } } decide.value = valCopy_4; return valCopy_4; } var valConsr = value.constructor; var valCopy; if (typeof valConsr === "function") { try { valCopy = new valConsr(); } catch (e) { valCopy = Object.create(valConsr.prototype); } } else { valCopy = Object.create(Object.getPrototypeOf(value)); } if (allOwnProperties) { var allKeys = Object.getOwnPropertyNames(value); } else { allKeys = Object.keys(value); } var _loop_2 = function (key_1) { var propVal = value[key_1]; deepCopyByRecursive({ value: propVal, typeReviverObject: typeReviverObject, allOwnProps: allOwnProperties, copyFun: copyFun, maxDepth: maxDepth, startDepth: nextDepth, rawCopyMap: rawCopyMap, completeCB: function (itemCopy) { var propDes = Object.getOwnPropertyDescriptor(value, key_1); Object.defineProperty(valCopy, key_1, propDes); valCopy[key_1] = itemCopy; }, key: key_1, host: value }); }; try { for (var allKeys_1 = __values(allKeys), allKeys_1_1 = allKeys_1.next(); !allKeys_1_1.done; allKeys_1_1 = allKeys_1.next()) { var key_1 = allKeys_1_1.value; _loop_2(key_1); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (allKeys_1_1 && !allKeys_1_1.done && (_b = allKeys_1.return)) _b.call(allKeys_1); } finally { if (e_2) throw e_2.error; } } decide.value = valCopy; return valCopy; } function createDeepCopy(presetTypeCopierMap) { function deepCopy(value, options, typeCopyers) { if (options) { var maxDepth = options.maxDepth, allOwnProps = options.allOwnProps, copyFun = options.copyFun; } var maxDepth_Num = maxDepth == null ? Infinity : maxDepth; var allOwnProps_Bool = !!allOwnProps; var copyFun_Bool = !!copyFun; var presetTCMap = deepCopy.presetTypeCopierMap; var mergedTCArr = typeReviver.mergeTypeRevivers(presetTCMap.size > 0 ? presetTCMap : null, typeCopyers); var trObj = typeReviver.toTypeReviverObject(mergedTCArr); return deepCopyByRecursive({ value: value, typeReviverObject: trObj, allOwnProps: allOwnProps_Bool, copyFun: copyFun_Bool, maxDepth: maxDepth_Num, startDepth: 0, rawCopyMap: new Map() }); } Object.defineProperty(deepCopy, "presetTypeCopierMap", { configurable: true, enumerable: true, get: function () { if (!this._presetTypeCopierMap) { this._presetTypeCopierMap = new Map(); } return this._presetTypeCopierMap; }, set: function (newValue) { if (newValue instanceof Map) { this._presetTypeCopierMap = newValue; } } }); if (presetTypeCopierMap) { deepCopy.presetTypeCopierMap = presetTypeCopierMap; } return deepCopy; } var defaultPresetTypeCopierMap = new Map(presetTypeCopierArray); var deepCopy = createDeepCopy(new Map(presetTypeCopierArray)); function isCopyable(target) { return target && typeof target.getCopy === "function"; } exports.createDeepCopy = createDeepCopy; exports.deepCopy = deepCopy; exports.default = deepCopy; exports.defaultPresetTypeCopierMap = defaultPresetTypeCopierMap; exports.isCopyable = isCopyable; exports.typeNameOfDefaultCopier = typeNameOfDefaultCopier; Object.defineProperty(exports, '__esModule', { value: true }); });