1. 确定值的类型
const _toString = Object.prototype.toString
export function toRawType (value) {
return _toString.call(value).slice(8, -1)
}
2. 获得一个值(含对象、数组)的字符串表示
const _toString = Object.prototype.toString
export function toString (val) {
return val == null
? ''
: Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
? JSON.stringify(val, null, 2)
: String(val)
}
3. 在函数里加入缓存控制
export function cached(fn) {
const cache = Object.create(null)
return (function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
})
}
4. 判断两个值是否宽松相等——如果两个值都是对象且它们‘模样’完全一致,则它们宽松相等
export function looseEqual (a, b) {
if (a === b) return true
const isObjectA = isObject(a)
const isObjectB = isObject(b)
if (isObjectA && isObjectB) {
try {
const isArrayA = Array.isArray(a)
const isArrayB = Array.isArray(b)
if (isArrayA && isArrayB) {
return a.length === b.length && a.every((e, i) => {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) {
const keysA = Object.keys(a)
const keysB = Object.keys(b)
return keysA.length === keysB.length && keysA.every(key => {
return looseEqual(a[key], b[key])
})
} else {
return false
}
} catch (e) {
return false
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b)
} else {
return false
}
}
5. 确保某个函数只执行一次
export function once (fn) {
let called = false
return function () {
if (!called) {
called = true
fn.apply(this, arguments)
}
}
}
6. 判断浏览器是否原生支持某个特性
export function isNative (Ctor) {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}