-
Notifications
You must be signed in to change notification settings - Fork 1
shared
kennana edited this page Jul 14, 2023
·
1 revision
import { hyphenateRE, camelizeRE } from '../regex/index'
export const isUndef = (v: any) => {
return v === undefined || v === null
}
export const isDef = (v: any) => {
return v !== undefined && v !== null
}
export const isTrue = (v: any) => {
return v === true
}
export const isFalse = (v: any) => {
return v === false
}
export const isPrimitive = (v: any) => {
return (
typeof v === 'string' ||
typeof v === 'number' ||
typeof v === 'symbol' ||
typeof v === 'boolean'
)
}
export const isObject = (obj: any) => {
return obj !== null && typeof obj === 'object' // 注意 null 在 typeof 的坑
}
export const isPromise = (val: any) => {
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function'
)
}
const _toString = Object.prototype.toString
export const toRawType = (val: any) => {
return _toString.call(val).slice(8, -1)
}
const hasOwnProperty = Object.prototype.hasOwnProperty
export const hasOwn = (obj: any, key: any) => {
return hasOwnProperty.call(obj, key)
}
export const toNumber = (val: any) => {
const n = parseFloat(val);
return isNaN(n) ? val : n
}
/**
* @param {any} obj The object to inspect.
* @returns {boolean} True if the argument appears to be a plain object.
*/
export function isPlainObject(obj) {
if (typeof obj !== 'object' || obj === null) return false
let proto = Object.getPrototypeOf(obj)
// 1. edge case Object.create(null)
if (proto === null) return true
let baseProto = proto
while (Object.getPrototypeOf(baseProto) !== null) {
baseProto = Object.getPrototypeOf(baseProto)
}
// 2. 原型链第一个和最后一个比较
return proto === baseProto
}
export const toString = (val: any) => {
return val == null
? ''
: Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
? JSON.stringify(val, null, 2) // 针对数组或对象
: String(val)
}
export function toArray (list, start) {
start = start || 0;
var i = list.length - start;
var ret = new Array(i);
while (i--) {
ret[i] = list[i + start];
}
return ret
}
export function extend (to, _from) {
for (var key in _from) {
to[key] = _from[key];
}
return to
}
export function toObject (arr) {
var res = {};
for (var i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i]);
}
}
return res
}
export function cached (fn) {
var cache = Object.create(null);
return (function cachedFn (str) {
var hit = cache[str]; // 进行缓存
return hit || (cache[str] = fn(str))
})
}
export const capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
});
export const hyphenate = cached(function (str) {
return str.replace(hyphenateRE, '-$1').toLowerCase()
});
export const camelize = cached(function (str) {
return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })
});
export function makeMap (
str,
expectsLowerCase
) {
var map = Object.create(null);
var list = str.split(',');
for (var i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase
? function (val) { return map[val.toLowerCase()]; }
: function (val) { return map[val]; }
}
export function looseEqual (a, b) {
// a、b恒等于,返回true
if (a === b) { return true }
var isObjectA = isObject(a);
var isObjectB = isObject(b);
// 判断是否为对象(引用类型)
if (isObjectA && isObjectB) {
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) {
// 若两者为数组,当长度一致时再递归判断每个数据项,不一致时返回false
return a.length === b.length && a.every(function (e, i) {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
// 若两者为Date类型,利用时间戳判断
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) {
// 若两者为对象,当长度一致时再递归判断每个属性值是否相同,不一致时返回false
var keysA = Object.keys(a);
var keysB = Object.keys(b);
return keysA.length === keysB.length && keysA.every(function (key) {
return looseEqual(a[key], b[key])
})
} else {
/* istanbul ignore next */
return false
}
} catch (e) {
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) {
// 若两者均不是对象(引用类型),转为字符串比较
return String(a) === String(b)
} else {
return false
}
}
export function remove (arr, item) {
if (arr.length) {
var index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1)
}
}
}
export function once (fn) {
var called = false;
return function () {
if (!called) {
called = true;
fn.apply(this, arguments);
}
}
}
export function looseCompareArrays(a, b) {
// 若长度不一致,返回false
if (a.length !== b.length)
return false;
let equal = true;
// 若长度一致,再逐个数组项进行对比
for (let i = 0; equal && i < a.length; i++) {
equal = looseEqual(a[i], b[i]);
}
return equal;
}
export const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true, // 可配置的
enumerable: false, // 不可枚举的
value
});
};
export const objectToString = Object.prototype.toString;
export const toTypeString = (value) => objectToString.call(value);
export const isArray = Array.isArray;
export const isMap = (val) => toTypeString(val) === '[object Map]';
export const isSet = (val) => toTypeString(val) === '[object Set]';
export const isDate = (val) => val instanceof Date;
export const isFunction = (val) => typeof val === 'function';
export const isString = (val) => typeof val === 'string';
export const isSymbol = (val) => typeof val === 'symbol';
export const isIntegerKey = (key) => isString(key) && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
遍历数组执行,利于一次性执行多个函数
export const invokeArrayFns = (fns, arg) => {
for (let i = 0; i < fns.length; i++) {
fns[i](arg);
}
};
利用Object.is,与严格比较运算符(===)的行为基本一致,但注意:+0不等于-0,NaN等于自身
export const hasChanged = (value, oldValue) => !Object.is(value, oldValue)