xe-utils
Version:
JavaScript 函数库、工具类
2,113 lines (1,937 loc) • 124 kB
JavaScript
var setupDefaults = {
keyId: 1,
cookies: {
path: '/'
},
treeOptions: {
parentKey: 'parentId',
key: 'id',
children: 'children'
},
parseDateFormat: 'yyyy-MM-dd HH:mm:ss',
firstDayOfWeek: 1
};
function arrayEach (list, iterate, context) {
if (list) {
if (list.forEach) {
list.forEach(iterate, context);
} else {
for (var index = 0, len = list.length; index < len; index++) {
iterate.call(context, list[index], index, list);
}
}
}
}
var objectToString = Object.prototype.toString;
function helperCreateInInObjectString (type) {
return function (obj) {
return '[object ' + type + ']' === objectToString.call(obj)
}
}
/**
* 判断是否数组
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isArray = Array.isArray || helperCreateInInObjectString('Array');
/**
* 判断对象自身属性中是否具有指定的属性
*
* @param {Object} obj 对象
* @param {String/Number} key 键值
* @return {Boolean}
*/
function hasOwnProp (obj, key) {
return obj && obj.hasOwnProperty ? obj.hasOwnProperty(key) : false
}
function objectEach (obj, iterate, context) {
if (obj) {
for (var key in obj) {
if (hasOwnProp(obj, key)) {
iterate.call(context, obj[key], key, obj);
}
}
}
}
/**
* 迭代器
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
function each (obj, iterate, context) {
if (obj) {
return (isArray(obj) ? arrayEach : objectEach)(obj, iterate, context)
}
return obj
}
/* eslint-disable valid-typeof */
function helperCreateInTypeof (type) {
return function (obj) {
return typeof obj === type
}
}
/**
* 判断是否方法
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isFunction = helperCreateInTypeof('function');
function helperCreateGetObjects (name, getIndex) {
var proMethod = Object[name];
return function (obj) {
var result = [];
if (obj) {
if (proMethod) {
return proMethod(obj)
}
each(obj, getIndex > 1 ? function (key) {
result.push(['' + key, obj[key]]);
} : function () {
result.push(arguments[getIndex]);
});
}
return result
}
}
/**
* 获取对象所有属性
*
* @param {Object} obj 对象/数组
* @return {Array}
*/
var keys = helperCreateGetObjects('keys', 1);
function getCativeCtor (val, args) {
var Ctor = val.__proto__.constructor;
return args ? new Ctor(args) : new Ctor()
}
function handleValueClone (item, isDeep) {
return isDeep ? copyValue(item, isDeep) : item
}
function copyValue (val, isDeep) {
if (val) {
switch(objectToString.call(val)) {
case "[object Object]": {
var restObj = Object.create(Object.getPrototypeOf(val));
objectEach(val, function (item, key) {
restObj[key] = handleValueClone(item, isDeep);
});
return restObj
}
case "[object Date]":
case "[object RegExp]": {
return getCativeCtor(val, val.valueOf())
}
case "[object Array]":
case "[object Arguments]": {
var restArr = [];
arrayEach(val, function (item) {
restArr.push(handleValueClone(item, isDeep));
});
return restArr
}
case "[object Set]": {
var restSet = getCativeCtor(val);
restSet.forEach(function (item) {
restSet.add(handleValueClone(item, isDeep));
});
return restSet
}
case "[object Map]": {
var restMap = getCativeCtor(val);
restMap.forEach(function (item, key) {
restMap.set(key, handleValueClone(item, isDeep));
});
return restMap
}
}
}
return val
}
/**
* 浅拷贝/深拷贝
*
* @param {Object} obj 对象/数组
* @param {Boolean} deep 是否深拷贝
* @return {Object}
*/
function clone (obj, deep) {
if (obj) {
return copyValue(obj, deep)
}
return obj
}
var objectAssignFns = Object.assign;
function handleAssign (destination, args, isClone) {
var len = args.length;
for (var source, index = 1; index < len; index++) {
source = args[index];
arrayEach(keys(args[index]), isClone ? function (key) {
destination[key] = clone(source[key], isClone);
} : function (key) {
destination[key] = source[key];
});
}
return destination
}
/**
* 将一个或多个源对象复制到目标对象中
*
* @param {Object} target 目标对象
* @param {...Object}
* @return {Boolean}
*/
var assign = function (target) {
if (target) {
var args = arguments;
if (target === true) {
if (args.length > 1) {
target = isArray(target[1]) ? [] : {};
return handleAssign(target, args, true)
}
} else {
return objectAssignFns ? objectAssignFns.apply(Object, args) : handleAssign(target, args)
}
}
return target
};
var XEUtils = function () {};
function mixin () {
arrayEach(arguments, function (methods) {
each(methods, function (fn, name) {
XEUtils[name] = isFunction(fn) ? function () {
var result = fn.apply(XEUtils.$context, arguments);
XEUtils.$context = null;
return result
} : fn;
});
});
}
function setConfig (options) {
return assign(setupDefaults, options)
}
function getConfig () {
return setupDefaults
}
var version = '4.0.9';
XEUtils.VERSION = version;
XEUtils.version = version;
XEUtils.mixin = mixin;
XEUtils.setup = setConfig;
XEUtils.setConfig = setConfig;
XEUtils.getConfig = getConfig;
function lastArrayEach (obj, iterate, context) {
for (var len = obj.length - 1; len >= 0; len--) {
iterate.call(context, obj[len], len, obj);
}
}
function lastObjectEach (obj, iterate, context) {
lastArrayEach(keys(obj), function (key) {
iterate.call(context, obj[key], key, obj);
});
}
/**
* 判断是否为Null
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isNull (obj) {
return obj === null
}
/**
* 返回一个获取对象属性的函数
*
* @param {String} name 属性名
* @param {Object} defs 空值
*/
function property (name, defs) {
return function (obj) {
return isNull(obj) ? defs : obj[name]
}
}
/**
* 指定方法后的返回值组成的新对象
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
function objectMap (obj, iterate, context) {
var result = {};
if (obj) {
if (iterate) {
if (!isFunction(iterate)) {
iterate = property(iterate);
}
each(obj, function (val, index) {
result[index] = iterate.call(context, val, index, obj);
});
} else {
return obj
}
}
return result
}
/**
* 判断是否对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isPlainObject (obj) {
return obj ? obj.constructor === Object : false
}
function helperCheckCopyKey (key) {
return key !== '__proto__' && key !== 'constructor'
}
function handleMerge (target, source) {
if ((isPlainObject(target) && isPlainObject(source)) || (isArray(target) && isArray(source))) {
each(source, function (val, key) {
if (helperCheckCopyKey(key)) {
target[key] = isFunction(source) ? val : handleMerge(target[key], val);
}
});
return target
}
return clone(source, true)
}
/**
* 将一个或多个源对象合并到目标对象中
*
* @param {Object} target 目标对象
* @param {...Object}
* @return {Boolean}
*/
var merge = function (target) {
if (!target) {
target = {};
}
var args = arguments;
var len = args.length;
for (var source, i = 1; i < len; i++) {
source = args[i];
if (source) {
handleMerge(target, source);
}
}
return target
};
/**
* 指定方法后的返回值组成的新数组
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Array}
*/
function map (obj, iterate, context) {
var result = [];
if (obj && arguments.length > 1) {
if (obj.map) {
return obj.map(iterate, context)
} else {
each(obj, function () {
result.push(iterate.apply(context, arguments));
});
}
}
return result
}
function helperCreateIterateHandle (prop, useArray, restIndex, matchValue, defaultValue) {
return function (obj, iterate, context) {
if (obj && iterate) {
if (prop && obj[prop]) {
return obj[prop](iterate, context)
} else {
if (useArray && isArray(obj)) {
for (var index = 0, len = obj.length; index < len; index++) {
if (!!iterate.call(context, obj[index], index, obj) === matchValue) {
return [true, false, index, obj[index]][restIndex]
}
}
} else {
for (var key in obj) {
if (hasOwnProp(obj, key)) {
if (!!iterate.call(context, obj[key], key, obj) === matchValue) {
return [true, false, key, obj[key]][restIndex]
}
}
}
}
}
}
return defaultValue
}
}
/**
* 对象中的值中的每一项运行给定函数,如果函数对任一项返回true,则返回true,否则返回false
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Boolean}
*/
var some = helperCreateIterateHandle('some', 1, 0, true, false);
/**
* 对象中的值中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true,否则返回false
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Boolean}
*/
var every = helperCreateIterateHandle('every', 1, 1, false, true);
/**
* 判断对象是否包含该值,成功返回true否则false
*
* @param {Object} obj 对象
* @param {Object} val 值
* @return {Boolean}
*/
function includes (obj, val) {
if (obj) {
if (obj.includes) {
return obj.includes(val)
}
for (var key in obj) {
if (hasOwnProp(obj, key)) {
if (val === obj[key]) {
return true
}
}
}
}
return false
}
/**
* 判断数组是否包含另一数组
*
* @param {Array} array1 数组
* @param {Array} array2 被包含数组
* @return {Boolean}
*/
function includeArrays (array1, array2) {
var len;
var index = 0;
if (isArray(array1) && isArray(array2)) {
for (len = array2.length; index < len; index++) {
if (!includes(array1, array2[index])) {
return false
}
}
return true
}
return includes(array1, array2)
}
/**
* 数组去重
*
* @param {*} array 数组
* @param {*} iterate 字段或回调
* @param {*} context
* @returns
*/
function uniq (array, iterate, context) {
var result = [];
if (iterate) {
if (!isFunction(iterate)) {
iterate = property(iterate);
}
var val, valMap = {};
each(array, function (item, key) {
val = iterate.call(context, item, key, array);
if (!valMap[val]) {
valMap[val] = 1;
result.push(item);
}
});
} else {
each(array, function (value) {
if (!includes(result, value)) {
result.push(value);
}
});
}
return result
}
/**
* 将对象或者伪数组转为新数组
*
* @param {Array} list 数组
* @return {Array}
*/
function toArray (list) {
return map(list, function (item) {
return item
})
}
/**
* 将多个数的值返回唯一的并集数组
*
* @param {...Array} 数组
* @return {Array}
*/
function union () {
var args = arguments;
var result = [];
var index = 0;
var len = args.length;
for (; index < len; index++) {
result = result.concat(toArray(args[index]));
}
return uniq(result)
}
var staticStrUndefined = 'undefined';
/**
* 判断是否Undefined
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isUndefined = helperCreateInTypeof(staticStrUndefined);
/**
* 判断是否 undefined 和 null
* @param {Object} obj 对象
* @return {Boolean}
*/
function eqNull (obj) {
return isNull(obj) || isUndefined(obj)
}
var staticHGKeyRE = /(.+)?\[(\d+)\]$/;
function helperGetHGSKeys (property) {
// 以最快的方式判断数组,可忽略准确性
return property ? (property.splice && property.join ? property : ('' + property).replace(/(\[\d+\])\.?/g,'$1.').replace(/\.$/, '').split('.')) : []
}
/**
* 获取对象的属性的值,如果值为 undefined,则返回默认值
* @param {Object/Array} obj 对象
* @param {String/Function} property 键、路径
* @param {Object} defaultValue 默认值
* @return {Object}
*/
function get (obj, property, defaultValue) {
if (eqNull(obj)) {
return defaultValue
}
var result = getValueByPath(obj, property);
return isUndefined(result) ? defaultValue : result
}
function getDeepProps (obj, key) {
var matchs = key ? key.match(staticHGKeyRE) : '';
return matchs ? (matchs[1] ? (obj[matchs[1]] ? obj[matchs[1]][matchs[2]] : undefined) : obj[matchs[2]]) : obj[key]
}
function getValueByPath (obj, property) {
if (obj) {
var rest, props, len;
var index = 0;
if (obj[property] || hasOwnProp(obj, property)) {
return obj[property]
} else {
props = helperGetHGSKeys(property);
len = props.length;
if (len) {
for (rest = obj; index < len; index++) {
rest = getDeepProps(rest, props[index]);
if (eqNull(rest)) {
if (index === len - 1) {
return rest
}
return
}
}
}
return rest
}
}
}
var ORDER_PROP_ASC = 'asc';
var ORDER_PROP_DESC = 'desc';
// function handleSort (v1, v2) {
// return v1 > v2 ? 1 : -1
// }
// '' < 数字 < 字符 < null < undefined
function handleSort (v1, v2) {
if (isUndefined(v1)) {
return 1
}
if (isNull(v1)) {
return isUndefined(v2) ? -1 : 1
}
return v1 && v1.localeCompare ? v1.localeCompare(v2) : (v1 > v2 ? 1 : -1)
}
function buildMultiOrders (name, confs, compares) {
return function (item1, item2) {
var v1 = item1[name];
var v2 = item2[name];
if (v1 === v2) {
return compares ? compares(item1, item2) : 0
}
return confs.order === ORDER_PROP_DESC ? handleSort(v2, v1) : handleSort(v1, v2)
}
}
function getSortConfs (arr, list, fieldConfs, context) {
var sortConfs = [];
fieldConfs = isArray(fieldConfs) ? fieldConfs : [fieldConfs];
arrayEach(fieldConfs, function (handle, index) {
if (handle) {
var field = handle;
var order;
if (isArray(handle)) {
field = handle[0];
order = handle[1];
} else if (isPlainObject(handle)) {
field = handle.field;
order = handle.order;
}
sortConfs.push({
field: field,
order: order || ORDER_PROP_ASC
});
arrayEach(list, isFunction(field) ? function (item, key) {
item[index] = field.call(context, item.data, key, arr);
} : function (item) {
item[index] = field ? get(item.data, field) : item.data;
});
}
});
return sortConfs
}
/**
* 将数组进行排序
*
* @param {Array} arr 数组
* @param {Function/String/Array} fieldConfs 方法或属性
* @param {Object} context 上下文
* @return {Array}
*/
function orderBy (arr, fieldConfs, context) {
if (arr) {
if (eqNull(fieldConfs)) {
return toArray(arr).sort(handleSort)
}
var compares;
var list = map(arr, function (item) {
return { data: item }
});
var sortConfs = getSortConfs(arr, list, fieldConfs, context);
var len = sortConfs.length - 1;
while (len >= 0) {
compares = buildMultiOrders(len, sortConfs[len], compares);
len--;
}
if (compares) {
list = list.sort(compares);
}
return map(list, property('data'))
}
return []
}
var sortBy = orderBy;
/**
* 获取一个指定范围内随机数
*
* @param {Number} minVal 最小值
* @param {Number} maxVal 最大值
* @return {Number}
*/
function random (minVal, maxVal) {
return minVal >= maxVal ? minVal : ((minVal = minVal >> 0) + Math.round(Math.random() * ((maxVal || 9) - minVal)))
}
/**
* 获取对象所有值
*
* @param {Object} obj 对象/数组
* @return {Array}
*/
var values = helperCreateGetObjects('values', 0);
/**
* 将一个数组随机打乱,返回一个新的数组
*
* @param {Array} array 数组
* @return {Array}
*/
function shuffle (array) {
var index;
var result = [];
var list = values(array);
var len = list.length - 1;
for (; len >= 0; len--) {
index = len > 0 ? random(0, len) : 0;
result.push(list[index]);
list.splice(index, 1);
}
return result
}
/**
* 从一个数组中随机返回几个元素
*
* @param {Array} array 数组
* @param {Number} number 个数
* @return {Array}
*/
function sample (array, number) {
var result = shuffle(array);
if (arguments.length <= 1) {
return result[0]
}
if (number < result.length) {
result.length = number || 0;
}
return result
}
function helperCreateToNumber (handle) {
return function (str) {
if (str) {
var num = handle(str && str.replace ? str.replace(/,/g, '') : str);
if (!isNaN(num)) {
return num
}
}
return 0
}
}
/**
* 转数值
* @param { String/Number } str 数值
*
* @return {Number}
*/
var toNumber = helperCreateToNumber(parseFloat);
/**
* 裁剪 Arguments 或数组 array,从 start 位置开始到 end 结束,但不包括 end 本身的位置
* @param {Array/Arguments} array 数组或Arguments
* @param {Number} startIndex 开始索引
* @param {Number} endIndex 结束索引
*/
function slice (array, startIndex, endIndex) {
var result = [];
var argsSize = arguments.length;
if (array) {
startIndex = argsSize >= 2 ? toNumber(startIndex) : 0;
endIndex = argsSize >= 3 ? toNumber(endIndex) : array.length;
if (array.slice) {
return array.slice(startIndex, endIndex)
}
for (; startIndex < endIndex; startIndex++) {
result.push(array[startIndex]);
}
}
return result
}
/**
* 根据回调过滤数据
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
function filter (obj, iterate, context) {
var result = [];
if (obj && iterate) {
if (obj.filter) {
return obj.filter(iterate, context)
}
each(obj, function (val, key) {
if (iterate.call(context, val, key, obj)) {
result.push(val);
}
});
}
return result
}
/**
* 查找匹配第一条数据的键
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
var findKey = helperCreateIterateHandle('', 0, 2, true);
/**
* 从左至右遍历,匹配最近的一条数据
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
var find = helperCreateIterateHandle('find', 1, 3, true);
/**
* 从右至左遍历,匹配最近的一条数据
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
function findLast (obj, iterate, context) {
if (obj) {
if (!isArray(obj)) {
obj = values(obj);
}
for (var len = obj.length - 1; len >= 0; len--) {
if (iterate.call(context, obj[len], len, obj)) {
return obj[len]
}
}
}
}
/**
* 接收一个函数作为累加器,数组中的每个值(从左到右)开始合并,最终为一个值。
*
* @param {Array} array 数组
* @param {Function} callback 方法
* @param {Object} initialValue 初始值
* @return {Number}
*/
function reduce (array, callback, initialValue) {
if (array) {
var len, reduceMethod;
var index = 0;
var context = null;
var previous = initialValue;
var isInitialVal = arguments.length > 2;
var keyList = keys(array);
if (array.length && array.reduce) {
reduceMethod = function () {
return callback.apply(context, arguments)
};
if (isInitialVal) {
return array.reduce(reduceMethod, previous)
}
return array.reduce(reduceMethod)
}
if (isInitialVal) {
index = 1;
previous = array[keyList[0]];
}
for (len = keyList.length; index < len; index++) {
previous = callback.call(context, previous, array[keyList[index]], index, array);
}
return previous
}
}
/**
* 浅复制数组的一部分到同一数组中的另一个位置,数组大小不变
*
* @param {Array} array 数组
* @param {Number} target 从该位置开始替换数据
* @param {Number} start 从该位置开始读取数据,默认为 0 。如果为负值,表示倒数
* @param {Number} end 到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数
* @return {Array}
*/
function copyWithin (array, target, start, end) {
if (isArray(array) && array.copyWithin) {
return array.copyWithin(target, start, end)
}
var replaceIndex, replaceArray;
var targetIndex = target >> 0;
var startIndex = start >> 0;
var len = array.length;
var endIndex = arguments.length > 3 ? end >> 0 : len;
if (targetIndex < len) {
targetIndex = targetIndex >= 0 ? targetIndex : len + targetIndex;
if (targetIndex >= 0) {
startIndex = startIndex >= 0 ? startIndex : len + startIndex;
endIndex = endIndex >= 0 ? endIndex : len + endIndex;
if (startIndex < endIndex) {
for (replaceIndex = 0, replaceArray = array.slice(startIndex, endIndex); targetIndex < len; targetIndex++) {
if (replaceArray.length <= replaceIndex) {
break
}
array[targetIndex] = replaceArray[replaceIndex++];
}
}
}
}
return array
}
/**
* 将一个数组分割成大小的组。如果数组不能被平均分配,那么最后一块将是剩下的元素
*
* @param {Array} array 数组
* @param {Number} size 每组大小
* @return {Array}
*/
function chunk (array, size) {
var index;
var result = [];
var arrLen = size >> 0 || 1;
if (isArray(array)) {
if (arrLen >= 0 && array.length > arrLen) {
index = 0;
while (index < array.length) {
result.push(array.slice(index, index + arrLen));
index += arrLen;
}
} else {
result = array.length ? [array] : array;
}
}
return result
}
/**
* 获取数组对象中某属性值,返回一个数组
*
* @param {Array} array 数组
* @param {String} key 属性值
* @return {Array}
*/
function pluck (obj, key) {
return map(obj, property(key))
}
function helperCreateMinMax (handle) {
return function (arr, iterate) {
if (arr && arr.length) {
var rest, itemIndex;
arrayEach(arr, function (itemVal, index) {
if (iterate) {
itemVal = isFunction(iterate) ? iterate(itemVal, index, arr) : get(itemVal, iterate);
}
if (!eqNull(itemVal) && (eqNull(rest) || handle(rest, itemVal))) {
itemIndex = index;
rest = itemVal;
}
});
return arr[itemIndex]
}
return rest
}
}
/**
* 获取最大值
*
* @param {Array} arr 数组
* @param {Function} iterate(item, index, obj) 回调
* @return {Number}
*/
var max = helperCreateMinMax(function (rest, itemVal) {
return rest < itemVal
});
/**
* 与 zip 相反
*
* @param {Array} arrays 数组集合
*/
function unzip (arrays) {
var index, maxItem, len;
var result = [];
if (arrays && arrays.length) {
index = 0;
maxItem = max(arrays, function (item) {
return item ? item.length : 0
});
for (len = maxItem ? maxItem.length : 0; index < len; index++) {
result.push(pluck(arrays, index));
}
}
return result
}
/**
* 将每个数组中相应位置的值合并在一起
*
* @param {Array*} array 数组
*/
function zip () {
return unzip(arguments)
}
/**
* 根据键数组、值数组对转换为对象
*
* @param {Array} props 键数组
* @param {Number} arr 值数组
* @return {Object}
*/
function zipObject (props, arr) {
var result = {};
arr = arr || [];
each(values(props), function (val, key) {
result[val] = arr[key];
});
return result
}
function flattenDeep (array, deep) {
var result = [];
arrayEach(array, function (vals) {
result = result.concat(isArray(vals) ? (deep ? flattenDeep(vals, deep) : vals) : [vals]);
});
return result
}
/**
* 将一个多维数组铺平
* @param {Array} array 数组
* @param {Boolean} deep 是否深层
* @return {Array}
*/
function flatten (array, deep) {
if (isArray(array)) {
return flattenDeep(array, deep)
}
return []
}
function deepGetObj (obj, path) {
var index = 0;
var len = path.length;
while (obj && index < len) {
obj = obj[path[index++]];
}
return len && obj ? obj : 0
}
/**
* 在list的每个元素上执行方法,任何传递的额外参数都会在调用方法的时候传递给它
*
* @param {Array} list
* @param {Array/String/Function} path
* @param {...Object} arguments
* @return {Array}
*/
function invoke (list, path) {
var func;
var args = arguments;
var params = [];
var paths = [];
var index = 2;
var len = args.length;
for (; index < len; index++) {
params.push(args[index]);
}
if (isArray(path)) {
len = path.length - 1;
for (index = 0; index < len; index++) {
paths.push(path[index]);
}
path = path[len];
}
return map(list, function (context) {
if (paths.length) {
context = deepGetObj(context, paths);
}
func = context[path] || path;
if (func && func.apply) {
return func.apply(context, params)
}
})
}
function helperLog (type, msg) {
return (console[type] || console.log)(msg)
}
function helperDeleteProperty (obj, property) {
try {
delete obj[property];
} catch (e) {
obj[property] = undefined;
}
}
/**
* 迭代器,从最后开始迭代
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
function lastEach (obj, iterate, context) {
if (obj) {
return (isArray(obj) ? lastArrayEach : lastObjectEach)(obj, iterate, context)
}
return obj
}
/**
* 判断是否Object对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isObject = helperCreateInTypeof('object');
/**
* 清空对象
*
* @param {Object} obj 对象
* @param {*} defs 默认值,如果不传(清空所有属性)、如果传对象(清空并继承)、如果传值(给所有赋值)
* @param {Object/Array} assigns 默认值
* @return {Object}
*/
function clear (obj, defs, assigns) {
if (obj) {
var len;
var isDefs = arguments.length > 1 && (isNull(defs) || !isObject(defs));
var extds = isDefs ? assigns : defs;
if (isPlainObject(obj)) {
objectEach(obj, isDefs ? function (val, key) {
obj[key] = defs;
} : function (val, key) {
helperDeleteProperty(obj, key);
});
if (extds) {
assign(obj, extds);
}
} else if (isArray(obj)) {
if (isDefs) {
len = obj.length;
while (len > 0) {
len--;
obj[len] = defs;
}
} else {
obj.length = 0;
}
if (extds) {
obj.push.apply(obj, extds);
}
}
}
return obj
}
function pluckProperty (name) {
return function (obj, key) {
return key === name
}
}
/**
* 移除对象属性
*
* @param {Object/Array} obj 对象/数组
* @param {Function/String} iterate 方法或属性
* @param {Object} context 上下文
* @return {Object/Array}
*/
function remove (obj, iterate, context) {
if (obj) {
if (!eqNull(iterate)) {
var removeKeys = [];
var rest = [];
if (!isFunction(iterate)) {
iterate = pluckProperty(iterate);
}
each(obj, function (item, index, rest) {
if (iterate.call(context, item, index, rest)) {
removeKeys.push(index);
}
});
if (isArray(obj)) {
lastEach(removeKeys, function (item, key) {
rest.push(obj[item]);
obj.splice(item, 1);
});
} else {
rest = {};
arrayEach(removeKeys, function (key) {
rest[key] = obj[key];
helperDeleteProperty(obj, key);
});
}
return rest
}
return clear(obj)
}
return obj
}
function strictTree (array, optChildren) {
each(array, function (item) {
if (item[optChildren] && !item[optChildren].length) {
remove(item, optChildren);
}
});
}
/**
* 将一个带层级的数据列表转成树结构
*
* @param {Array} array 数组
* @param {Object} options {strict: false, parentKey: 'parentId', key: 'id', children: 'children', mapChildren: 'children', data: 'data'}
* @return {Array}
*/
function toArrayTree (array, options) {
var opts = assign({}, setupDefaults.treeOptions, options);
var optStrict = opts.strict;
var optKey = opts.key;
var optParentKey = opts.parentKey;
var optChildren = opts.children;
var optMapChildren = opts.mapChildren;
var optRootValues = opts.rootValues;
var optRootParentVal = opts.rootParentValue;
var optSortKey = opts.sortKey;
var optReverse = opts.reverse;
var optData = opts.data;
var result = [];
var defTreeMaps = {};
var empTreeMaps = {};
var idDefMaps = {};
var idEmpMaps = {};
var rootIdMaps = {};
var isDefaultRootParentVal = optRootParentVal === undefined;
var id, treeData, parentId, idMaps, isIdNull, isPdNull, idTreeMaps, pdTreeMaps;
if (optSortKey) {
array = orderBy(clone(array), optSortKey);
if (optReverse) {
array = array.reverse();
}
}
if (optRootValues && optRootValues.length) {
each(optRootValues, function (v) {
rootIdMaps[v] = 1;
});
}
each(array, function (item) {
id = item[optKey];
idMaps = eqNull(id) ? idEmpMaps : idDefMaps;
if (idMaps[id]) {
helperLog('warn', 'Duplicate primary key=' + id);
}
idMaps[id] = true;
});
each(array, function (item) {
id = item[optKey];
isIdNull = eqNull(id);
if (optData) {
treeData = {};
treeData[optData] = item;
} else {
treeData = item;
}
parentId = item[optParentKey];
isPdNull = eqNull(parentId);
idTreeMaps = isIdNull ? empTreeMaps : defTreeMaps;
idTreeMaps[id] = idTreeMaps[id] || [];
treeData[optKey] = id;
treeData[optParentKey] = parentId;
if (id === parentId) {
parentId = null;
helperLog('warn', 'Error infinite Loop. key=' + id + ' parentKey=' + id);
}
pdTreeMaps = isPdNull ? empTreeMaps : defTreeMaps;
idMaps = isPdNull ? idEmpMaps : idDefMaps;
pdTreeMaps[parentId] = pdTreeMaps[parentId] || [];
pdTreeMaps[parentId].push(treeData);
treeData[optChildren] = idTreeMaps[id];
if (optMapChildren) {
treeData[optMapChildren] = idTreeMaps[id];
}
if (optRootValues && optRootValues.length) {
if (rootIdMaps[id]) {
result.push(treeData);
}
} else if (isDefaultRootParentVal) {
if (!optStrict || (optStrict && isPdNull)) {
if (!idMaps[parentId]) {
result.push(treeData);
}
}
} else {
if (parentId === optRootParentVal) {
result.push(treeData);
}
}
});
if (optStrict) {
strictTree(array, optChildren);
}
return result
}
function unTreeList (result, parentItem, array, opts) {
var optKey = opts.key;
var optParentKey = opts.parentKey;
var optChildren = opts.children;
var optData = opts.data;
var optUpdated = opts.updated;
var optClear = opts.clear;
arrayEach(array, function (item) {
var childList = item[optChildren];
if (optData) {
item = item[optData];
}
if (optUpdated !== false) {
item[optParentKey] = parentItem ? parentItem[optKey] : null;
}
result.push(item);
if (childList && childList.length) {
unTreeList(result, item, childList, opts);
}
if (optClear) {
delete item[optChildren];
}
});
return result
}
/**
* 将一个树结构转成数组列表
*
* @param {Array} array 数组
* @param {Object} options { children: 'children', data: 'data', clear: false }
* @return {Array}
*/
function toTreeArray (array, options) {
return unTreeList([], null, array, assign({}, setupDefaults.treeOptions, options))
}
function helperCreateTreeFunc (handle) {
return function (obj, iterate, options, context) {
var opts = options || {};
var optChildren = opts.children || 'children';
return handle(null, obj, iterate, context, [], [], optChildren, opts)
}
}
function findTreeItem (parent, obj, iterate, context, path, node, parseChildren, opts) {
if (obj) {
var item, index, len, paths, nodes, match;
for (index = 0, len = obj.length; index < len; index++) {
item = obj[index];
paths = path.concat(['' + index]);
nodes = node.concat([item]);
if (iterate.call(context, item, index, obj, paths, parent, nodes)) {
return { index: index, item: item, path: paths, items: obj, parent: parent, nodes: nodes }
}
if (parseChildren && item) {
match = findTreeItem(item, item[parseChildren], iterate, context, paths.concat([parseChildren]), nodes, parseChildren);
if (match) {
return match
}
}
}
}
}
/**
* 从树结构中查找匹配第一条数据的键、值、路径
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, items, path, parent, nodes) 回调
* @param {Object} options {children: 'children'}
* @param {Object} context 上下文
* @return {Object} { item, index, items, path, parent, nodes }
*/
var findTree = helperCreateTreeFunc(findTreeItem);
function eachTreeItem (parent, obj, iterate, context, path, node, parseChildren, opts) {
var paths, nodes;
each(obj, function (item, index) {
paths = path.concat(['' + index]);
nodes = node.concat([item]);
iterate.call(context, item, index, obj, paths, parent, nodes);
if (item && parseChildren) {
paths.push(parseChildren);
eachTreeItem(item, item[parseChildren], iterate, context, paths, nodes, parseChildren);
}
});
}
/**
* 从树结构中遍历数据的键、值、路径
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, items, path, parent, nodes) 回调
* @param {Object} options {children: 'children', mapChildren: 'children}
* @param {Object} context 上下文
*/
var eachTree = helperCreateTreeFunc(eachTreeItem);
function mapTreeItem (parent, obj, iterate, context, path, node, parseChildren, opts) {
var paths, nodes, rest;
var mapChildren = opts.mapChildren || parseChildren;
return map(obj, function (item, index) {
paths = path.concat(['' + index]);
nodes = node.concat([item]);
rest = iterate.call(context, item, index, obj, paths, parent, nodes);
if (rest && item && parseChildren && item[parseChildren]) {
rest[mapChildren] = mapTreeItem(item, item[parseChildren], iterate, context, paths, nodes, parseChildren, opts);
}
return rest
})
}
/**
* 从树结构中指定方法后的返回值组成的新数组
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, items, path, parent, nodes) 回调
* @param {Object} options {children: 'children'}
* @param {Object} context 上下文
* @return {Object/Array}
*/
var mapTree = helperCreateTreeFunc(mapTreeItem);
/**
* 从树结构中根据回调过滤数据
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, items, path, parent) 回调
* @param {Object} options {children: 'children'}
* @param {Object} context 上下文
* @return {Array}
*/
function filterTree (obj, iterate, options, context) {
var result = [];
if (obj && iterate) {
eachTree(obj, function (item, index, items, path, parent, nodes) {
if (iterate.call(context, item, index, items, path, parent, nodes)) {
result.push(item);
}
}, options);
}
return result
}
function searchTreeItem (matchParent, parent, obj, iterate, context, path, node, parseChildren, opts) {
var paths, nodes, rest, isMatch, hasChild;
var rests = [];
var hasOriginal = opts.original;
var sourceData = opts.data;
var mapChildren = opts.mapChildren || parseChildren;
var isEvery = opts.isEvery;
arrayEach(obj, function (item, index) {
paths = path.concat(['' + index]);
nodes = node.concat([item]);
isMatch = (matchParent && !isEvery) || iterate.call(context, item, index, obj, paths, parent, nodes);
hasChild = parseChildren && item[parseChildren];
if (isMatch || hasChild) {
if (hasOriginal) {
rest = item;
} else {
rest = assign({}, item);
if (sourceData) {
rest[sourceData] = item;
}
}
rest[mapChildren] = searchTreeItem(isMatch, item, item[parseChildren], iterate, context, paths, nodes, parseChildren, opts);
if (isMatch || rest[mapChildren].length) {
rests.push(rest);
}
} else if (isMatch) {
rests.push(rest);
}
});
return rests
}
/**
* 从树结构中根据回调查找数据
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, items, path, parent, nodes) 回调
* @param {Object} options {children: 'children'}
* @param {Object} context 上下文
* @return {Array}
*/
var searchTree = helperCreateTreeFunc(function (parent, obj, iterate, context, path, nodes, parseChildren, opts) {
return searchTreeItem(0, parent, obj, iterate, context, path, nodes, parseChildren, opts)
});
function arrayIndexOf (list, val) {
if (list.indexOf) {
return list.indexOf(val)
}
for (var index = 0, len = list.length; index < len; index++) {
if (val === list[index]) {
return index
}
}
}
function arrayLastIndexOf (list, val) {
if (list.lastIndexOf) {
return list.lastIndexOf(val)
}
for (var len = list.length - 1; len >= 0; len--) {
if (val === list[len]) {
return len
}
}
return -1
}
/**
* 判断是否Number对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isNumber = helperCreateInTypeof('number');
/* eslint-disable eqeqeq */
function isNumberNaN (obj) {
return isNumber(obj) && isNaN(obj)
}
/**
* 判断是否String对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isString = helperCreateInTypeof('string');
/**
* 判断是否Date对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isDate = helperCreateInInObjectString('Date');
var staticParseInt = parseInt;
function helperGetUTCDateTime (resMaps) {
return Date.UTC(resMaps.y, resMaps.M || 0, resMaps.d || 1, resMaps.H || 0, resMaps.m || 0, resMaps.s || 0, resMaps.S || 0)
}
function helperGetDateTime (date) {
return date.getTime()
}
function getParseRule (txt) {
return '(\\d{' + txt + '})'
}
function toParseMs (num) {
if (num < 10) {
return num * 100
} else if (num < 100) {
return num * 10
}
return num
}
function toParseNum (num) {
return isNaN(num) ? num : staticParseInt(num)
}
var d2 = getParseRule(2);
var d1or2 = getParseRule('1,2');
var d1or7 = getParseRule('1,7');
var d3or4 = getParseRule('3,4');
var place = '.{1}';
var d1Or2RE = place + d1or2;
var dzZ = '(([zZ])|([-+]\\d{2}:?\\d{2}))';
var defaulParseStrs = [d3or4, d1Or2RE, d1Or2RE, d1Or2RE, d1Or2RE, d1Or2RE, place + d1or7, dzZ];
var defaulParseREs = [];
for (var len = defaulParseStrs.length - 1; len >= 0; len--) {
var rule = '';
for (var i = 0; i < len + 1; i++) {
rule += defaulParseStrs[i];
}
defaulParseREs.push(new RegExp('^' + rule));
}
/**
* 解析默认格式
*/
function parseDefaultRules (str) {
var matchRest, resMaps = {};
for (var i = 0, dfrLen = defaulParseREs.length; i < dfrLen; i++) {
matchRest = str.match(defaulParseREs[i]);
if (matchRest) {
resMaps.y = matchRest[1];
resMaps.M = matchRest[2];
resMaps.d = matchRest[3];
resMaps.H = matchRest[4];
resMaps.m = matchRest[5];
resMaps.s = matchRest[6];
resMaps.S = matchRest[7];
resMaps.Z = matchRest[8];
break
}
}
return resMaps
}
var customParseStrs = [
['yyyy', d3or4],
['yy', d2],
['MM', d2],
['M', d1or2],
['dd', d2],
['d', d1or2],
['HH', d2],
['H', d1or2],
['mm', d2],
['m', d1or2],
['ss', d2],
['s', d1or2],
['SSS', getParseRule(3)],
['S', d1or7],
['Z', dzZ]
];
var parseRuleMaps = {};
var parseRuleKeys = ['\\[([^\\]]+)\\]'];
for (var i = 0; i < customParseStrs.length; i++) {
var itemRule = customParseStrs[i];
parseRuleMaps[itemRule[0]] = itemRule[1] + '?';
parseRuleKeys.push(itemRule[0]);
}
var customParseRes = new RegExp(parseRuleKeys.join('|'), 'g');
var cacheFormatMaps = {};
/**
* 解析自定义格式
*/
function parseCustomRules (str, format) {
var cacheItem = cacheFormatMaps[format];
if (!cacheItem) {
var posIndexs = [];
var re = format.replace(/([$(){}*+.?\\^|])/g, "\\$1").replace(customParseRes, function (text, val) {
var firstChar = text.charAt(0);
// 如果为转义符号:[关键字]
if (firstChar === '[') {
return val
}
posIndexs.push(firstChar);
return parseRuleMaps[text]
});
cacheItem = cacheFormatMaps[format] = {
_i: posIndexs,
_r: new RegExp(re)
};
}
var resMaps = {};
var matchRest = str.match(cacheItem._r);
if (matchRest) {
var _i = cacheItem._i;
for (var i = 1, len = matchRest.length; i < len; i++) {
resMaps[_i[i - 1]] = matchRest[i];
}
return resMaps
}
return resMaps
}
/**
* 解析时区
*/
function parseTimeZone (resMaps) {
// 如果为UTC 时间
if (/^[zZ]/.test(resMaps.Z)) {
return new Date(helperGetUTCDateTime(resMaps))
} else {
// 如果指定时区,时区转换
var matchRest = resMaps.Z.match(/([-+])(\d{2}):?(\d{2})/);
if (matchRest) {
return new Date(helperGetUTCDateTime(resMaps) - (matchRest[1] === '-' ? -1 : 1) * staticParseInt(matchRest[2]) * 3600000 + staticParseInt(matchRest[3]) * 60000)
}
}
return new Date('')
}
/**
* 字符串转为日期
*
* @param {String/Number/Date} str 日期或数字
* @param {String} format 解析日期格式(yyyy年份、MM月份、dd天、hh(12)HH(24)小时、mm分钟、ss秒、SSS毫秒、Z时区)
* @return {Date}
*/
function toStringDate (str, format) {
if (str) {
var isDType = isDate(str);
if (isDType || (!format && /^[0-9]{11,15}$/.test(str))) {
return new Date(isDType ? helperGetDateTime(str) : staticParseInt(str))
}
if (isString(str)) {
var resMaps = format ? parseCustomRules(str, format) : parseDefaultRules(str);
if (resMaps.y) {
if (resMaps.M) {
resMaps.M = toParseNum(resMaps.M) - 1;
}
if (resMaps.S) {
// 如果7位则是微秒,只精确到3位毫秒
resMaps.S = toParseMs(toParseNum(resMaps.S.substring(0, 3)));
}
if (resMaps.Z) {
return parseTimeZone(resMaps)
} else {
return new Date(resMaps.y, resMaps.M || 0, resMaps.d || 1, resMaps.H || 0, resMaps.m || 0, resMaps.s || 0, resMaps.S || 0)
}
}
}
}
return new Date('')
}
function helperNewDate () {
return new Date()
}
/**
* 判断是否闰年
*
* @param {Date} date 日期或数字
* @return {Boolean}
*/
function isLeapYear (date) {
var year;
var currentDate = date ? toStringDate(date) : helperNewDate();
if (isDate(currentDate)) {
year = currentDate.getFullYear();
return (year % 4 === 0) && (year % 100 !== 0 || year % 400 === 0)
}
return false
}
/**
* 已废弃,被 some, every 替换
* @deprecated
*/
function forOf (obj, iterate, context) {
if (obj) {
if (isArray(obj)) {
for (var index = 0, len = obj.length; index < len; index++) {
if (iterate.call(context, obj[index], index, obj) === false) {
break
}
}
} else {
for (var key in obj) {
if (hasOwnProp(obj, key)) {
if (iterate.call(context, obj[key], key, obj) === false) {
break
}
}
}
}
}
}
/**
* 已废弃
* @deprecated
*/
function lastForOf (obj, iterate, context) {
if (obj) {
var len, list;
if (isArray(obj)) {
for (len = obj.length - 1; len >= 0; len--) {
if (iterate.call(context, obj[len], len, obj) === false) {
break
}
}
} else {
list = hasOwnProp(obj);
for (len = list.length - 1; len >= 0; len--) {
if (iterate.call(context, obj[list[len]], list[len], obj) === false) {
break
}
}
}
}
}
function helperCreateIndexOf (name, callback) {
return function (obj, val) {
if (obj) {
if (obj[name]) {
return obj[name](val)
}
if (isString(obj) || isArray(obj)) {
return callback(obj, val)
}
for (var key in obj) {
if (hasOwnProp(obj, key)) {
if (val === obj[key]) {
return key
}
}
}
}
return -1
}
}
/**
* 返回对象第一个索引值
*
* @param {Object} obj 对象
* @param {Object} val 值
* @return {Number}
*/
var indexOf = helperCreateIndexOf('indexOf', arrayIndexOf);
/**
* 从最后开始的索引值,返回对象第一个索引值
*
* @param {Object} array 对象
* @param {Object} val 值
* @return {Number}
*/
var lastIndexOf = helperCreateIndexOf('lastIndexOf', arrayLastIndexOf);
/**
* 返回对象的长度
*
* @param {Object} obj 对象
* @return {Number}
*/
function getSize (obj) {
var len = 0;
if (isString(obj) || isArray(obj)) {
return obj.length
}
each(obj, function () {
len++;
});
return len
}
function isNumberFinite (obj) {
return isNumber(obj) && isFinite(obj)
}
/**
* 判断是否整数
*
* @param {Number, String} number 数值
* @return {Boolean}
*/
var isInteger = function (obj) {
return !isNull(obj) && !isNaN(obj) && !isArray(obj) && obj % 1 === 0
};
/**
* 判断是否小数
*
* @param {Number} obj 数值
* @return {Boolean}
*/
function isFloat (obj) {
return !isNull(obj) && !isNaN(obj) && !isArray(obj) && !isInteger(obj)
}
/**
* 判断是否Boolean对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isBoolean = helperCreateInTypeof('boolean');
/**
* 判断是否RegExp对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isRegExp = helperCreateInInObjectString('RegExp');
/**
* 判断是否Error对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isError = helperCreateInInObjectString('Error');
/**
* 判断是否TypeError对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isTypeError (obj) {
return obj ? obj.constructor === TypeError : false
}
/**
* 判断是否为空对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isEmpty (obj) {
for (var key in obj) {
return false
}
return true
}
/* eslint-disable valid-typeof */
/**
* 判断是否Symbol对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var supportSymbol = typeof Symbol !== staticStrUndefined;
function isSymbol (obj) {
return supportSymbol && Symbol.isSymbol ? Symbol.isSymbol(obj) : (typeof obj === 'symbol')
}
/**
* 判断是否Arguments对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var isArguments = helperCreateInInObjectString('Arguments');
/**
* 判断是否Element对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isElement (obj) {
return !!(obj && isString(obj.nodeName) && isNumber(obj.nodeType))
}
/* eslint-disable valid-typeof */
var staticDocument = typeof document === staticStrUndefined ? 0 : document;
/**
* 判断是否Document对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isDocument (obj) {
return !!(obj && staticDocument && obj.nodeType === 9)
}
/* eslint-disable valid-typeof */
var staticWindow = typeof window === staticStrUndefined ? 0 : window;
/**
* 判断是否Window对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
function isWindow (obj) {
return !!(staticWindow && !!(obj && obj === obj.window))
}
/* eslint-disable valid-typeof */
/**
* 判断是否FormData对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var supportFormData = typeof FormData !== staticStrUndefined;
function isFormData (obj) {
return supportFormData && obj instanceof FormData
}
/* eslint-disable valid-typeof */
/**
* 判断是否Map对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var supportMap = typeof Map !== staticStrUndefined;
function isMap (obj) {
return supportMap && obj instanceof Map
}
/* eslint-disable valid-typeof */
/**
* 判断是否WeakMap对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var supportWeakMap = typeof WeakMap !== staticStrUndefined;
function isWeakMap (obj) {
return supportWeakMap && obj instanceof WeakMap
}
/* eslint-disable valid-typeof */
/**
* 判断是否Set对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var supportSet = typeof Set !== staticStrUndefined;
function isSet (obj) {
return supportSet && obj instanceof Set
}
/* eslint-disable valid-typeof */
/**
* 判断是否WeakSet对象
*
* @param {Object} obj 对象
* @return {Boolean}
*/
var supportWeakSet = typeof WeakSet !== staticStrUndefined;
function isWeakSet (obj) {
return supportWeakSet && obj instanceof WeakSet
}
function helperCreateiterateIndexOf (callback) {
return function (obj, iterate, context) {
if (obj && isFunction(iterate)) {
if (isArray(obj) || isString(obj)) {
return callback(obj, iterate, context)
}
for (var key in obj) {
if (hasOwnProp(obj, key)) {
if (iterate.call(context, obj[key], key, obj)) {
return key
}
}
}
}
return -1
}
}
/**
* 返回对象第一个索引值
*
* @param {Object} obj 对象/数组
* @param {Function} iterate(item, index, obj) 回调
* @param {Object} context 上下文
* @return {Object}
*/
var findIndexOf = helperCreateiterateIndexOf(function (obj, iterate, context) {
for (var index = 0, len = obj.length; index < len; index++) {
if (iterate.call(context, obj[index], index, obj))