/*
* @Author: zhangyu
* @Email: zhangdulin@outlook.com
* @Date: 2021-06-16 17:43:38
* @LastEditors: zhangyu
* @LastEditTime: 2021-08-24 17:40:25
* @Description:
*/
import { isFunc, getType, compareSize } from '../judgement/index'
var has = Object.prototype.hasOwnProperty;
/**
* 检测是否为对象
* @param {object} obj 要检测的数据
*/
function isObject(obj) {
//typeof null => object
//toString.call(null) => [object Object]
return obj && toString.call(obj) === "[object Object]";
}
/**
* 检测是否为数组
* @param {object} obj 要检测的数据
*/
function isArray(obj) {
return toString.call(obj) === "[object Array]";
}
/*
* 数据克隆(深拷贝)
* @param {object} data 要克隆的对象
*/
export function deepCopy(data) {
if (!data) return data;
switch (typeof data) {
case "string":
case "number":
case "boolean":
return data;
}
var result;
if (isArray(data)) {
result = [];
for (var i = 0, len = data.length; i < len; i++) {
result[i] = deepCopy(data[i]);
}
} else if (isObject(data)) {
result = {};
for (var key in data) {
if (has.call(data, key)) result[key] = deepCopy(data[key]);
}
}
return result;
}
/**
* 给原型方法或属性添加别名 eg:alias(Array,"forEach","each");
* @param {object} obj 对象
* @param {string|object} name 属性名称或对象 eg: 'forEach' | {forEach:'each'}
* @param {string} aliasName 别名
*/
export function alias(obj, name, aliasName) {
if (!obj || !obj.prototype) return;
var prototype = obj.prototype;
if (typeof name == "string") {
prototype[aliasName] = prototype[name];
} else {
for (var key in name) {
if (has.call(name, key) && has.call(prototype, key)) prototype[name[key]] = prototype[key];
}
}
return obj;
}
/**
* 将源对象(source)的所有可枚举且目标对象(target)不存在的属性, 复制到目标对象
* @param {object} target 目标对象
* @param {object} source 源对象
* @param {boolean} forced 是否强制复制, 为true时将会覆盖目标对象同名属性, 默认为false
*/
export function extend(target, source, forced) {
if (!target || !source) return target;
for (var key in source) {
if (key == undefined || !has.call(source, key)) continue;
if (forced || target[key] === undefined) target[key] = source[key];
}
return target;
}
/**
* 将数组或类数组转换为键值对 eg: ['a','b'] => {a:0,b:1}
* @param {Array} list 要转换的数组
* @param {object|function} fv 默认值或处理函数(value,i) => [key,value]
* @param {boolean} ignoreCase 是否忽略大小写, 为true时将统一使用小写, 默认为false
*/
export function toMap(list, fv, ignoreCase) {
if (!list) return;
var map = {},
isFn = isFunc(fv),
hasValue = fv !== undefined;
for (var i = 0, len = list.length; i < len; i++) {
var key = list[i], value;
if (key == undefined) continue;
if (isFn) {
var kv = fv.call(list, key, i);
if (!kv) continue;
key = kv[0];
value = kv[1];
} else {
value = hasValue ? fv : i;
}
map[ignoreCase ? key.toLowerCase() : key] = value;
}
return map;
}
/**
* 将对象数组转换为键值对 eg: [{name:'a',value:1},{name:'b',value:2}] => {a:1,b:2}
* @param {array} list 要转换的对象数组
* @param {string} propKey 对象中作为键的属性 eg: name
* @param {string|boolean} propValue 对象中作为值的属性, 为true时将给对象增加index属性, 为空时将整个对象作为值
*/
function toObjectMap(list, propKey, propValue) {
if (!list) return;
var map = {}, isBuildIndex = false;
if (propValue === true) {
isBuildIndex = propValue;
propValue = undefined;
}
for (var i = 0, len = list.length; i < len; i++) {
var obj = list[i];
if (!obj || typeof obj != "object") continue;
if (isBuildIndex) obj.index = i;
map[obj[propKey]] = propValue ? obj[propValue] : obj;
}
return map;
}
/**
* 将目标对象中和源对象值不同的数据作为键值对返回
* @param {object} target 目标对象
* @param {object} source 源对象
* @param {Array.<string>} skipProps 要忽略比较的属性数组
* @param {string} skipPrefix 要忽略的属性前缀
*/
function getChangedData(target, source, skipProps, skipPrefix) {
if (!target) return undefined;
var map_skip_prop = skipProps ? toMap(skipProps, true) : {},
data_changed = {},
has_changed = false;
for (var key in target) {
if (!key || !has.call(target, key) || map_skip_prop[key] || (skipPrefix && key.indexOf(skipPrefix) == 0) || target[key] == source[key]) continue;
data_changed[key] = target[key];
has_changed = true;
}
return has_changed ? data_changed : undefined;
}
/**
* 目标和对象组合转换成数组 target{name:'1',age:'58'} formattedObject{name:'你好',age:'年龄'} => [{label:'你好':,value:'1'},{label:'年龄':,value:'58'}]
* @param target 目标对象
* @param formattedObject 格式化对象
* @param options K/V
*/
function objectConversionToList(target, formattedObject,options) {
let _options;
if (options) _options = options
else _options = { label: 'label', value: 'value' }
const returnList = [];
const { label, value } = _options
// 判断target类型
if (getType(target) === 'object') {
for (const key in formattedObject) {
if (Object.prototype.hasOwnProperty.call(formattedObject, key)) {
const getLabel = formattedObject[key];
const getValue = target[key]
returnList.push({
[label]: getLabel,
[value]: getValue
})
}
}
}
return returnList
}
/**
* 根据对象key排序
* @param {object} map 排序对象
* @param {boolean} isKeyUpSort 排序方式 默认顺序
*/
export function sortMapByKey(map, isKeyUpSort=true) {
const keys =[];
const isMap = getType(map) === 'map';
if (isMap) {
map.forEach((_, key) => {
keys.push(key);
});
} else {
for (const key in map) {
if (Object.prototype.hasOwnProperty.call(map, key)) {
keys.push(key)
}
}
}
if (isKeyUpSort) {
keys.sort((key1, key2) => compareSize(key2, key1));
} else {
keys.sort((key1, key2) => compareSize(key1, key2));
}
let newMap;
if (isMap) {
newMap = new Map();
keys.forEach(key => {
newMap.set(key, map.get(key));
});
} else {
newMap = {}
keys.forEach(key => {
newMap[key] = map[key]
});
}
return newMap;
}
/**
* 对象to 对象数组
* @param {object} target
*/
export function objectToArray(target) {
const arr = [];
if (getType(target) === 'object') {
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const item = target[key];
arr.push({ [key]: item })
}
}
} else if (getType(target) === 'map') {
target.forEach((value, key) => {
arr.push({ [key]: value })
})
}
return arr;
}
/**
* @description: 对象方法工具 hasKey:判断一个对象是否存在key; objEqual: 两个对象是否相等这两个对象的值只能是数字或字符串
* @param {*}
* @returns {number|boolean}
*/
export const objTools = {
/**
* 判断一个对象是否存在key,如果传入第二个参数key,则是判断这个obj对象是否存在key这个属性
* 如果没有传入key这个参数,则判断obj对象是否有键值对
*/
hasKey: (obj, key) => {
if (key) return key in obj;
else {
const keysArr = Object.keys(obj);
return keysArr.length;
}
},
// 两个对象是否相等这两个对象的值只能是数字或字符串
objEqual: (obj1, obj2) => {
const keysArr1 = Object.keys(obj1);
const keysArr2 = Object.keys(obj2);
if (keysArr1.length !== keysArr2.length) return false;
else if (keysArr1.length === 0 && keysArr2.length === 0) return true;
/* eslint-disable-next-line */ else {
return !keysArr1.some((key) => obj1[key] != obj2[key]);
}
},
alias,
extend,
toMap,
toObjectMap,
objectToArray,
getChangedData,
objectConversionToList,
sortMapByKey
}