UNPKG

deep-tls

Version:

deep-tls 提供了一些对数据进行深度操作的工具,如:深度相等测试、深度遍历、深拷贝等;其中,深拷贝deepCopy可对任意数据进行深度拷贝,包括 函数 function、正则 RegExp、Map、Set、Date、Array、URL 等等;支持含循环引用对象的拷贝,并且不会丢失成员的引用关系 和 类型信息,支持扩展,可根据数据类型定制拷贝逻辑,也可指定拷贝深度;所以,通过它可实现对任意类型的数据进行任意想要的拷贝

304 lines (293 loc) 11.7 kB
/* deep-tls v3.0.0 author: { "name": "郭斌勇", "email": "guobinyong@qq.com" } license: MIT homepage: https://github.com/GuoBinyong/deep-tls#readme repository: { "type": "git", "url": "https://github.com/GuoBinyong/deep-tls" } description: deep-tls 提供了一些对数据进行深度操作的工具,如:深度相等测试、深度遍历、深拷贝等;其中,深拷贝deepCopy可对任意数据进行深度拷贝,包括 函数 function、正则 RegExp、Map、Set、Date、Array、URL 等等;支持含循环引用对象的拷贝,并且不会丢失成员的引用关系 和 类型信息,支持扩展,可根据数据类型定制拷贝逻辑,也可指定拷贝深度;所以,通过它可实现对任意类型的数据进行任意想要的拷贝 */ export * from '@gby/deep-copy'; import { isIterable } from 'type-tls'; /*! ***************************************************************************** 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."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } /** * isDeepEqual(a, b, nullNotEqualUndefined) * 深度测试 a 和 b 是否完全相等;如果 a 和 b 是 对象,会进行递归相等测试,只有所有的属性 都相等时,才会认为是相等的; * * 注意: * - 对于 值为 undefined 的属性 和 不存在的属性 认为是相等的属性; * - 对于 对于 函数 ,如果整个函数的代码字符(fun.toString())串相等,则认为函数是相等的; * - 目前只判断了 基础类型、Object、Array、function、Date、可迭代 类型; * - 对于可迭代类型,必须迭代 索引 和 索引对应的值 都相等才认为是相等的; * * @param a : any * @param b : any * @param nullNotEqualUndefined ? : boolean 可选;默认值:false; 是否把 null 和 undefined 作为不等的值来对待 * @param strict ? : boolean 可选;默认值:false; 是否使用严格相等来对 基本类型的值 进行比较 * @return boolean */ function isDeepEqual(a, b, nullNotEqualUndefined, strict) { var e_1, _a, e_2, _b, e_3, _c; if (strict) { if (nullNotEqualUndefined) { var equalTest = function (a, b) { return a === b; }; } else { equalTest = function (a, b) { return a === b || (a == null && b == null); }; } } else { if (nullNotEqualUndefined) { equalTest = function (a, b) { return a == null ? a === b : a == b; }; } else { equalTest = function (a, b) { return a == b; }; } } if (equalTest(a, b) || Object.is(a, b)) { return true; } else if (a == null || b == null) { return equalTest(a, b); } var aType = typeof a; var bType = typeof b; if (aType != bType) { //测试 基础类型 与 其包装类型 的相等性 return equalTest(a.valueOf ? a.valueOf() : a, b.valueOf ? b.valueOf() : b); } if (aType == "function") { return equalTest(a, b) || equalTest(a.toString(), b.toString()); } if (aType == "object") { if (a instanceof Date) { return equalTest(a.valueOf(), b.valueOf()); } if (a instanceof Map) { if (b instanceof Map && a.size === b.size) { try { for (var a_1 = __values(a), a_1_1 = a_1.next(); !a_1_1.done; a_1_1 = a_1.next()) { var _d = __read(a_1_1.value, 2), key = _d[0], aVal = _d[1]; if (!(b.has(key) && isDeepEqual(aVal, b.get(key), nullNotEqualUndefined, strict))) { return false; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (a_1_1 && !a_1_1.done && (_a = a_1.return)) _a.call(a_1); } finally { if (e_1) throw e_1.error; } } return true; } return false; } var aIsArr = Array.isArray(a); var bIsArr = Array.isArray(b); if (!aIsArr && isIterable(a)) { var aArr = []; try { for (var a_2 = __values(a), a_2_1 = a_2.next(); !a_2_1.done; a_2_1 = a_2.next()) { var value = a_2_1.value; aArr.push(value); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (a_2_1 && !a_2_1.done && (_b = a_2.return)) _b.call(a_2); } finally { if (e_2) throw e_2.error; } } a = aArr; aIsArr = true; } if (!bIsArr && isIterable(b)) { var bArr = []; try { for (var b_1 = __values(b), b_1_1 = b_1.next(); !b_1_1.done; b_1_1 = b_1.next()) { var value = b_1_1.value; bArr.push(value); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (b_1_1 && !b_1_1.done && (_c = b_1.return)) _c.call(b_1); } finally { if (e_3) throw e_3.error; } } b = bArr; bIsArr = true; } if (aIsArr != bIsArr) { return false; } if (aIsArr) { if (a.length != b.length) { return false; } return a.every(function (aValue, index) { var bValue = b[index]; return isDeepEqual(aValue, bValue, nullNotEqualUndefined, strict); }); } var aEntrs = Object.entries(a); var bEntrs = Object.entries(b); aEntrs = aEntrs.filter(function (entr) { return !equalTest(entr[1], undefined); }); bEntrs = bEntrs.filter(function (entr) { return !equalTest(entr[1], undefined); }); if (aEntrs.length != bEntrs.length) { return false; } return aEntrs.every(function (aEntr) { var key = aEntr[0]; var aValue = aEntr[1]; var bValue = b[key]; return isDeepEqual(aValue, bValue, nullNotEqualUndefined, strict); }); } return equalTest(a, b); } /** * 递归遍历自身属性链中的所有属性(不包含原型上的属性) * @param options: DeepLoopOwnPropertyByRecursiveOptions<ThisVal> * @returns stopInfo : any 终止循环时返回的信息; */ function deepLoopOwnPropertyByRecursive(options) { var e_1, _a; var target = options.target, callback = options.callback, maxDepth = options.maxDepth, thisValue = options.thisValue, startDepth = options.startDepth, allOwnProps = options.allOwnProps; if (maxDepth <= startDepth) { return; } if (allOwnProps) { var keyList = Object.getOwnPropertyNames(target); } else { keyList = Object.keys(target); } var nextDepth = startDepth + 1; //中止遍历 var stopInfo; try { for (var keyList_1 = __values(keyList), keyList_1_1 = keyList_1.next(); !keyList_1_1.done; keyList_1_1 = keyList_1.next()) { var key = keyList_1_1.value; var value = target[key]; if (typeof value === "object") { stopInfo = deepLoopOwnPropertyByRecursive({ target: value, callback: callback, maxDepth: maxDepth, thisValue: thisValue, startDepth: nextDepth, allOwnProps: allOwnProps }); if (stopInfo) { break; } } stopInfo = callback.call(thisValue, key, value, target, nextDepth); if (stopInfo) { break; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (keyList_1_1 && !keyList_1_1.done && (_a = keyList_1.return)) _a.call(keyList_1); } finally { if (e_1) throw e_1.error; } } return stopInfo; } function deepLoopOwnProperty(target, callback, options) { var _a = options || {}, maxDepth = _a.maxDepth, thisValue = _a.thisValue, allOwnProps = _a.allOwnProps; return deepLoopOwnPropertyByRecursive({ target: target, callback: callback, maxDepth: maxDepth == undefined ? Infinity : maxDepth, thisValue: (thisValue === undefined ? target : thisValue), startDepth: 0, allOwnProps: allOwnProps }); } /** * 递归遍历自身包括原型的属性链中的所有可枚举的属性 * @param options:DeepLoopByRecursiveOptions<ThisVal> * @returns stopInfo : any 终止循环时返回的信息; */ function deepLoopPropertyWithPrototypeByRecursive(options) { var target = options.target, callback = options.callback, maxDepth = options.maxDepth, thisValue = options.thisValue, startDepth = options.startDepth; if (maxDepth <= startDepth) { return; } var nextDepth = startDepth + 1; //中止遍历 var stopInfo; for (var key in target) { var value = target[key]; if (typeof value === "object") { stopInfo = deepLoopPropertyWithPrototypeByRecursive({ target: value, callback: callback, maxDepth: maxDepth, thisValue: thisValue, startDepth: nextDepth }); if (stopInfo) { break; } } stopInfo = callback.call(thisValue, key, value, target, nextDepth); if (stopInfo) { break; } } return stopInfo; } function deepLoopPropertyWithPrototype(target, callback, options) { var _a = options || {}, maxDepth = _a.maxDepth, thisValue = _a.thisValue; return deepLoopPropertyWithPrototypeByRecursive({ target: target, callback: callback, maxDepth: maxDepth == undefined ? Infinity : maxDepth, thisValue: (thisValue === undefined ? target : thisValue), startDepth: 0 }); } export { deepLoopOwnProperty, deepLoopPropertyWithPrototype, isDeepEqual };