"use strict"; function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } var toString = Object.prototype.toString; function __type(x) { // fix typeof null = object if (x === null) { return 'null'; } var t = _typeof(x); if (t !== 'object') { return t; } var cls; var clsLow; try { cls = toString.call(x).slice(8, -1); clsLow = cls.toLowerCase(); } catch (e) { // ie下的 activex对象 return 'object'; } if (clsLow !== 'object') { return clsLow; } if (x.constructor === Object) { return clsLow; } // Object.create(null) try { /* eslint-disable no-proto */ if (Object.getPrototypeOf(x) === null || x.__proto__ === null) { /* eslint-enable no-proto */ return 'object'; } } catch (e) {// } try { var cname = x.constructor.name; if (typeof cname === 'string') { return cname; } } catch (e) {// 无constructor } // function A() {}; A.prototype.constructor = null; new A return 'unknown'; } function SimpleWeakmap() { this.cacheArray = []; } var UNIQUE_KEY = "com.yanhaijing.jsmini.clone".concat(new Date().getTime()); SimpleWeakmap.prototype.set = function (key, value) { this.cacheArray.push(key); key[UNIQUE_KEY] = value; }; SimpleWeakmap.prototype.get = function (key) { return key[UNIQUE_KEY]; }; SimpleWeakmap.prototype.clear = function () { for (var i = 0; i < this.cacheArray.length; i++) { var key = this.cacheArray[i]; delete key[UNIQUE_KEY]; } this.cacheArray.length = 0; }; function getWeakMap() { var result; if (typeof WeakMap !== 'undefined' && __type(WeakMap) === 'function') { result = new WeakMap(); if (__type(result) === 'weakmap') { return result; } } result = new SimpleWeakmap(); return result; } function isClone(x) { var t = __type(x); return t === 'object' || t === 'array'; } function hasOwnProp(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); } function copy(x) { var uniqueData = getWeakMap(); var t = __type(x); var root = x; if (t === 'array') { root = []; } else if (t === 'object') { root = {}; } // 循环数组 var loopList = [{ parent: root, key: undefined, data: x }]; while (loopList.length) { // 深度优先 var node = loopList.pop(); var parent = node.parent; var key = node.key; var source = node.data; var tt = __type(source); // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素 var target = parent; if (typeof key !== 'undefined') { parent[key] = tt === 'array' ? [] : {}; target = parent[key]; } // 复杂数据需要缓存操作 if (isClone(source)) { // 命中缓存,直接返回缓存数据 var uniqueTarget = uniqueData.get(source); if (uniqueTarget) { parent[key] = uniqueTarget; continue; // 中断本次循环 } // 未命中缓存,保存到缓存 uniqueData.set(source, target); } if (tt === 'array') { for (var i = 0; i < source.length; i++) { if (isClone(source[i])) { // 下一次循环 loopList.push({ parent: target, key: i, data: source[i] }); } else { target[i] = source[i]; } } } else if (tt === 'object') { for (var k in source) { if (hasOwnProp(source, k)) { if (k === UNIQUE_KEY) { continue; } if (isClone(source[k])) { // 下一次循环 loopList.push({ parent: target, key: k, data: source[k] }); } else { target[k] = source[k]; } } } } } uniqueData.clear && uniqueData.clear(); return root; } module.exports = { copy: copy };