// 深拷贝,为了解决循环引用和共同引用的问题,引入了WeakMap,又因为引入WeakMap可能会导致被拷贝对象被挂上【作为WeakMap的探针的】匿名函数(是pollyfill的行为吧?),所以不会拷贝非根元素的匿名函数。 function deepClone(target, hash = new WeakMap()) { // 定义一个变量 let result = null // 如果当前需要深拷贝的是一个对象的话 if (typeof target === 'object') { if (hash.has(target)) { // 如果是循环引用 result = hash.get(target) } else if (Array.isArray(target)) { // 如果是一个数组的话 result = [] // 将result赋值为一个数组,并且执行遍历 hash.set(target, result) for (let i in target) { if (!(typeof(target[i]) === 'function' && !target.name)) { // 递归克隆数组中的每一项 result.push(deepClone(target[i], hash)) } } // 判断如果当前的值是null的话;直接赋值为null } else if (target === null) { result = null // 判断如果当前的值是一个RegExp对象的话,直接赋值 } else if (target.constructor === RegExp) { result = target } else { // 否则是普通对象,直接for in循环,递归赋值对象的所有值 result = {} hash.set(target, result) for (let i in target) { if (!(typeof(target[i]) === 'function' && !target.name)) { result[i] = deepClone(target[i], hash) } } } } else if (typeof target === 'function') { result = target } else { // 如果不是对象也不是函数,直接赋值 result = target } // 返回最终结果 return result } export default { throttle(fn, interval) { let lastRunTime = 0 return function (...args) { let elapsedTime = Date.now() - lastRunTime if (elapsedTime < interval) { return null } let context = this lastRunTime = Date.now() return fn.apply(context, args) } }, copyToClipBoard(content) { let tempDom = document.createElement('input') tempDom.setAttribute('value', content) document.body.appendChild(tempDom) tempDom.select() tempDom.setSelectionRange(0, 9999) document.execCommand('Copy') document.body.removeChild(tempDom) }, showToast(contentStr) { const toastNode = document.createElement('div') toastNode.style.position = 'fixed' toastNode.style.left = '50%' toastNode.style.top = '50%' toastNode.style.transform = 'translate(-50%, -50%)' toastNode.style.backgroundColor = '#555' toastNode.style.borderRadius = '0.5rem' toastNode.style.padding = '1.67rem' toastNode.style.minWidth = '33vw' toastNode.style.color = '#fff' toastNode.style.fontSize = '1.67rem' toastNode.style.zIndex = globalConfig.zIndex.toast.self toastNode.style.display = 'flex' toastNode.style.flexDirection = 'column' toastNode.style.justifyContent = 'center' toastNode.style.alignItems = 'center' toastNode.innerText = contentStr document.body.appendChild(toastNode) setTimeout(() => { document.body.removeChild(toastNode) }, 1700) }, randomWord(randomFlag, min, max) { //随机字符串 var str = "", range = min, arr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ] if (randomFlag) { // 随机长度 range = Math.round(Math.random() * (max - min)) + min } for (var i = 0; i < range; i++) { var pos = Math.round(Math.random() * (arr.length - 1)) str += arr[pos] } return str }, unique(arr) { let map = new Map() let array = new Array() // 数组用于返回结果 for (let i = 0; i < arr.length; i++) { if (map.has(arr[i])) { // 如果有该key值 map.set(arr[i], true) } else { map.set(arr[i], false) // 如果没有该key值 array.push(arr[i]) } } return array }, deepClone, } /** * 如果想让注册的回调只调用一次就自动注销,在注册的回调中执行注销即可。 */ export class MessageCenter { constructor() { this._recorder = {} } logInvalidParam() { console.error('MessageCenter: invalid parameter.') } subscribe(message, callback) { if (typeof (message) !== 'string' || typeof (callback) !== 'function') { this.logInvalidParam() return } if (!Object.prototype.hasOwnProperty.call(this._recorder, message)) { this._recorder[message] = [] } this._recorder[message].push(callback) } unsubscribe(message, callback) { if (typeof (message) !== 'string' || typeof (callback) !== 'function') { this.logInvalidParam() return } if (!Object.prototype.hasOwnProperty.call(this._recorder, message)) { const idx = this._recorder[message].indexOf(callback) if (idx !== -1) { this._recorder[message].splice(idx, 1) } } } publish(message, param) { console.log(this._recorder) if (Object.prototype.hasOwnProperty.call(this._recorder, message)) { this._recorder[message].forEach((callback) => { callback(param) }) } } }