UNPKG

@mpxjs/utils

Version:

A toolkit for mpx framework

202 lines (189 loc) 5.58 kB
import { type, noop, isObject } from './base' const hasOwnProperty = Object.prototype.hasOwnProperty const extend = Object.assign function hasOwn (obj, key) { return isObject(obj) && hasOwnProperty.call(obj, key) } function isPlainObject (value) { if (value === null || typeof value !== 'object' || type(value) !== 'Object') return false const proto = Object.getPrototypeOf(value) if (proto === null) return true // 处理支付宝接口返回数据对象的__proto__与js中创建对象的__proto__不一致的问题,判断value.__proto__.__proto__ === null时也认为是plainObject const innerProto = Object.getPrototypeOf(proto) if (proto === Object.prototype || innerProto === null) return true // issue #644 const observeClassInstance = mpxGlobal.__mpx?.config.observeClassInstance if (observeClassInstance) { if (Array.isArray(observeClassInstance)) { for (let i = 0; i < observeClassInstance.length; i++) { if (proto === observeClassInstance[i].prototype) return true } } else { return true } } return false } function diffAndCloneA (a, b) { let diffData = null let curPath = '' let diff = false function deepDiffAndCloneA (a, b, currentDiff, bIsEmpty) { const setDiff = (val) => { if (val && !currentDiff) { currentDiff = val if (curPath) { diffData = diffData || {} diffData[curPath] = clone } } } let clone = a setDiff(bIsEmpty) if (typeof a !== 'object' || a === null) { setDiff(a !== b) } else { const toString = Object.prototype.toString const className = toString.call(a) const sameClass = className === toString.call(b) let length let lastPath if (isPlainObject(a)) { const keys = Object.keys(a) length = keys.length clone = {} setDiff(!sameClass || length < Object.keys(b).length || !Object.keys(b).every((key) => hasOwn(a, key))) lastPath = curPath for (let i = 0; i < length; i++) { const key = keys[i] curPath += `.${key}` clone[key] = deepDiffAndCloneA(a[key], sameClass ? b[key] : undefined, currentDiff, !(sameClass && hasOwn(b, key))) curPath = lastPath } // 继承原始对象的freeze/seal/preventExtensions操作 if (Object.isFrozen(a)) { Object.freeze(clone) } else if (Object.isSealed(a)) { Object.seal(clone) } else if (!Object.isExtensible(a)) { Object.preventExtensions(clone) } } else if (Array.isArray(a)) { length = a.length clone = [] setDiff(!sameClass || length < b.length) lastPath = curPath for (let i = 0; i < length; i++) { curPath += `[${i}]` clone[i] = deepDiffAndCloneA(a[i], sameClass ? b[i] : undefined, currentDiff, !(sameClass && i < b.length)) curPath = lastPath } // 继承原始数组的freeze/seal/preventExtensions操作 if (Object.isFrozen(a)) { Object.freeze(clone) } else if (Object.isSealed(a)) { Object.seal(clone) } else if (!Object.isExtensible(a)) { Object.preventExtensions(clone) } } else if (a instanceof RegExp) { setDiff(!sameClass || '' + a !== '' + b) } else if (a instanceof Date) { setDiff(!sameClass || +a !== +b) } else { setDiff(!sameClass || a !== b) } } if (currentDiff) { diff = currentDiff } return clone } return { clone: deepDiffAndCloneA(a, b, diff), diff, diffData } } function proxy (target, source, keys, readonly, onConflict) { if (!mpxGlobal.__mpx) { console.warn('[Mpx utils warn]: Can not find "global.__mpx", "proxy" may encounter some potential problems!') } keys = keys || Object.keys(source) keys.forEach((key) => { const descriptor = { get () { const val = source[key] if (mpxGlobal.__mpx) { return !mpxGlobal.__mpx.isReactive(source) && mpxGlobal.__mpx.isRef(val) ? val.value : val } else { return val } }, configurable: true, enumerable: true } descriptor.set = readonly ? noop : function (val) { if (mpxGlobal.__mpx) { const isRef = mpxGlobal.__mpx.isRef // 对reactive对象代理时不需要处理ref解包 if (!mpxGlobal.__mpx.isReactive(source)) { const oldVal = source[key] if (isRef(oldVal) && !isRef(val)) { oldVal.value = val return } } } source[key] = val } if (onConflict) { if (key in target) { if (onConflict(key) === false) return } } Object.defineProperty(target, key, descriptor) }) return target } function spreadProp (obj, key) { if (hasOwn(obj, key)) { const temp = obj[key] delete obj[key] Object.assign(obj, temp) } return obj } // 包含原型链上属性keys function enumerableKeys (obj) { const keys = [] for (const key in obj) { keys.push(key) } return keys } function processUndefined (obj) { const result = {} for (const key in obj) { if (hasOwn(obj, key)) { if (obj[key] !== undefined) { result[key] = obj[key] } else { result[key] = '' } } } return result } export { hasOwn, extend, isPlainObject, diffAndCloneA, proxy, spreadProp, enumerableKeys, processUndefined }