1 /**
2 * xe-utils.js v1.8.19
3 * (c) 2017-2018 Xu Liangzhan
4 * ISC License.
5 * @preserve
6 */
7 (function (global, factory) {
8 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory()
9 : typeof define === 'function' && define.amd ? define(factory)
10 : (global.XEUtils = factory())
11 }(this, function () {
12 'use strict'
13
14 function XEUtils () { }
15
16 var formatString = 'yyyy-MM-dd HH:mm:ss'
17 var setupDefaults = {
18 treeOptions: {
19 parentKey: 'parentId',
20 key: 'id',
21 children: 'children'
22 },
23 formatDate: formatString + '.SSSZ',
24 formatString: formatString,
25 dateDiffRules: [
26 ['yyyy', 31536000000],
27 ['MM', 2592000000],
28 ['dd', 86400000],
29 ['HH', 3600000],
30 ['mm', 60000],
31 ['ss', 1000],
32 ['S', 0]
33 ]
34 }
35
36 /**
37 * 数组去重
38 *
39 * @param {Array} array 数组
40 * @return {Array}
41 */
42 function arrayUniq (array) {
43 var result = []
44 baseExports.each(array, function (value) {
45 if (!result.includes(value)) {
46 result.push(value)
47 }
48 })
49 return result
50 }
51
52 /**
53 * 将多个数的值返回唯一的并集数组
54 *
55 * @param {...Array} 数组
56 * @return {Array}
57 */
58 function arrayUnion () {
59 var args = arguments
60 var result = []
61 var index = 0
62 var len = args.length
63 for (; index < len; index++) {
64 result = result.concat(toArray(args[index]))
65 }
66 return arrayUniq(result)
67 }
68
69 function sortByDef (v1, v2) {
70 return v1 > v2 ? 1 : -1
71 }
72
73 function sortMultis (name, compares) {
74 return function (item1, item2) {
75 var v1 = item1[name]
76 var v2 = item2[name]
77 if (v1 === v2) {
78 return compares ? compares(item1, item2) : 0
79 }
80 return sortByDef(v1, v2)
81 }
82 }
83
84 function getSortPros (arr, list, iterate, context) {
85 iterate = baseExports.isArray(iterate) ? iterate : [iterate]
86 baseExports.arrayEach(iterate, function (item, index) {
87 baseExports.arrayEach(list, baseExports.isFunction(item) ? function (val, key) {
88 val[index] = item.call(context, val.data, key, arr)
89 } : function (val) {
90 val[index] = val.data[item]
91 })
92 })
93 return iterate
94 }
95
96 /**
97 * 数组按属性值升序
98 *
99 * @param {Array} arr 数组
100 * @param {Function/String/Array} iterate 方法或属性
101 * @param {Object} context 上下文
102 * @return {Array}
103 */
104 function arraySort (arr, iterate, context, STR_UNDEFINED) {
105 if (arr) {
106 if (iterate === STR_UNDEFINED) {
107 return toArray(arr).sort(sortByDef)
108 }
109 var compares
110 var list = arrayMap(arr, function (item) {
111 return { data: item }
112 })
113 var sortPros = getSortPros(arr, list, iterate, context || this)
114 var len = sortPros.length
115 if (len) {
116 while (len >= 0) {
117 compares = sortMultis(len, compares)
118 len--
119 }
120 list = list.sort(compares)
121 }
122 return arrayMap(list, baseExports.property('data'))
123 }
124 return []
125 }
126
127 /**
128 * 将一个数组随机打乱,返回一个新的数组
129 *
130 * @param {Array} array 数组
131 * @return {Array}
132 */
133 function arrayShuffle (array) {
134 var index
135 var result = []
136 var list = baseExports.values(array)
137 var len = list.length - 1
138 for (; len >= 0; len--) {
139 index = len > 0 ? XEUtils.random(0, len) : 0
140 result.push(list[index])
141 list.splice(index, 1)
142 }
143 return result
144 }
145
146 /**
147 * 从一个数组中随机返回几个元素
148 *
149 * @param {Array} array 数组
150 * @param {Number} number 个数
151 * @return {Array}
152 */
153 function arraySample (array, number) {
154 var result = arrayShuffle(array)
155 if (arguments.length <= 1) {
156 return result[0]
157 }
158 if (number < result.length) {
159 result.length = number || 0
160 }
161 return result
162 }
163
164 function createIterateHandle (prop, useArray, restIndex, matchValue, defaultValue) {
165 return function (obj, iterate, context) {
166 if (obj && iterate) {
167 context = context || this
168 if (prop && obj[prop]) {
169 return obj[prop](iterate, context)
170 } else {
171 if (useArray && baseExports.isArray(obj)) {
172 for (var index = 0, len = obj.length; index < len; index++) {
173 if (!!iterate.call(context, obj[index], index, obj) === matchValue) {
174 return [true, false, index, obj[index]][restIndex]
175 }
176 }
177 } else {
178 for (var key in obj) {
179 if (baseExports._hasOwnProp(obj, key)) {
180 if (!!iterate.call(context, obj[key], key, obj) === matchValue) {
181 return [true, false, key, obj[key]][restIndex]
182 }
183 }
184 }
185 }
186 }
187 }
188 return defaultValue
189 }
190 }
191
192 /**
193 * 对象中的值中的每一项运行给定函数,如果函数对任一项返回true,则返回true,否则返回false
194 *
195 * @param {Object} obj 对象/数组
196 * @param {Function} iterate(item, index, obj) 回调
197 * @param {Object} context 上下文
198 * @return {Boolean}
199 */
200 var arraySome = createIterateHandle('some', 1, 0, true, false)
201
202 /**
203 * 对象中的值中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true,否则返回false
204 *
205 * @param {Object} obj 对象/数组
206 * @param {Function} iterate(item, index, obj) 回调
207 * @param {Object} context 上下文
208 * @return {Boolean}
209 */
210 var arrayEvery = createIterateHandle('every', 1, 1, false, true)
211
212 /**
213 * 查找匹配第一条数据的键
214 *
215 * @param {Object} obj 对象/数组
216 * @param {Function} iterate(item, index, obj) 回调
217 * @param {Object} context 上下文
218 * @return {Object}
219 */
220 var findKey = createIterateHandle('', 0, 2, true)
221
222 /**
223 * 查找匹配第一条数据
224 *
225 * @param {Object} obj 对象/数组
226 * @param {Function} iterate(item, index, obj) 回调
227 * @param {Object} context 上下文
228 * @return {Object}
229 */
230 var arrayFind = createIterateHandle('find', 1, 3, true)
231
232 /**
233 * 根据回调过滤数据
234 *
235 * @param {Object} obj 对象/数组
236 * @param {Function} iterate(item, index, obj) 回调
237 * @param {Object} context 上下文
238 * @return {Object}
239 */
240 function arrayFilter (obj, iterate, context) {
241 var result = []
242 if (obj && iterate) {
243 context = context || this
244 if (obj.filter) {
245 return obj.filter(iterate, context)
246 }
247 baseExports.each(obj, function (val, key) {
248 if (iterate.call(context, val, key, obj)) {
249 result.push(val)
250 }
251 })
252 }
253 return result
254 }
255
256 /**
257 * 指定方法后的返回值组成的新数组
258 *
259 * @param {Object} obj 对象/数组
260 * @param {Function} iterate(item, index, obj) 回调
261 * @param {Object} context 上下文
262 * @return {Array}
263 */
264 function arrayMap (obj, iterate, context) {
265 var result = []
266 if (obj && arguments.length > 1) {
267 context = context || this
268 if (!baseExports.isFunction(iterate)) {
269 iterate = baseExports.property(iterate)
270 }
271 if (obj.map) {
272 return obj.map(iterate, context)
273 } else {
274 baseExports.each(obj, function () {
275 result.push(iterate.apply(context, arguments))
276 })
277 }
278 }
279 return result
280 }
281
282 /**
283 * 求和函数,将数值相加
284 *
285 * @param {Array} array 数组
286 * @param {Function/String} iterate 方法或属性
287 * @param {Object} context 上下文
288 * @return {Number}
289 */
290 function arraySum (array, iterate, context) {
291 var result = 0
292 var toNumber = XEUtils.toNumber
293 context = context || this
294 baseExports.each(array, iterate ? baseExports.isFunction(iterate) ? function () {
295 result += toNumber(iterate.apply(context, arguments))
296 } : function (val) {
297 result += toNumber(val[iterate])
298 } : function (val) {
299 result += toNumber(val)
300 })
301 return result
302 }
303
304 /**
305 * 求平均值函数
306 *
307 * @param {Array} array 数组
308 * @param {Function/String} iterate 方法或属性
309 * @param {Object} context 上下文
310 * @return {Number}
311 */
312 function arrayMean (array, iterate, context) {
313 return XEUtils.toNumber(arraySum(array, iterate, context || this) / baseExports.getSize(array))
314 }
315
316 /**
317 * 接收一个函数作为累加器,数组中的每个值(从左到右)开始合并,最终为一个值。
318 *
319 * @param {Array} array 数组
320 * @param {Function} callback 方法
321 * @param {Object} initialValue 初始值
322 * @return {Number}
323 */
324 function arrayReduce (array, callback, initialValue) {
325 if (array) {
326 var len, reduceMethod
327 var index = 0
328 var context = this
329 var previous = initialValue
330 var isInitialVal = arguments.length > 2
331 var keyList = baseExports.keys(array)
332 if (array.length && array.reduce) {
333 reduceMethod = function () {
334 return callback.apply(context, arguments)
335 }
336 if (isInitialVal) {
337 return array.reduce(reduceMethod, previous)
338 }
339 return array.reduce(reduceMethod)
340 }
341 if (isInitialVal) {
342 index = 1
343 previous = array[keyList[0]]
344 }
345 for (len = keyList.length; index < len; index++) {
346 previous = callback.call(context, previous, array[keyList[index]], index, array)
347 }
348 return previous
349 }
350 }
351
352 /**
353 * 浅复制数组的一部分到同一数组中的另一个位置,数组大小不变
354 *
355 * @param {Array} array 数组
356 * @param {Number} target 从该位置开始替换数据
357 * @param {Number} start 从该位置开始读取数据,默认为 0 。如果为负值,表示倒数
358 * @param {Number} end 到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数
359 * @return {Array}
360 */
361 function arrayCopyWithin (array, target, start, end) {
362 if (baseExports.isArray(array) && array.copyWithin) {
363 return array.copyWithin(target, start, end)
364 }
365 var replaceIndex, replaceArray
366 var targetIndex = target >> 0
367 var startIndex = start >> 0
368 var len = array.length
369 var endIndex = arguments.length > 3 ? end >> 0 : len
370 if (targetIndex < len) {
371 targetIndex = targetIndex >= 0 ? targetIndex : len + targetIndex
372 if (targetIndex >= 0) {
373 startIndex = startIndex >= 0 ? startIndex : len + startIndex
374 endIndex = endIndex >= 0 ? endIndex : len + endIndex
375 if (startIndex < endIndex) {
376 for (replaceIndex = 0, replaceArray = array.slice(startIndex, endIndex); targetIndex < len; targetIndex++) {
377 if (replaceArray.length <= replaceIndex) {
378 break
379 }
380 array[targetIndex] = replaceArray[replaceIndex++]
381 }
382 }
383 }
384 }
385 return array
386 }
387
388 /**
389 * 将一个数组分割成大小的组。如果数组不能被平均分配,那么最后一块将是剩下的元素
390 *
391 * @param {Array} array 数组
392 * @param {Number} size 每组大小
393 * @return {Array}
394 */
395 function chunk (array, size) {
396 var index
397 var result = []
398 var arrLen = size >> 0 || 1
399 if (baseExports.isArray(array)) {
400 if (arrLen >= 0 && array.length > arrLen) {
401 index = 0
402 while (index < array.length) {
403 result.push(array.slice(index, index + arrLen))
404 index += arrLen
405 }
406 } else {
407 result = array.length ? [array] : array
408 }
409 }
410 return result
411 }
412
413 /**
414 * 根据键数组、值数组对转换为对象
415 *
416 * @param {Array} props 键数组
417 * @param {Number} values 值数组
418 * @return {Object}
419 */
420 function zipObject (props, values) {
421 var result = {}
422 values = values || []
423 baseExports.each(baseExports.values(props), function (val, key) {
424 result[val] = values[key]
425 })
426 return result
427 }
428
429 /**
430 * 将每个数组中相应位置的值合并在一起
431 *
432 * @param {Array*} array 数组
433 */
434 function zip () {
435 return unzip(arguments)
436 }
437
438 /**
439 * 与 zip 相反
440 *
441 * @param {Array} arrays 数组集合
442 */
443 function unzip (arrays) {
444 var result = []
445 var index = 0
446 var len = XEUtils.max(arrays, function (item) {
447 return item.length || 0
448 }).length
449 for (; index < len; index++) {
450 result.push(arrayMap(arrays, index))
451 }
452 return result
453 }
454
455 /**
456 * 将对象或者伪数组转为新数组
457 *
458 * @param {Array} obj 数组
459 * @return {Array}
460 */
461 function toArray (array) {
462 return arrayMap(array, function (item) {
463 return item
464 })
465 }
466
467 /**
468 * 判断数组是否包含另一数组
469 *
470 * @param {Array} array1 数组
471 * @param {Array} array2 被包含数组
472 * @return {Boolean}
473 */
474 function includeArrays (array1, array2) {
475 var len
476 var index = 0
477 var includes = baseExports.includes
478 if (baseExports.isArray(array1) && baseExports.isArray(array2)) {
479 for (len = array2.length; index < len; index++) {
480 if (!includes(array1, array2[index])) {
481 return false
482 }
483 }
484 return true
485 }
486 return includes(array1, array2)
487 }
488
489 /**
490 * 获取数组对象中某属性值,返回一个数组
491 *
492 * @param {Array} array 数组
493 * @param {String} key 属性值
494 * @return {Array}
495 */
496 function pluck (obj, key) {
497 return arrayMap(obj, key)
498 }
499
500 function deepGetObj (obj, path) {
501 var index = 0
502 var len = path.length
503 while (obj && index < len) {
504 obj = obj[path[index++]]
505 }
506 return len && obj ? obj : 0
507 }
508
509 /**
510 * 在list的每个元素上执行方法,任何传递的额外参数都会在调用方法的时候传递给它
511 *
512 * @param {Array} list
513 * @param {Array/String/Function} path
514 * @param {...Object} arguments
515 * @return {Array}
516 */
517 function invokeMap (list, path) {
518 var func
519 var args = arguments
520 var params = []
521 var paths = []
522 var index = 2
523 var len = args.length
524 for (; index < len; index++) {
525 params.push(args[index])
526 }
527 if (baseExports.isArray(path)) {
528 len = path.length - 1
529 for (index = 0; index < len; index++) {
530 paths.push(path[index])
531 }
532 path = path[len]
533 }
534 return arrayMap(list, function (context) {
535 if (paths.length) {
536 context = deepGetObj(context, paths)
537 }
538 func = context[path] || path
539 if (func && func.apply) {
540 return func.apply(context, params)
541 }
542 })
543 }
544
545 /**
546 * 将一个带层级的数据列表转成树结构
547 *
548 * @param {Array} array 数组
549 * @param {Object} options {strict: false, parentKey: 'parentId', key: 'id', children: 'children', data: 'data'}
550 * @return {Array}
551 */
552 function toArrayTree (array, options) {
553 var opts = baseExports.assign({}, setupDefaults.treeOptions, options)
554 var optStrict = opts.strict
555 var optKey = opts.key
556 var optParentKey = opts.parentKey
557 var optChildren = opts.children
558 var optSortKey = opts.sortKey
559 var optReverse = opts.reverse
560 var optData = opts.data
561 var result = []
562 var treeMap = {}
563 var idList, id, treeData, parentId
564
565 if (optSortKey) {
566 array = arraySort(baseExports.clone(array), optSortKey)
567 if (optReverse) {
568 array = array.reverse()
569 }
570 }
571
572 idList = arrayMap(array, function (item) {
573 return item[optKey]
574 })
575
576 baseExports.each(array, function (item) {
577 id = item[optKey]
578
579 if (optData) {
580 treeData = {}
581 treeData[optData] = item
582 } else {
583 treeData = item
584 }
585
586 parentId = item[optParentKey]
587 treeMap[id] = treeMap[id] || []
588 treeMap[parentId] = treeMap[parentId] || []
589 treeMap[parentId].push(treeData)
590 treeData[optKey] = id
591 treeData[optParentKey] = parentId
592 treeData[optChildren] = treeMap[id]
593
594 if (!optStrict || (optStrict && !parentId)) {
595 if (!baseExports.includes(idList, parentId)) {
596 result.push(treeData)
597 }
598 }
599 })
600
601 if (optStrict) {
602 strictTree(array, optChildren)
603 }
604
605 return result
606 }
607
608 function strictTree (array, optChildren) {
609 baseExports.each(array, function (item) {
610 if (item.children && !item.children.length) {
611 baseExports.remove(item, optChildren)
612 }
613 })
614 }
615
616 function unTreeList (result, array, opts) {
617 var children
618 var optChildren = opts.children
619 var optData = opts.data
620 baseExports.each(array, function (item) {
621 children = item[optChildren]
622 if (optData) {
623 item = item[optData]
624 }
625 result.push(item)
626 if (children) {
627 unTreeList(result, children, opts)
628 }
629 })
630 return result
631 }
632
633 /**
634 * 将一个树结构转成数组列表
635 *
636 * @param {Array} array 数组
637 * @param {Object} options {children: 'children', data: 'data'}
638 * @return {Array}
639 */
640 function toTreeArray (array, options) {
641 return unTreeList([], array, baseExports.assign({}, setupDefaults.treeOptions, options))
642 }
643
644 function createTreeFunc (handle) {
645 return function (obj, iterate, options, context) {
646 var opts = options || {}
647 var optChildren = opts.children || 'children'
648 return handle(null, obj, iterate, context || this, [], optChildren, opts.mapChildren || optChildren)
649 }
650 }
651
652 function findTreeItem (parent, obj, iterate, context, path, parseChildren, mapChildren) {
653 var item, key, index, len, paths, match
654 if (baseExports.isArray(obj)) {
655 for (index = 0, len = obj.length; index < len; index++) {
656 item = obj[index]
657 paths = path.concat(['' + index])
658 if (iterate.call(context, item, index, obj, paths, parent)) {
659 return { index: index, item: item, path: paths, items: obj, parent: parent }
660 }
661 if (parseChildren && item) {
662 match = findTreeItem(item, item[parseChildren], iterate, context, paths.concat([parseChildren]), parseChildren, mapChildren)
663 if (match) {
664 return match
665 }
666 }
667 }
668 } else {
669 for (key in obj) {
670 if (baseExports._hasOwnProp(obj, key)) {
671 item = obj[key]
672 paths = path.concat([key])
673 if (iterate.call(context, item, index, obj, paths, parent)) {
674 return { index: key, item: item, path: paths, items: obj }
675 }
676 if (parseChildren && item) {
677 match = findTreeItem(item, item[parseChildren], iterate, context, paths.concat([parseChildren]), parseChildren, mapChildren)
678 if (match) {
679 return match
680 }
681 }
682 }
683 }
684 }
685 }
686
687 /**
688 * 从树结构中查找匹配第一条数据的键、值、路径
689 *
690 * @param {Object} obj 对象/数组
691 * @param {Function} iterate(item, index, items, path, parent) 回调
692 * @param {Object} options {children: 'children'}
693 * @param {Object} context 上下文
694 * @return {Object} { item, index, items, path }
695 */
696 var findTree = createTreeFunc(findTreeItem)
697
698 function eachTreeItem (parent, obj, iterate, context, path, parseChildren, mapChildren) {
699 var paths
700 baseExports.each(obj, function (item, index) {
701 paths = path.concat(['' + index])
702 iterate.call(context, item, index, obj, paths, parent)
703 if (item && parseChildren) {
704 eachTreeItem(item, item[parseChildren], iterate, context, paths, parseChildren, mapChildren)
705 }
706 })
707 }
708
709 /**
710 * 从树结构中遍历数据的键、值、路径
711 *
712 * @param {Object} obj 对象/数组
713 * @param {Function} iterate(item, index, items, path, parent) 回调
714 * @param {Object} options {children: 'children', mapChildren: 'children}
715 * @param {Object} context 上下文
716 */
717 var eachTree = createTreeFunc(eachTreeItem)
718
719 function mapTreeItem (parent, obj, iterate, context, path, parseChildren, mapChildren) {
720 var paths, rest
721 return arrayMap(obj, function (item, index) {
722 paths = path.concat(['' + index])
723 rest = iterate.call(context, item, index, obj, paths, parent)
724 if (rest && item && parseChildren && item[parseChildren]) {
725 rest[mapChildren] = mapTreeItem(item, item[parseChildren], iterate, context, paths, parseChildren, mapChildren)
726 }
727 return rest
728 })
729 }
730
731 /**
732 * 从树结构中指定方法后的返回值组成的新数组
733 *
734 * @param {Object} obj 对象/数组
735 * @param {Function} iterate(item, index, items, path, parent) 回调
736 * @param {Object} options {children: 'children'}
737 * @param {Object} context 上下文
738 * @return {Object/Array}
739 */
740 var mapTree = createTreeFunc(mapTreeItem)
741
742 /**
743 * 从树结构中根据回调过滤数据
744 *
745 * @param {Object} obj 对象/数组
746 * @param {Function} iterate(item, index, items, path, parent) 回调
747 * @param {Object} options {children: 'children'}
748 * @param {Object} context 上下文
749 * @return {Array}
750 */
751 function filterTree (obj, iterate, options, context) {
752 var result = []
753 if (obj && iterate) {
754 context = context || this
755 eachTree(obj, function (item, index, items, path, parent) {
756 if (iterate.call(context, item, index, items, path, parent)) {
757 result.push(item)
758 }
759 }, options)
760 }
761 return result
762 }
763
764 var arrayExports = {
765 uniq: arrayUniq,
766 union: arrayUnion,
767 sortBy: arraySort,
768 shuffle: arrayShuffle,
769 sample: arraySample,
770 some: arraySome,
771 every: arrayEvery,
772 filter: arrayFilter,
773 find: arrayFind,
774 findKey: findKey,
775 map: arrayMap,
776 sum: arraySum,
777 mean: arrayMean,
778 reduce: arrayReduce,
779 copyWithin: arrayCopyWithin,
780 chunk: chunk,
781 zip: zip,
782 unzip: unzip,
783 zipObject: zipObject,
784 toArray: toArray,
785 includeArrays: includeArrays,
786 pluck: pluck,
787 invoke: invokeMap,
788 invokeMap: invokeMap,
789 toArrayTree: toArrayTree,
790 toTreeArray: toTreeArray,
791 findTree: findTree,
792 eachTree: eachTree,
793 mapTree: mapTree,
794 filterTree: filterTree
795 }
796
797 var STRING_UNDEFINED = 'undefined'
798 var objectToString = Object.prototype.toString
799 var objectAssignFns = Object.assign
800
801 function hasOwnProp (obj, key) {
802 return obj.hasOwnProperty(key)
803 }
804
805 /* eslint-disable valid-typeof */
806 function createInTypeof (type) {
807 return function (obj) {
808 return typeof obj === type
809 }
810 }
811
812 function createInInObjectString (type) {
813 return function (obj) {
814 return '[object ' + type + ']' === objectToString.call(obj)
815 }
816 }
817
818 /**
819 * 指定方法后的返回值组成的新对象
820 *
821 * @param {Object} obj 对象/数组
822 * @param {Function} iterate(item, index, obj) 回调
823 * @param {Object} context 上下文
824 * @return {Object}
825 */
826 function objectMap (obj, iterate, context) {
827 var result = {}
828 if (obj) {
829 if (iterate) {
830 context = context || this
831 if (!isFunction(iterate)) {
832 iterate = property(iterate)
833 }
834 each(obj, function (val, index) {
835 result[index] = iterate.call(context, val, index, obj)
836 })
837 } else {
838 return obj
839 }
840 }
841 return result
842 }
843
844 function cloneObj (obj) {
845 var result = {}
846 each(obj, function (val, key) {
847 result[key] = deepClone(val)
848 })
849 return result
850 }
851
852 function cloneArr (arr) {
853 return XEUtils.map(arr, deepClone)
854 }
855
856 function deepClone (obj) {
857 return isPlainObject(obj) ? cloneObj(obj) : isArray(obj) ? cloneArr(obj) : obj
858 }
859
860 /**
861 * 浅拷贝/深拷贝
862 *
863 * @param {Object} obj 对象/数组
864 * @param {Boolean} deep 是否深拷贝
865 * @return {Object}
866 */
867 function clone (obj, deep) {
868 if (obj) {
869 return deep ? deepClone(obj) : objectAssign(isPlainObject(obj) ? {} : [], obj)
870 }
871 return obj
872 }
873
874 /**
875 * 该方法和 setTimeout 一样的效果,区别就是支持上下文和额外参数
876 *
877 * @param {Function} callback 函数
878 * @param {Number} wait 延迟毫秒
879 * @param {*} args 额外的参数
880 * @return {Number}
881 */
882 function delay (callback, wait) {
883 var args = arraySlice(arguments, 2)
884 var context = this
885 return setTimeout(function () {
886 callback.apply(context, args)
887 }, wait)
888 }
889
890 /**
891 * 创建一个绑定上下文的函数
892 *
893 * @param {Function} callback 函数
894 * @param {Object} context 上下文
895 * @param {*} args 额外的参数
896 * @return {Object}
897 */
898 function bind (callback, context) {
899 var args = arraySlice(arguments, 2)
900 context = context || this
901 return function () {
902 return callback.apply(context, arraySlice(arguments).concat(args))
903 }
904 }
905
906 /**
907 * 创建一个只能调用一次的函数,只会返回第一次执行后的结果
908 *
909 * @param {Function} callback 函数
910 * @param {Object} context 上下文
911 * @param {*} args 额外的参数
912 * @return {Object}
913 */
914 function once (callback, context) {
915 var done = false
916 var rest = null
917 var args = arraySlice(arguments, 2)
918 context = context || this
919 return function () {
920 if (done) {
921 return rest
922 }
923 rest = callback.apply(context, arraySlice(arguments).concat(args))
924 done = true
925 return rest
926 }
927 }
928
929 /**
930 * 创建一个函数, 调用次数超过 count 次之后执行回调并将所有结果记住后返回
931 *
932 * @param {Number} count 调用次数
933 * @param {Function} callback 完成回调
934 * @return {Object}
935 */
936 function after (count, callback, context) {
937 var runCount = 0
938 var rests = []
939 context = context || this
940 return function () {
941 runCount++
942 if (runCount <= count) {
943 rests.push(arguments[0])
944 }
945 if (runCount >= count) {
946 callback.apply(context, [rests].concat(arraySlice(arguments)))
947 }
948 }
949 }
950
951 /**
952 * 创建一个函数, 调用次数不超过 count 次之前执行回调并将所有结果记住后返回
953 *
954 * @param {Number} count 调用次数
955 * @param {Function} callback 完成回调
956 * @return {Object}
957 */
958 function before (count, callback, context) {
959 var runCount = 0
960 var rests = []
961 context = context || this
962 return function () {
963 runCount++
964 if (runCount < count) {
965 rests.push(arguments[0])
966 callback.apply(context, [rests].concat(arraySlice(arguments)))
967 }
968 }
969 }
970
971 function isNumberFinite (obj) {
972 return isNumber(obj) && isFinite(obj)
973 }
974
975 /**
976 * 判断是否Undefined
977 *
978 * @param {Object} obj 对象
979 * @return {Boolean}
980 */
981 var isUndefined = createInTypeof(STRING_UNDEFINED)
982
983 /**
984 * 判断是否数组
985 *
986 * @param {Object} obj 对象
987 * @return {Boolean}
988 */
989 var isArray = Array.isArray || createInInObjectString('Array')
990
991 /**
992 * 判断是否小数
993 *
994 * @param {Number} obj 数值
995 * @return {Boolean}
996 */
997 function isFloat (obj) {
998 return obj !== null && !isNaN(obj) && !isArray(obj) && !isInteger(obj)
999 }
1000
1001 /**
1002 * 判断是否整数
1003 *
1004 * @param {Number, String} number 数值
1005 * @return {Boolean}
1006 */
1007 var isInteger = function (obj) {
1008 return obj !== null && !isNaN(obj) && !isArray(obj) && obj % 1 === 0
1009 }
1010
1011 /**
1012 * 判断是否方法
1013 *
1014 * @param {Object} obj 对象
1015 * @return {Boolean}
1016 */
1017 var isFunction = createInTypeof('function')
1018
1019 /**
1020 * 判断是否Boolean对象
1021 *
1022 * @param {Object} obj 对象
1023 * @return {Boolean}
1024 */
1025 var isBoolean = createInTypeof('boolean')
1026
1027 /**
1028 * 判断是否String对象
1029 *
1030 * @param {Object} obj 对象
1031 * @return {Boolean}
1032 */
1033 var isString = createInTypeof('string')
1034
1035 /**
1036 * 判断是否Number对象
1037 *
1038 * @param {Object} obj 对象
1039 * @return {Boolean}
1040 */
1041 var isNumber = createInTypeof('number')
1042
1043 /**
1044 * 判断是否RegExp对象
1045 *
1046 * @param {Object} obj 对象
1047 * @return {Boolean}
1048 */
1049 var isRegExp = createInInObjectString('RegExp')
1050
1051 /**
1052 * 判断是否Object对象
1053 *
1054 * @param {Object} obj 对象
1055 * @return {Boolean}
1056 */
1057 var isObject = createInTypeof('object')
1058
1059 /**
1060 * 判断是否对象
1061 *
1062 * @param {Object} obj 对象
1063 * @return {Boolean}
1064 */
1065 function isPlainObject (obj) {
1066 return obj ? obj.constructor === Object : false
1067 }
1068
1069 /**
1070 * 判断是否Date对象
1071 *
1072 * @param {Object} obj 对象
1073 * @return {Boolean}
1074 */
1075 var isDate = createInInObjectString('Date')
1076
1077 /**
1078 * 判断是否Error对象
1079 *
1080 * @param {Object} obj 对象
1081 * @return {Boolean}
1082 */
1083 var isError = createInInObjectString('Error')
1084
1085 /**
1086 * 判断是否TypeError对象
1087 *
1088 * @param {Object} obj 对象
1089 * @return {Boolean}
1090 */
1091 function isTypeError (obj) {
1092 return obj ? obj.constructor === TypeError : false
1093 }
1094
1095 /**
1096 * 判断是否为空,包括空对象、空数值、空字符串
1097 *
1098 * @param {Object} obj 对象
1099 * @return {Boolean}
1100 */
1101 function isEmpty (obj) {
1102 for (var key in obj) {
1103 return false
1104 }
1105 return true
1106 }
1107
1108 /**
1109 * 判断是否为Null
1110 *
1111 * @param {Object} obj 对象
1112 * @return {Boolean}
1113 */
1114 function isNull (obj) {
1115 return obj === null
1116 }
1117
1118 /**
1119 * 判断是否Symbol对象
1120 *
1121 * @param {Object} obj 对象
1122 * @return {Boolean}
1123 */
1124 var supportSymbol = typeof Symbol !== STRING_UNDEFINED
1125 function isSymbol (obj) {
1126 return supportSymbol && Symbol.isSymbol ? Symbol.isSymbol(obj) : (typeof obj === 'symbol')
1127 }
1128
1129 /**
1130 * 判断是否Arguments对象
1131 *
1132 * @param {Object} obj 对象
1133 * @return {Boolean}
1134 */
1135 var isArguments = createInInObjectString('Arguments')
1136
1137 /**
1138 * 判断是否Element对象
1139 *
1140 * @param {Object} obj 对象
1141 * @return {Boolean}
1142 */
1143 function isElement (obj) {
1144 return !!(obj && isString(obj.nodeName) && isNumber(obj.nodeType))
1145 }
1146
1147 /**
1148 * 判断是否Document对象
1149 *
1150 * @param {Object} obj 对象
1151 * @return {Boolean}
1152 */
1153 var supportDocument = typeof document !== STRING_UNDEFINED
1154 function isDocument (obj) {
1155 return !!(obj && obj.nodeType === 9 && supportDocument)
1156 }
1157
1158 /**
1159 * 判断是否Window对象
1160 *
1161 * @param {Object} obj 对象
1162 * @return {Boolean}
1163 */
1164 var supportWindow = typeof window !== STRING_UNDEFINED
1165 function isWindow (obj) {
1166 return !!(obj && obj === obj.window && supportWindow)
1167 }
1168
1169 /**
1170 * 判断是否FormData对象
1171 *
1172 * @param {Object} obj 对象
1173 * @return {Boolean}
1174 */
1175 var supportFormData = typeof FormData !== STRING_UNDEFINED
1176 function isFormData (obj) {
1177 return supportFormData && obj instanceof FormData
1178 }
1179
1180 /**
1181 * 判断是否Map对象
1182 *
1183 * @param {Object} obj 对象
1184 * @return {Boolean}
1185 */
1186 var supportMap = typeof Map !== STRING_UNDEFINED
1187 function isMap (obj) {
1188 return supportMap && obj instanceof Map
1189 }
1190
1191 /**
1192 * 判断是否WeakMap对象
1193 *
1194 * @param {Object} obj 对象
1195 * @return {Boolean}
1196 */
1197 var supportWeakMap = typeof WeakMap !== STRING_UNDEFINED
1198 function isWeakMap (obj) {
1199 return supportWeakMap && obj instanceof WeakMap
1200 }
1201
1202 /**
1203 * 判断是否Set对象
1204 *
1205 * @param {Object} obj 对象
1206 * @return {Boolean}
1207 */
1208 var supportSet = typeof Set !== STRING_UNDEFINED
1209 function isSet (obj) {
1210 return supportSet && obj instanceof Set
1211 }
1212
1213 /**
1214 * 判断是否WeakSet对象
1215 *
1216 * @param {Object} obj 对象
1217 * @return {Boolean}
1218 */
1219 var supportWeakSet = typeof WeakSet !== STRING_UNDEFINED
1220 function isWeakSet (obj) {
1221 return supportWeakSet && obj instanceof WeakSet
1222 }
1223
1224 /**
1225 * 判断是否闰年
1226 *
1227 * @param {Date} date 日期或数字
1228 * @return {Boolean}
1229 */
1230 function isLeapYear (date) {
1231 var year
1232 var currentDate = date ? XEUtils.toStringDate(date) : new Date()
1233 if (isDate(currentDate)) {
1234 year = currentDate.getFullYear()
1235 return (year % 4 === 0) && (year % 100 !== 0 || year % 400 === 0)
1236 }
1237 return false
1238 }
1239
1240 /**
1241 * 判断属性中的键和值是否包含在对象中
1242 *
1243 * @param {Object/Array} obj 对象
1244 * @param {Object} source 值
1245 * @return {Boolean}
1246 */
1247 function isMatch (obj, source) {
1248 var objKeys = objectKeys(obj)
1249 var sourceKeys = objectKeys(source)
1250 if (sourceKeys.length) {
1251 if (XEUtils.includeArrays(objKeys, sourceKeys)) {
1252 return XEUtils.some(sourceKeys, function (key2) {
1253 return findIndexOf(objKeys, function (key1) {
1254 return key1 === key2 && isEqual(obj[key1], source[key2])
1255 }) > -1
1256 })
1257 }
1258 } else {
1259 return true
1260 }
1261 return isEqual(obj, source)
1262 }
1263
1264 /**
1265 * 深度比较两个对象之间的值是否相等
1266 *
1267 * @param {Object} obj1 值1
1268 * @param {Object} obj2 值2
1269 * @return {Boolean}
1270 */
1271 function isEqual (obj1, obj2) {
1272 return equalCompare(obj1, obj2, defaultCompare)
1273 }
1274
1275 function defaultCompare (v1, v2) {
1276 return v1 === v2
1277 }
1278
1279 function equalCompare (val1, val2, compare, func, key, obj1, obj2) {
1280 if (val1 && val2 && !isNumber(val1) && !isNumber(val2) && !isString(val1) && !isString(val2)) {
1281 if (isRegExp(val1)) {
1282 return compare('' + val1, '' + val2, key, obj1, obj2)
1283 } if (isDate(val1) || isBoolean(val1)) {
1284 return compare(+val1, +val2, key, obj1, obj2)
1285 } else {
1286 var result, val1Keys, val2Keys
1287 var isObj1Arr = isArray(val1)
1288 var isObj2Arr = isArray(val2)
1289 if (isObj1Arr || isObj2Arr ? isObj1Arr && isObj2Arr : val1.constructor === val2.constructor) {
1290 val1Keys = objectKeys(val1)
1291 val2Keys = objectKeys(val2)
1292 if (func) {
1293 result = func(val1, val2, key)
1294 }
1295 if (val1Keys.length === val2Keys.length) {
1296 return isUndefined(result) ? XEUtils.every(val1Keys, function (key, index) {
1297 return key === val2Keys[index] && equalCompare(val1[key], val2[val2Keys[index]], compare, func, isObj1Arr || isObj2Arr ? index : key, val1, val2)
1298 }) : !!result
1299 }
1300 return false
1301 }
1302 }
1303 }
1304 return compare(val1, val2, key, obj1, obj2)
1305 }
1306
1307 /**
1308 * 深度比较两个对象之间的值是否相等,使用自定义比较函数
1309 *
1310 * @param {Object} obj1 值1
1311 * @param {Object} obj2 值2
1312 * @param {Function} func 自定义函数
1313 * @return {Boolean}
1314 */
1315 function isEqualWith (obj1, obj2, func) {
1316 if (isFunction(func)) {
1317 return equalCompare(obj1, obj2, function (v1, v2, key, obj1, obj2) {
1318 var result = func(v1, v2, key, obj1, obj2)
1319 return isUndefined(result) ? defaultCompare(v1, v2) : !!result
1320 }, func)
1321 }
1322 return equalCompare(obj1, obj2, defaultCompare)
1323 }
1324
1325 /**
1326 * 返回一个获取对象属性的函数
1327 *
1328 * @param {String} name 属性名
1329 * @param {Object} defs 空值
1330 */
1331 function property (name, defs) {
1332 return function (obj) {
1333 return obj === null ? defs : obj[name]
1334 }
1335 }
1336
1337 /**
1338 * 获取对象类型
1339 *
1340 * @param {Object} obj 对象
1341 * @return {String}
1342 */
1343 function getType (obj) {
1344 if (obj === null) {
1345 return '' + obj
1346 }
1347 if (isSymbol(obj)) {
1348 return 'symbol'
1349 }
1350 if (isDate(obj)) {
1351 return 'date'
1352 }
1353 if (isArray(obj)) {
1354 return 'array'
1355 }
1356 if (isRegExp(obj)) {
1357 return 'regexp'
1358 }
1359 if (isError(obj)) {
1360 return 'error'
1361 }
1362 return typeof obj
1363 }
1364
1365 /**
1366 * 获取一个全局唯一标识
1367 *
1368 * @param {String} prefix 前缀
1369 * @return {Number}
1370 */
1371 var __uniqueId = 0
1372 function uniqueId (prefix) {
1373 return (prefix ? '' + prefix : 0) + ++__uniqueId
1374 }
1375
1376 /**
1377 * 返回对象的长度
1378 *
1379 * @param {Object} obj 对象
1380 * @return {Number}
1381 */
1382 function getSize (obj) {
1383 var len = 0
1384 if (isString(obj) || isArray(obj)) {
1385 return obj.length
1386 }
1387 each(obj, function () {
1388 len++
1389 })
1390 return len
1391 }
1392
1393 /**
1394 * 裁剪 Arguments 或数组 array,从 start 位置开始到 end 结束,但不包括 end 本身的位置
1395 * @param {Array/Arguments} array 数组或Arguments
1396 * @param {Number} startIndex 开始索引
1397 * @param {Number} endIndex 结束索引
1398 */
1399 function arraySlice (array, startIndex, endIndex) {
1400 var result = []
1401 if (array) {
1402 for (startIndex = startIndex || 0, endIndex = endIndex || array.length; startIndex < endIndex; startIndex++) {
1403 result.push(array[startIndex])
1404 }
1405 }
1406 return result
1407 }
1408
1409 function createIndexOf (name, callback) {
1410 return function (obj, val) {
1411 if (obj) {
1412 if (isString(obj) || isArray(obj)) {
1413 if (obj[name]) {
1414 return obj[name](val)
1415 }
1416 return callback(obj, val)
1417 }
1418 for (var key in obj) {
1419 if (hasOwnProp(obj, key)) {
1420 if (val === obj[key]) {
1421 return key
1422 }
1423 }
1424 }
1425 }
1426 return -1
1427 }
1428 }
1429
1430 /**
1431 * 返回对象第一个索引值
1432 *
1433 * @param {Object} obj 对象
1434 * @param {Object} val 值
1435 * @return {Number}
1436 */
1437 var indexOf = createIndexOf('indexOf', function (obj, val) {
1438 for (var index = 0, len = obj.length; index < len; index++) {
1439 if (val === obj[index]) {
1440 return index
1441 }
1442 }
1443 })
1444
1445 /**
1446 * 从最后开始的索引值,返回对象第一个索引值
1447 *
1448 * @param {Object} array 对象
1449 * @param {Object} val 值
1450 * @return {Number}
1451 */
1452 var lastIndexOf = createIndexOf('lastIndexOf', function (obj, val) {
1453 for (var len = obj.length - 1; len >= 0; len--) {
1454 if (val === obj[len]) {
1455 return len
1456 }
1457 }
1458 return -1
1459 })
1460
1461 function createiterateIndexOf (callback) {
1462 return function (obj, iterate, context) {
1463 if (obj && isFunction(iterate)) {
1464 context = this || context
1465 if (isArray(obj) || isString(obj)) {
1466 return callback(obj, iterate, context)
1467 }
1468 for (var key in obj) {
1469 if (hasOwnProp(obj, key)) {
1470 if (iterate.call(context, obj[key], key, obj)) {
1471 return key
1472 }
1473 }
1474 }
1475 }
1476 return -1
1477 }
1478 }
1479
1480 /**
1481 * 返回对象第一个索引值
1482 *
1483 * @param {Object} obj 对象/数组
1484 * @param {Function} iterate(item, index, obj) 回调
1485 * @param {Object} context 上下文
1486 * @return {Object}
1487 */
1488 var findIndexOf = createiterateIndexOf(function (obj, iterate, context) {
1489 for (var index = 0, len = obj.length; index < len; index++) {
1490 if (iterate.call(context, obj[index], index, obj)) {
1491 return index
1492 }
1493 }
1494 return -1
1495 })
1496
1497 /**
1498 * 从最后开始的索引值,返回对象第一个索引值
1499 *
1500 * @param {Object} obj 对象/数组
1501 * @param {Function} iterate(item, index, obj) 回调
1502 * @param {Object} context 上下文
1503 * @return {Object}
1504 */
1505 var findLastIndexOf = createiterateIndexOf(function (obj, iterate, context) {
1506 for (var len = obj.length - 1; len >= 0; len--) {
1507 if (iterate.call(context, obj[len], len, obj)) {
1508 return len
1509 }
1510 }
1511 return -1
1512 })
1513
1514 /**
1515 * 判断对象是否包含该值,成功返回true否则false
1516 *
1517 * @param {Object} obj 对象
1518 * @param {Object} val 值
1519 * @return {Boolean}
1520 */
1521 function includes (obj, val) {
1522 return indexOf(obj, val) !== -1
1523 }
1524
1525 function extend (destination, args, isClone) {
1526 var len = args.length
1527 for (var source, index = 1; index < len; index++) {
1528 source = args[index]
1529 arrayEach(objectKeys(args[index]), isClone ? function (key) {
1530 destination[key] = clone(source[key], isClone)
1531 } : function (key) {
1532 destination[key] = source[key]
1533 })
1534 }
1535 return destination
1536 }
1537
1538 /**
1539 * 将一个或者多个对象值解构到目标对象
1540 *
1541 * @param {Object} destination 目标对象
1542 * @param {...Object}
1543 * @return {Boolean}
1544 */
1545 function destructuring (destination, sources) {
1546 if (destination && sources) {
1547 var rest = objectAssign.apply(this, [{}].concat(arraySlice(arguments, 1)))
1548 var restKeys = objectKeys(rest)
1549 arrayEach(objectKeys(destination), function (key) {
1550 if (includes(restKeys, key)) {
1551 destination[key] = rest[key]
1552 }
1553 })
1554 }
1555 return destination
1556 }
1557
1558 /**
1559 * 浅拷贝一个或者多个对象到目标对象中
1560 *
1561 * @param {Object} obj 目标对象
1562 * @param {...Object}
1563 * @return {Boolean}
1564 */
1565 var objectAssign = function (target) {
1566 if (target) {
1567 var args = arguments
1568 if (target === true) {
1569 if (args.length > 1) {
1570 target = isArray(target[1]) ? [] : {}
1571 return extend(target, args, true)
1572 }
1573 } else {
1574 return objectAssignFns ? objectAssignFns.apply(Object, args) : extend(target, args)
1575 }
1576 }
1577 return target
1578 }
1579
1580 /**
1581 * 字符串转JSON
1582 *
1583 * @param {String} str 字符串
1584 * @return {Object} 返回转换后对象
1585 */
1586 function toStringJSON (str) {
1587 if (isObject(str)) {
1588 return str
1589 } else if (isString(str)) {
1590 try {
1591 return JSON.parse(str)
1592 } catch (e) { }
1593 }
1594 return {}
1595 }
1596
1597 /**
1598 * JSON转字符串
1599 *
1600 * @param {Object} obj 对象
1601 * @return {String} 返回字符串
1602 */
1603 function toJSONString (obj) {
1604 return JSON.stringify(obj) || ''
1605 }
1606
1607 function deleteProperty (obj, property) {
1608 try {
1609 delete obj[property]
1610 } catch (e) {
1611 obj[property] = undefined
1612 }
1613 }
1614
1615 /**
1616 * 清空对象
1617 *
1618 * @param {Object} obj 对象
1619 * @param {*} defs 默认值,如果不传(清空所有属性)、如果传对象(清空并继承)、如果传值(给所有赋值)
1620 * @param {Object/Array} assigns 默认值
1621 * @return {Object}
1622 */
1623 function clearObject (obj, defs, assigns) {
1624 if (obj) {
1625 var len
1626 var isDefs = arguments.length > 1 && (defs === null || !isObject(defs))
1627 var extds = isDefs ? assigns : defs
1628 if (isPlainObject(obj)) {
1629 objectEach(obj, isDefs ? function (val, key) {
1630 obj[key] = defs
1631 } : function (val, key) {
1632 deleteProperty(obj, key)
1633 })
1634 if (extds) {
1635 objectAssign(obj, extds)
1636 }
1637 } else if (isArray(obj)) {
1638 if (isDefs) {
1639 len = obj.length
1640 while (len > 0) {
1641 len--
1642 obj[len] = defs
1643 }
1644 } else {
1645 obj.length = 0
1646 }
1647 if (extds) {
1648 obj.push.apply(obj, extds)
1649 }
1650 }
1651 }
1652 return obj
1653 }
1654
1655 function pluckProperty (name) {
1656 return function (obj, key) {
1657 return key === name
1658 }
1659 }
1660
1661 /**
1662 * 移除对象属性
1663 *
1664 * @param {Object/Array} obj 对象/数组
1665 * @param {Function/String} iterate 方法或属性
1666 * @param {Object} context 上下文
1667 * @return {Object/Array}
1668 */
1669 function removeObject (obj, iterate, context) {
1670 if (obj) {
1671 if (arguments.length > 1) {
1672 var removeKeys = []
1673 var rest = []
1674 context = context || this
1675 if (!isFunction(iterate)) {
1676 iterate = pluckProperty(iterate)
1677 }
1678 each(obj, function (item, index, rest) {
1679 if (iterate.call(context, item, index, rest)) {
1680 removeKeys.push(index)
1681 }
1682 })
1683 if (isArray(obj)) {
1684 lastEach(removeKeys, function (item, key) {
1685 rest.push(obj[item])
1686 obj.splice(item, 1)
1687 })
1688 } else {
1689 rest = {}
1690 arrayEach(removeKeys, function (key) {
1691 rest[key] = obj[key]
1692 deleteProperty(obj, key)
1693 })
1694 }
1695 return rest
1696 }
1697 return clearObject(obj)
1698 }
1699 return obj
1700 }
1701
1702 function createGetObjects (name, getIndex) {
1703 var proMethod = Object[name]
1704 return function (obj) {
1705 var result = []
1706 if (obj) {
1707 if (proMethod) {
1708 return proMethod(obj)
1709 }
1710 each(obj, getIndex > 1 ? function (key) {
1711 result.push(['' + key, obj[key]])
1712 } : function () {
1713 result.push(arguments[getIndex])
1714 })
1715 }
1716 return result
1717 }
1718 }
1719
1720 /**
1721 * 获取对象所有属性
1722 *
1723 * @param {Object} obj 对象/数组
1724 * @return {Array}
1725 */
1726 var objectKeys = createGetObjects('keys', 1)
1727
1728 /**
1729 * 获取对象所有值
1730 *
1731 * @param {Object} obj 对象/数组
1732 * @return {Array}
1733 */
1734 var objectValues = createGetObjects('values', 0)
1735
1736 /**
1737 * 获取对象所有属性、值
1738 *
1739 * @param {Object} obj 对象/数组
1740 * @return {Array}
1741 */
1742 var objectEntries = createGetObjects('entries', 2)
1743
1744 function createPickOmit (case1, case2) {
1745 return function (obj, callback) {
1746 var item
1747 var rest = {}
1748 var result = []
1749 var context = this
1750 var args = arguments
1751 var index = 1
1752 var len = args.length
1753 if (!isFunction(callback)) {
1754 for (callback = 0; index < len; index++) {
1755 item = args[index]
1756 if (isArray(item)) {
1757 result = result.concat(item)
1758 } else {
1759 result.push(item)
1760 }
1761 }
1762 }
1763 each(obj, function (val, key) {
1764 if ((callback ? callback.call(context, val, key, obj) : findIndexOf(result, function (name) {
1765 return name === key
1766 }) > -1) ? case1 : case2) {
1767 rest[key] = val
1768 }
1769 })
1770 return rest
1771 }
1772 }
1773
1774 /**
1775 * 根据 keys 过滤指定的属性值,返回一个新的对象
1776 *
1777 * @param {Object} obj 对象
1778 * @param {String/Array} keys 键数组
1779 * @return {Object}
1780 */
1781 var pick = createPickOmit(1, 0)
1782
1783 /**
1784 * 根据 keys 排除指定的属性值,返回一个新的对象
1785 *
1786 * @param {Object} obj 对象
1787 * @param {String/Array} keys 键数组
1788 * @return {Object}
1789 */
1790 var omit = createPickOmit(0, 1)
1791
1792 /**
1793 * 获取对象第一个值
1794 *
1795 * @param {Object} obj 对象/数组
1796 * @return {Object}
1797 */
1798 function getFirst (obj) {
1799 return objectValues(obj)[0]
1800 }
1801
1802 /**
1803 * 获取对象最后一个值
1804 *
1805 * @param {Object} obj 对象/数组
1806 * @return {Object}
1807 */
1808 function getLast (obj) {
1809 var list = objectValues(obj)
1810 return list[list.length - 1]
1811 }
1812
1813 function arrayEach (obj, iterate, context) {
1814 if (obj.forEach) {
1815 obj.forEach(iterate, context)
1816 } else {
1817 for (var index = 0, len = obj.length; index < len; index++) {
1818 iterate.call(context || this, obj[index], index, obj)
1819 }
1820 }
1821 }
1822
1823 function objectEach (obj, iterate, context) {
1824 for (var key in obj) {
1825 if (hasOwnProp(obj, key)) {
1826 iterate.call(context || this, obj[key], key, obj)
1827 }
1828 }
1829 }
1830
1831 function lastObjectEach (obj, iterate, context) {
1832 lastArrayEach(objectKeys(obj), function (key) {
1833 iterate.call(context || this, obj[key], key, obj)
1834 })
1835 }
1836
1837 function lastArrayEach (obj, iterate, context) {
1838 for (var len = obj.length - 1; len >= 0; len--) {
1839 iterate.call(context || this, obj[len], len, obj)
1840 }
1841 }
1842
1843 /**
1844 * 迭代器,支持 return false 跳出循环 break
1845 *
1846 * @param {Object} obj 对象/数组
1847 * @param {Function} iterate(item, index, obj) 回调
1848 * @param {Object} context 上下文
1849 * @return {Object}
1850 */
1851 function forOf (obj, iterate, context) {
1852 if (obj) {
1853 context = context || this
1854 if (isArray(obj)) {
1855 for (var index = 0, len = obj.length; index < len; index++) {
1856 if (iterate.call(context, obj[index], index, obj) === false) {
1857 break
1858 }
1859 }
1860 } else {
1861 for (var key in obj) {
1862 if (hasOwnProp(obj, key)) {
1863 if (iterate.call(context, obj[key], key, obj) === false) {
1864 break
1865 }
1866 }
1867 }
1868 }
1869 }
1870 }
1871
1872 /**
1873 * 迭代器
1874 *
1875 * @param {Object} obj 对象/数组
1876 * @param {Function} iterate(item, index, obj) 回调
1877 * @param {Object} context 上下文
1878 * @return {Object}
1879 */
1880 function each (obj, iterate, context) {
1881 if (obj) {
1882 context = context || this
1883 if (isArray(obj)) {
1884 return arrayEach(obj, iterate, context)
1885 }
1886 return objectEach(obj, iterate, context)
1887 }
1888 return obj
1889 }
1890
1891 /**
1892 * 迭代器,从最后开始迭代
1893 *
1894 * @param {Object} obj 对象/数组
1895 * @param {Function} iterate(item, index, obj) 回调
1896 * @param {Object} context 上下文
1897 * @return {Object}
1898 */
1899 function lastEach (obj, iterate, context) {
1900 if (obj) {
1901 return (isArray(obj) ? lastArrayEach : lastObjectEach)(obj, iterate, context || this)
1902 }
1903 return obj
1904 }
1905
1906 /**
1907 * 迭代器,从最后开始迭代,支持 return false 跳出循环 break
1908 *
1909 * @param {Object} obj 对象/数组
1910 * @param {Function} iterate(item, index, obj) 回调
1911 * @param {Object} context 上下文
1912 * @return {Object}
1913 */
1914 function lastForOf (obj, iterate, context) {
1915 if (obj) {
1916 var len, list
1917 context = context || this
1918 if (isArray(obj)) {
1919 for (len = obj.length - 1; len >= 0; len--) {
1920 if (iterate.call(context, obj[len], len, obj) === false) {
1921 break
1922 }
1923 }
1924 } else {
1925 list = objectKeys(obj)
1926 for (len = list.length - 1; len >= 0; len--) {
1927 if (iterate.call(context, obj[list[len]], list[len], obj) === false) {
1928 break
1929 }
1930 }
1931 }
1932 }
1933 }
1934
1935 function createiterateEmpty (iterate) {
1936 return function () {
1937 return isEmpty(iterate)
1938 }
1939 }
1940
1941 function getHGSKeys (property) {
1942 return property ? (isArray(property) ? property : ('' + property).split('.')) : []
1943 }
1944
1945 /**
1946 * 检查键、路径是否是该对象的属性
1947 * @param {Object/Array} data 对象
1948 * @param {String/Function} property 键、路径
1949 * @return {Boolean}
1950 */
1951 var hgKeyRE = /(.+)?[(d+)]$/
1952 var sKeyRE = /(.+)[(d+)]$/
1953 function has (obj, property) {
1954 if (obj) {
1955 if (hasOwnProp(obj, property)) {
1956 return true
1957 } else {
1958 var prop, arrIndex, objProp, matchs, rest, isHas
1959 var keys = getHGSKeys(property)
1960 var index = 0
1961 var len = keys.length
1962 for (rest = obj; index < len; index++) {
1963 isHas = false
1964 prop = keys[index]
1965 matchs = prop ? prop.match(hgKeyRE) : ''
1966 if (matchs) {
1967 arrIndex = matchs[1]
1968 objProp = matchs[2]
1969 if (arrIndex) {
1970 if (rest[arrIndex]) {
1971 if (hasOwnProp(rest[arrIndex], objProp)) {
1972 isHas = true
1973 rest = rest[arrIndex][objProp]
1974 }
1975 }
1976 } else {
1977 if (hasOwnProp(rest, objProp)) {
1978 isHas = true
1979 rest = rest[objProp]
1980 }
1981 }
1982 } else {
1983 if (hasOwnProp(rest, prop)) {
1984 isHas = true
1985 rest = rest[prop]
1986 }
1987 }
1988 if (isHas) {
1989 if (index === len - 1) {
1990 return true
1991 }
1992 } else {
1993 break
1994 }
1995 }
1996 }
1997 }
1998 return false
1999 }
2000
2001 function valGet (obj, key) {
2002 var matchs = key ? key.match(hgKeyRE) : ''
2003 return matchs ? (matchs[1] ? (obj[matchs[1]] ? obj[matchs[1]][matchs[2]] : undefined) : obj[matchs[2]]) : obj[key]
2004 }
2005
2006 function pathGet (obj, property) {
2007 if (obj) {
2008 var rest, keys, len
2009 var index = 0
2010 if (hasOwnProp(obj, property)) {
2011 return obj[property]
2012 } else {
2013 keys = getHGSKeys(property)
2014 len = keys.length
2015 if (len) {
2016 for (rest = obj; index < len; index++) {
2017 rest = valGet(rest, keys[index])
2018 if (isUndefined(rest) || isNull(rest)) {
2019 return
2020 }
2021 }
2022 }
2023 return rest
2024 }
2025 }
2026 }
2027
2028 /**
2029 * 获取对象的属性的值,如果值为 undefined,则返回默认值
2030 * @param {Object/Array} data 对象
2031 * @param {String/Function} property 键、路径
2032 * @param {Object} defaultValue 默认值
2033 * @return {Object}
2034 */
2035 function get (obj, property, defaultValue) {
2036 if (isNull(obj) || isUndefined(obj)) {
2037 return defaultValue
2038 }
2039 var result = pathGet(obj, property)
2040 return isUndefined(result) ? defaultValue : result
2041 }
2042
2043 function valSet (obj, key, isSet, value) {
2044 if (obj[key]) {
2045 if (isSet) {
2046 obj[key] = value
2047 }
2048 } else {
2049 var index
2050 var matchs = key ? key.match(sKeyRE) : null
2051 var rest = isSet ? value : {}
2052 if (matchs) {
2053 index = parseInt(matchs[2])
2054 if (obj[matchs[1]]) {
2055 obj[matchs[1]][index] = rest
2056 } else {
2057 obj[matchs[1]] = new Array(index + 1)
2058 obj[matchs[1]][index] = rest
2059 }
2060 } else {
2061 obj[key] = rest
2062 }
2063 return rest
2064 }
2065 return obj[key]
2066 }
2067
2068 /**
2069 * 设置对象属性上的值。如果属性不存在则创建它
2070 * @param {Object/Array} data 对象
2071 * @param {String/Function} property 键、路径
2072 * @param {Object} value 值
2073 */
2074 function set (obj, property, value) {
2075 if (obj) {
2076 var rest = obj
2077 var keys = getHGSKeys(property)
2078 var len = keys.length
2079 arrayEach(keys, function (key, index) {
2080 rest = valSet(rest, key, index === len - 1, value)
2081 })
2082 }
2083 return obj
2084 }
2085
2086 /**
2087 * 集合分组,默认使用键值分组,如果有iterate则使用结果进行分组
2088 *
2089 * @param {Array} obj 对象
2090 * @param {Function} iterate 回调/对象属性
2091 * @param {Object} context 上下文
2092 * @return {Object}
2093 */
2094 function groupBy (obj, iterate, context) {
2095 var groupKey
2096 var result = {}
2097 if (obj) {
2098 context = this || context
2099 if (iterate && isObject(iterate)) {
2100 iterate = createiterateEmpty(iterate)
2101 } else if (!isFunction(iterate)) {
2102 iterate = property(iterate)
2103 }
2104 each(obj, function (val, key) {
2105 groupKey = iterate ? iterate.call(context, val, key, obj) : val
2106 if (result[groupKey]) {
2107 result[groupKey].push(val)
2108 } else {
2109 result[groupKey] = [val]
2110 }
2111 })
2112 }
2113 return result
2114 }
2115
2116 /**
2117 * 集合分组统计,返回各组中对象的数量统计
2118 *
2119 * @param {Array} obj 对象
2120 * @param {Function} iterate 回调/对象属性
2121 * @param {Object} context 上下文
2122 * @return {Object}
2123 */
2124 function countBy (obj, iterate, context) {
2125 var result = groupBy(obj, iterate, context || this)
2126 objectEach(result, function (item, key) {
2127 result[key] = item.length
2128 })
2129 return result
2130 }
2131
2132 /**
2133 * 序号列表生成函数
2134 *
2135 * @param {Number} start 起始值
2136 * @param {Number} stop 结束值
2137 * @param {Number} step 自增值
2138 * @return {Object}
2139 */
2140 function range (start, stop, step) {
2141 var index, len
2142 var result = []
2143 var args = arguments
2144 if (args.length < 2) {
2145 stop = args[0]
2146 start = 0
2147 }
2148 index = start >> 0
2149 len = stop >> 0
2150 if (index < stop) {
2151 step = step >> 0 || 1
2152 for (; index < len; index += step) {
2153 result.push(index)
2154 }
2155 }
2156 return result
2157 }
2158
2159 /**
2160 * 创建一个策略函数,当被重复调用函数的时候,至少每隔多少秒毫秒调用一次该函数
2161 *
2162 * @param {Function} callback 回调
2163 * @param {Number} wait 多少秒毫
2164 * @param {Object} options 参数{leading: 是否在之前执行, trailing: 是否在之后执行}
2165 * @return {Function}
2166 */
2167 function throttle (callback, wait, options) {
2168 var args, context
2169 var opts = options || {}
2170 var runFlag = false
2171 var timeout = 0
2172 var optLeading = 'leading' in opts ? opts.leading : true
2173 var optTrailing = 'trailing' in opts ? opts.trailing : false
2174 var runFn = function () {
2175 runFlag = true
2176 callback.apply(context, args)
2177 timeout = setTimeout(endFn, wait)
2178 }
2179 var endFn = function () {
2180 timeout = 0
2181 if (!runFlag && optTrailing === true) {
2182 runFn()
2183 }
2184 }
2185 var cancelFn = function () {
2186 var rest = timeout !== 0
2187 clearTimeout(timeout)
2188 runFlag = false
2189 timeout = 0
2190 return rest
2191 }
2192 var throttled = function () {
2193 args = arguments
2194 context = this
2195 runFlag = false
2196 if (timeout === 0) {
2197 if (optLeading === true) {
2198 runFn()
2199 } else if (optTrailing === true) {
2200 timeout = setTimeout(endFn, wait)
2201 }
2202 }
2203 }
2204 throttled.cancel = cancelFn
2205 return throttled
2206 }
2207
2208 /**
2209 * 创建一个防反跳策略函数,在函数最后一次调用多少毫秒之后才会再次执行,如果在期间内重复调用会重新计算延迟
2210 *
2211 * @param {Function} callback 回调
2212 * @param {Number} wait 多少秒毫
2213 * @param {Object} options 参数{leading: 是否在之前执行, trailing: 是否在之后执行}
2214 * @return {Function}
2215 */
2216 function debounce (callback, wait, options) {
2217 var args, context
2218 var opts = options || {}
2219 var runFlag = false
2220 var timeout = 0
2221 var isLeading = typeof options === 'boolean'
2222 var optLeading = 'leading' in opts ? opts.leading : isLeading
2223 var optTrailing = 'trailing' in opts ? opts.trailing : !isLeading
2224 var clearTimeoutFn = clearTimeout
2225 var runFn = function () {
2226 runFlag = true
2227 timeout = 0
2228 callback.apply(context, args)
2229 }
2230 var endFn = function () {
2231 if (optLeading === true) {
2232 timeout = 0
2233 }
2234 if (!runFlag && optTrailing === true) {
2235 runFn()
2236 }
2237 }
2238 var cancelFn = function () {
2239 var rest = timeout !== 0
2240 clearTimeoutFn(timeout)
2241 timeout = 0
2242 return rest
2243 }
2244 var debounced = function () {
2245 runFlag = false
2246 args = arguments
2247 context = this
2248 if (timeout === 0) {
2249 if (optLeading === true) {
2250 runFn()
2251 }
2252 } else {
2253 clearTimeoutFn(timeout)
2254 }
2255 timeout = setTimeout(endFn, wait)
2256 }
2257 debounced.cancel = cancelFn
2258 return debounced
2259 }
2260
2261 var baseExports = {
2262 _hasOwnProp: hasOwnProp,
2263 isNaN: isNaN,
2264 isFinite: isNumberFinite,
2265 isUndefined: isUndefined,
2266 isArray: isArray,
2267 isFloat: isFloat,
2268 isInteger: isInteger,
2269 isFunction: isFunction,
2270 isBoolean: isBoolean,
2271 isString: isString,
2272 isNumber: isNumber,
2273 isRegExp: isRegExp,
2274 isObject: isObject,
2275 isPlainObject: isPlainObject,
2276 isDate: isDate,
2277 isError: isError,
2278 isTypeError: isTypeError,
2279 isEmpty: isEmpty,
2280 isNull: isNull,
2281 isSymbol: isSymbol,
2282 isArguments: isArguments,
2283 isElement: isElement,
2284 isDocument: isDocument,
2285 isWindow: isWindow,
2286 isFormData: isFormData,
2287 isMap: isMap,
2288 isWeakMap: isWeakMap,
2289 isSet: isSet,
2290 isWeakSet: isWeakSet,
2291 isLeapYear: isLeapYear,
2292 isMatch: isMatch,
2293 isEqual: isEqual,
2294 isEqualWith: isEqualWith,
2295 property: property,
2296 getType: getType,
2297 uniqueId: uniqueId,
2298 getSize: getSize,
2299 slice: arraySlice,
2300 indexOf: indexOf,
2301 lastIndexOf: lastIndexOf,
2302 findIndexOf: findIndexOf,
2303 findLastIndexOf: findLastIndexOf,
2304 includes: includes,
2305 contains: includes,
2306 assign: objectAssign,
2307 extend: objectAssign,
2308 toStringJSON: toStringJSON,
2309 toJSONString: toJSONString,
2310 keys: objectKeys,
2311 values: objectValues,
2312 entries: objectEntries,
2313 pick: pick,
2314 omit: omit,
2315 first: getFirst,
2316 last: getLast,
2317 each: each,
2318 forOf: forOf,
2319 arrayEach: arrayEach,
2320 forEach: arrayEach,
2321 objectEach: objectEach,
2322 lastForOf: lastForOf,
2323 lastEach: lastEach,
2324 lastForEach: lastArrayEach,
2325 lastArrayEach: lastArrayEach,
2326 lastObjectEach: lastObjectEach,
2327 has: has,
2328 get: get,
2329 set: set,
2330 groupBy: groupBy,
2331 countBy: countBy,
2332 objectMap: objectMap,
2333 clone: clone,
2334 delay: delay,
2335 bind: bind,
2336 once: once,
2337 after: after,
2338 before: before,
2339 clear: clearObject,
2340 remove: removeObject,
2341 range: range,
2342 throttle: throttle,
2343 debounce: debounce,
2344 destructuring: destructuring
2345 }
2346
2347 /* eslint-disable valid-typeof */
2348 function isBrowseStorage (storage) {
2349 try {
2350 var testKey = '__xe_t'
2351 storage.setItem(testKey, 1)
2352 storage.removeItem(testKey)
2353 return true
2354 } catch (e) {
2355 return false
2356 }
2357 }
2358
2359 function isBrowseType (type) {
2360 return navigator.userAgent.indexOf(type) > -1
2361 }
2362
2363 /**
2364 * 获取浏览器内核
2365 * @return Object
2366 */
2367 function browse () {
2368 var $body, $dom, isChrome, isEdge
2369 var isMobile = false
2370 var strUndefined = 'undefined'
2371 var result = {
2372 isNode: false,
2373 isMobile: isMobile,
2374 isPC: false,
2375 isDoc: typeof document !== strUndefined
2376 }
2377 if (typeof window === strUndefined && typeof process !== strUndefined) {
2378 result.isNode = true
2379 } else {
2380 isEdge = isBrowseType('Edge')
2381 isChrome = isBrowseType('Chrome')
2382 isMobile = /(Android|webOS|iPhone|iPad|iPod|SymbianOS|BlackBerry|Windows Phone)/.test(navigator.userAgent)
2383 if (result.isDoc) {
2384 $dom = document
2385 $body = $dom.body || $dom.documentElement
2386 baseExports.each(['webkit', 'khtml', 'moz', 'ms', 'o'], function (core) {
2387 result['-' + core] = !!$body[core + 'MatchesSelector']
2388 })
2389 }
2390 baseExports.assign(result, {
2391 edge: isEdge,
2392 msie: !isEdge && result['-ms'],
2393 safari: !isChrome && !isEdge && isBrowseType('Safari'),
2394 isMobile: isMobile,
2395 isPC: !isMobile,
2396 isLocalStorage: isBrowseStorage(window.localStorage),
2397 isSessionStorage: isBrowseStorage(window.sessionStorage)
2398 })
2399 }
2400 return result
2401 }
2402
2403 var browseExports = {
2404 browse: browse
2405 }
2406
2407 var isBowseDoc = typeof document !== 'undefined'
2408
2409 function toCookieUnitTime (unit, expires) {
2410 var num = parseFloat(expires)
2411 var nowdate = new Date()
2412 var time = nowdate.getTime()
2413 switch (unit) {
2414 case 'y': return dateExports.getWhatYear(nowdate, num).getTime()
2415 case 'M': return dateExports.getWhatMonth(nowdate, num).getTime()
2416 case 'd': return dateExports.getWhatDay(nowdate, num).getTime()
2417 case 'h':
2418 case 'H': return time + num * 60 * 60 * 1000
2419 case 'm': return time + num * 60 * 1000
2420 case 's': return time + num * 1000
2421 }
2422 return time
2423 }
2424
2425 function toCookieUTCString (date) {
2426 return (baseExports.isDate(date) ? date : new Date(date)).toUTCString()
2427 }
2428
2429 /**
2430 * cookie操作函数
2431 * @param {String/Array/Object} name 键/数组/对象
2432 * @param {String} value 值
2433 * @param {Object} options 参数
2434 * @param {String} name: 键
2435 * @param {Object} value: 值
2436 * @param {String} path: 路径
2437 * @param {String} domain: 作用域
2438 * @param {Boolean} secure: 设置为安全的,只能用https协议
2439 * @param {Number} expires: 过期时间,可以指定日期或者字符串,默认天
2440 */
2441 function cookie (name, value, options) {
2442 if (isBowseDoc) {
2443 var opts, expires, values, result, cookies, keyIndex
2444 var inserts = []
2445 var args = arguments
2446 var decode = decodeURIComponent
2447 var encode = encodeURIComponent
2448 var $dom = document
2449 var arrayEach = baseExports.each
2450 var objectAssign = baseExports.assign
2451 var isObject = baseExports.isObject
2452 if (this && this.$context) {
2453 this.$context = null
2454 }
2455 if (baseExports.isArray(name)) {
2456 inserts = name
2457 } else if (args.length > 1) {
2458 inserts = [objectAssign({ name: name, value: value }, options)]
2459 } else if (isObject(name)) {
2460 inserts = [name]
2461 }
2462 if (inserts.length > 0) {
2463 arrayEach(inserts, function (obj) {
2464 opts = objectAssign({}, setupDefaults.cookies, obj)
2465 values = []
2466 if (opts.name) {
2467 expires = opts.expires
2468 values.push(encode(opts.name) + '=' + encode(isObject(opts.value) ? JSON.stringify(opts.value) : opts.value))
2469 if (expires) {
2470 if (isNaN(expires)) {
2471 // UTCString || Unit
2472 expires = expires.replace(/^([0-9]+)(y|M|d|H|h|m|s)$/, function (text, num, unit) {
2473 return toCookieUTCString(toCookieUnitTime(unit, num))
2474 })
2475 } else if (/^[0-9]{11,13}$/.test(expires) || baseExports.isDate(expires)) {
2476 // Date || now
2477 expires = toCookieUTCString(expires)
2478 } else {
2479 // day
2480 expires = toCookieUTCString(toCookieUnitTime('d', expires))
2481 }
2482 opts.expires = expires
2483 }
2484 arrayEach(['expires', 'path', 'domain', 'secure'], function (key) {
2485 if (opts[key] !== undefined) {
2486 values.push(opts[key] && key === 'secure' ? key : (key + '=' + opts[key]))
2487 }
2488 })
2489 }
2490 $dom.cookie = values.join('; ')
2491 })
2492 return true
2493 } else {
2494 result = {}
2495 cookies = $dom.cookie
2496 if (cookies) {
2497 arrayEach(cookies.split('; '), function (val) {
2498 keyIndex = val.indexOf('=')
2499 result[decode(val.substring(0, keyIndex))] = decode(val.substring(keyIndex + 1) || '')
2500 })
2501 }
2502 return args.length === 1 ? result[name] : result
2503 }
2504 }
2505 return false
2506 }
2507
2508 function isCookieKey (key) {
2509 return baseExports.includes(cookieKeys(), key)
2510 }
2511
2512 function setCookieItem (name, key, options) {
2513 cookie(name, key, options)
2514 return cookie
2515 }
2516
2517 function removeCookieItem (name, options) {
2518 cookie(name, 0, baseExports.assign({ expires: -1 }, setupDefaults.cookies, options))
2519 }
2520
2521 function cookieKeys () {
2522 return baseExports.keys(cookie())
2523 }
2524
2525 baseExports.assign(cookie, {
2526 _c: false,
2527 isKey: isCookieKey,
2528 set: setCookieItem,
2529 setItem: setCookieItem,
2530 get: cookie,
2531 getItem: cookie,
2532 remove: removeCookieItem,
2533 removeItem: removeCookieItem,
2534 keys: cookieKeys,
2535 getJSON: cookie
2536 })
2537
2538 var cookieExports = {
2539 cookie: cookie
2540 }
2541
2542 var DAY_TIME = 86400000
2543 var WEEK_TIME = DAY_TIME * 7
2544 var STRING_FIRST = 'first'
2545 var STRING_LAST = 'last'
2546
2547 /**
2548 * 返回当前时间戳
2549 *
2550 * @returns Number
2551 */
2552 var now = Date.now || function () {
2553 return getDateTime(new Date())
2554 }
2555
2556 /**
2557 * 将日期格式化为时间戳
2558 *
2559 * @param {String/Number/Date} str 日期或数字
2560 * @param {String} format 解析日期格式
2561 * @returns Number
2562 */
2563 var timestamp = function (str, format) {
2564 if (arguments.length) {
2565 var date = toStringDate(str, format)
2566 return baseExports.isDate(date) ? getDateTime(date) : date
2567 }
2568 return now()
2569 }
2570
2571 var dateFormatRules = [
2572 { rules: [['yyyy', 4], ['yy', 2]] },
2573 { rules: [['MM', 2], ['M', 1]], offset: -1 },
2574 { rules: [['dd', 2], ['d', 1]] },
2575 { rules: [['HH', 2], ['H', 1]] },
2576 { rules: [['mm', 2], ['m', 1]] },
2577 { rules: [['ss', 2], ['s', 1]] },
2578 { rules: [['SSS', 3], ['SS', 2], ['S', 1]] },
2579 { rules: [['ZZ', 5], ['Z', 6]] }
2580 ]
2581
2582 function getDateTime (date) {
2583 return date.getTime()
2584 }
2585
2586 function _utcDateTime (dates) {
2587 return Date.UTC(dates[0], dates[1], dates[2], dates[3], dates[4], dates[5], dates[6])
2588 }
2589
2590 function _dateFullYear (date) {
2591 return date.getFullYear()
2592 }
2593
2594 function _dateMonth (date) {
2595 return date.getMonth()
2596 }
2597
2598 function getYMD (date) {
2599 return new Date(_dateFullYear(date), _dateMonth(date), date.getDate())
2600 }
2601
2602 function getYMDTime (date) {
2603 return getDateTime(getYMD(date))
2604 }
2605
2606 /**
2607 * 比较两个日期
2608 *
2609 * @param {Number/String/Date} date1 日期
2610 * @param {Number/String/Date} date2 日期
2611 * @param {String} format 格式化
2612 */
2613 function isDateSame (date1, date2, format) {
2614 if (date1 && date2) {
2615 return toDateString(date1, format) === toDateString(date2, format)
2616 }
2617 return false
2618 }
2619
2620 /**
2621 * 字符串转为日期
2622 *
2623 * @param {String/Number/Date} str 日期或数字
2624 * @param {String} format 解析日期格式(yyyy年份、MM月份、dd天、hh(12)HH(24)小时、mm分钟、ss秒、SSS毫秒、Z时区)
2625 * @return {String}
2626 */
2627 function toStringDate (str, format) {
2628 var arr, sIndex, index, rules, len, rest, isDate, tempMatch, zStr
2629 var dates = []
2630 if (str) {
2631 isDate = baseExports.isDate(str)
2632 if (isDate || /^[0-9]{11,13}$/.test(str)) {
2633 rest = new Date(isDate ? getDateTime(str) : Number(str))
2634 } else if (baseExports.isString(str)) {
2635 format = format || setupDefaults.formatDate
2636 baseExports.each(dateFormatRules, function (item) {
2637 for (index = 0, rules = item.rules, len = rules.length; index < len; index++) {
2638 arr = rules[index]
2639 sIndex = format.indexOf(arr[0])
2640 if (sIndex > -1) {
2641 tempMatch = str.substring(sIndex, sIndex + arr[1]) || 0
2642 if (item.offset) {
2643 tempMatch = parseFloat(tempMatch) + item.offset
2644 }
2645 dates.push(tempMatch)
2646 break
2647 } else if (index === len - 1) {
2648 dates.push(0)
2649 }
2650 }
2651 })
2652 zStr = dates[7]
2653 // 解析时区
2654 if (zStr) {
2655 // 如果为UTC 时间
2656 if (zStr[0] === 'z' || zStr[0] === 'Z') {
2657 rest = new Date(_utcDateTime(dates))
2658 } else {
2659 // 如果指定时区,时区转换
2660 tempMatch = zStr.match(/([-+]{1})(d{2}):?(d{2})/)
2661 if (tempMatch) {
2662 rest = new Date(_utcDateTime(dates) - (tempMatch[1] === '-' ? -1 : 1) * parseInt(tempMatch[2]) * 3600000 + parseInt(tempMatch[3]) * 60000)
2663 }
2664 }
2665 } else {
2666 rest = new Date(dates[0], dates[1], dates[2], dates[3], dates[4], dates[5], dates[6])
2667 }
2668 }
2669 }
2670 return !rest || isNaN(getDateTime(rest)) ? 'Invalid Date' : rest
2671 }
2672
2673 function handleCustomTemplate (date, formats, match, value) {
2674 var format = formats[match]
2675 if (format) {
2676 if (baseExports.isFunction(format)) {
2677 return format(value, match, date)
2678 } else {
2679 return format[value]
2680 }
2681 }
2682 return value
2683 }
2684
2685 function formatPadStart (str, len, padStr) {
2686 str = '' + str
2687 var index = str.length
2688 while (index < len) {
2689 str = padStr + str
2690 index++
2691 }
2692 return str
2693 }
2694
2695 /**
2696 * 日期格式化为字符串
2697 *
2698 * @param {Date} date 日期或数字
2699 * @param {String} format 输出日期格式(年份(yy|yyyy)、月份(M|MM自动补0)、天(d|dd自动补0)、12小时制(h|hh自动补0)、24小时制(H|HH自动补0)、分钟(m|mm自动补0)、秒(s|ss自动补0)、毫秒(S|SSS自动补0)、D当年的第几天、a/A上午下午、e/E星期几、w当年的第几周、W当月的第几周、q当年第几个季度、Z时区)
2700 * @param {Object} options {formats: {q: ['日', '一', '二', '三', '四', '五', '六'], E: function (value, match, date) {return '三'}, }} 自定义格式化模板
2701 * @return {String}
2702 */
2703 function toDateString (date, format, options) {
2704 if (date) {
2705 date = toStringDate(date)
2706 if (baseExports.isDate(date)) {
2707 var result = format || setupDefaults.formatString
2708 var hours = date.getHours()
2709 var apm = hours < 12 ? 'am' : 'pm'
2710 var zoneHours = date.getTimezoneOffset() / 60 * -1
2711 var formats = baseExports.assign({}, setupDefaults.formatStringMatchs, options ? options.formats : null)
2712 var timeRules = [
2713 [/y{2,4}/g, '', function (match) { return ('' + _dateFullYear(date)).substr(4 - match.length) }],
2714 [/M{1,2}/g, _dateMonth(date) + 1],
2715 [/d{1,2}/g, date.getDate()],
2716 [/H{1,2}/g, hours],
2717 [/h{1,2}/g, hours <= 12 ? hours : hours - 12],
2718 [/m{1,2}/g, date.getMinutes()],
2719 [/s{1,2}/g, date.getSeconds()],
2720 [/S{1,3}/g, date.getMilliseconds()],
2721 [/a/g, '', function (match) { return handleCustomTemplate(date, formats, match, apm) }],
2722 [/A/g, '', function (match) { return handleCustomTemplate(date, formats, match, apm.toLocaleUpperCase()) }],
2723 [/e/g, '', function (match) { return handleCustomTemplate(date, formats, match, date.getDay() - 1) }],
2724 [/E/g, '', function (match) { return handleCustomTemplate(date, formats, match, date.getDay()) }],
2725 [/q/g, '', function (match) { return handleCustomTemplate(date, formats, match, Math.floor((_dateMonth(date) + 3) / 3)) }],
2726 [/Z{1,2}/g, '', function (match) { return handleCustomTemplate(date, formats, match, (zoneHours >= 0 ? '+' : '-') + formatPadStart(zoneHours, 2, '0') + (match.length === 1 ? ':' : '') + '00') }],
2727 [/W{1,2}/g, '', function (match) { return formatPadStart(handleCustomTemplate(date, formats, match, getYearWeek(date)), match.length, '0') }],
2728 [/D{1,3}/g, '', function (match) { return formatPadStart(handleCustomTemplate(date, formats, match, getYearDay(date)), match.length, '0') }]
2729 ]
2730 var item
2731 var index = 0
2732 var len = timeRules.length
2733 for (; index < len; index++) {
2734 item = timeRules[index]
2735 result = result.replace(item[0], item[2] || function (match) {
2736 return formatPadStart(item[1], match.length, '0')
2737 })
2738 }
2739 return result
2740 }
2741 return date
2742 }
2743 return ''
2744 }
2745
2746 /**
2747 * 返回前几年或后几年的日期
2748 *
2749 * @param {Date} date 日期或数字
2750 * @param {Number} year 年(默认当前年)、前几个年(数值)、后几个年(数值)
2751 * @param {Number/String} month 获取哪月(null默认当前年)、年初(first)、年末(last)、指定月份(0-11)
2752 * @return {Date}
2753 */
2754 function getWhatYear (date, year, month) {
2755 var number
2756 date = toStringDate(date)
2757 if (baseExports.isDate(date)) {
2758 if (year) {
2759 number = year && !isNaN(year) ? year : 0
2760 date.setFullYear(_dateFullYear(date) + number)
2761 }
2762 if (month || !isNaN(month)) {
2763 if (month === STRING_FIRST) {
2764 return new Date(_dateFullYear(date), 0, 1)
2765 } else if (month === STRING_LAST) {
2766 date.setMonth(11)
2767 return getWhatMonth(date, 0, STRING_LAST)
2768 } else {
2769 date.setMonth(month)
2770 }
2771 }
2772 }
2773 return date
2774 }
2775
2776 /**
2777 * 返回前几月或后几月的日期
2778 *
2779 * @param {Date} date 日期或数字
2780 * @param {Number} month 月(默认当前月)、前几个月、后几个月
2781 * @param {Number/String} day 获取哪天(null默认当前天)、月初(first)、月末(last)、指定天数(数值)
2782 * @return {Date}
2783 */
2784 function getWhatMonth (date, month, day) {
2785 var monthOffset = month && !isNaN(month) ? month : 0
2786 date = toStringDate(date)
2787 if (baseExports.isDate(date)) {
2788 if (day || !isNaN(day)) {
2789 if (day === STRING_FIRST) {
2790 return new Date(_dateFullYear(date), _dateMonth(date) + monthOffset, 1)
2791 } else if (day === STRING_LAST) {
2792 return new Date(getDateTime(getWhatMonth(date, monthOffset + 1, STRING_FIRST)) - 1)
2793 } else {
2794 date.setDate(day)
2795 }
2796 }
2797 if (monthOffset) {
2798 date.setMonth(_dateMonth(date) + monthOffset)
2799 }
2800 }
2801 return date
2802 }
2803
2804 /**
2805 * 返回前几周或后几周的星期几
2806 *
2807 * @param {Date} date 日期
2808 * @param {Number} week 周(默认当前周)、前几周、后几周
2809 * @param {Number} day 星期天(默认0)、星期一(1)、星期二(2)、星期三(3)、星期四(4)、星期五(5)、星期六(6)
2810 * @return {Date}
2811 */
2812 function getWhatWeek (date, week, day) {
2813 var time, whatDayTime, currentDay, customDay
2814 date = toStringDate(date)
2815 if (baseExports.isDate(date)) {
2816 customDay = Number(/^[0-7]$/.test(day) ? day : date.getDay())
2817 currentDay = date.getDay()
2818 time = getDateTime(date)
2819 whatDayTime = time + ((customDay === 0 ? 7 : customDay) - (currentDay === 0 ? 7 : currentDay)) * DAY_TIME
2820 if (week && !isNaN(week)) {
2821 whatDayTime += week * WEEK_TIME
2822 }
2823 return new Date(whatDayTime)
2824 }
2825 return date
2826 }
2827
2828 /**
2829 * 返回前几天或后几天的日期
2830 *
2831 * @param {Date} date 日期或数字
2832 * @param {Number} day 天(默认当天)、前几天、后几天
2833 * @param {String} mode 获取时分秒(null默认当前时分秒)、日初(first)、日末(last)
2834 * @return {Date}
2835 */
2836 function getWhatDay (date, day, mode) {
2837 date = toStringDate(date)
2838 if (baseExports.isDate(date) && !isNaN(day)) {
2839 date.setDate(date.getDate() + Number(day))
2840 if (mode === STRING_FIRST) {
2841 return new Date(_dateFullYear(date), _dateMonth(date), date.getDate())
2842 } else if (mode === STRING_LAST) {
2843 return new Date(getDateTime(getWhatDay(date, 1, STRING_FIRST)) - 1)
2844 }
2845 }
2846 return date
2847 }
2848
2849 /**
2850 * 返回某个月的第几周
2851 *
2852 * @param {Date} date 日期或数字
2853 * @return {Number}
2854 */
2855 function getMonthWeek (date) {
2856 var monthFirst, monthFirstWeek
2857 var currentDate = toStringDate(date)
2858 if (baseExports.isDate(currentDate)) {
2859 monthFirst = getWhatMonth(currentDate, 0, STRING_FIRST)
2860 monthFirstWeek = getWhatWeek(monthFirst, 0, 1)
2861 if (monthFirstWeek < monthFirst) {
2862 monthFirstWeek = getWhatWeek(monthFirst, 1, 1)
2863 }
2864 if (currentDate >= monthFirstWeek) {
2865 return Math.floor((getYMDTime(currentDate) - getYMDTime(monthFirstWeek)) / WEEK_TIME) + 1
2866 }
2867 return getMonthWeek(getWhatWeek(currentDate, 0, 1))
2868 }
2869 return currentDate
2870 }
2871
2872 /**
2873 * 返回某个年份的第几天
2874 *
2875 * @param {Date} date 日期或数字
2876 * @return {Number}
2877 */
2878 function getYearDay (date) {
2879 date = toStringDate(date)
2880 if (baseExports.isDate(date)) {
2881 return Math.floor((getYMDTime(date) - getYMDTime(getWhatYear(date, 0, STRING_FIRST))) / DAY_TIME) + 1
2882 }
2883 return date
2884 }
2885
2886 /**
2887 * 返回某个年份的第几周
2888 *
2889 * @param {Date} date 日期或数字
2890 * @return {Number}
2891 */
2892 function getYearWeek (date) {
2893 date = toStringDate(date)
2894 if (baseExports.isDate(date)) {
2895 date.setHours(0, 0, 0, 0)
2896 date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7)
2897 var week = new Date(date.getFullYear(), 0, 4)
2898 return Math.round(((date.getTime() - week.getTime()) / DAY_TIME + (week.getDay() + 6) % 7 - 3) / 7) + 1
2899 }
2900 return date
2901 }
2902
2903 /**
2904 * 返回某个年份的天数
2905 *
2906 * @param {Date} date 日期或数字
2907 * @param {Number} year 年(默认当年)、前几个年、后几个年
2908 * @return {Number}
2909 */
2910 function getDayOfYear (date, year) {
2911 date = toStringDate(date)
2912 if (baseExports.isDate(date)) {
2913 return baseExports.isLeapYear(getWhatYear(date, year)) ? 366 : 365
2914 }
2915 return date
2916 }
2917
2918 /**
2919 * 返回某个月份的天数
2920 *
2921 * @param {Date} date 日期或数字
2922 * @param {Number} month 月(默认当月)、前几个月、后几个月
2923 * @return {Number}
2924 */
2925 function getDayOfMonth (date, month) {
2926 date = toStringDate(date)
2927 if (baseExports.isDate(date)) {
2928 return Math.floor((getDateTime(getWhatMonth(date, month, STRING_LAST)) - getDateTime(getWhatMonth(date, month, STRING_FIRST))) / DAY_TIME) + 1
2929 }
2930 return date
2931 }
2932
2933 /**
2934 * 返回两个日期之间差距,如果结束日期小于开始日期done为fasle
2935 *
2936 * @param {Date} startDate 开始日期
2937 * @param {Date} endDate 结束日期或当期日期
2938 * @param {Date} rule 自定义计算规则
2939 * @return {Object}
2940 */
2941 function getDateDiff (startDate, endDate, rules) {
2942 var startTime, endTime, item, diffTime, rule, len, index
2943 var result = { done: false, time: 0 }
2944 startDate = toStringDate(startDate)
2945 endDate = endDate ? toStringDate(endDate) : new Date()
2946 if (baseExports.isDate(startDate) && baseExports.isDate(endDate)) {
2947 startTime = getDateTime(startDate)
2948 endTime = getDateTime(endDate)
2949 if (startTime < endTime) {
2950 diffTime = result.time = endTime - startTime
2951 rule = rules && rules.length > 0 ? rules : setupDefaults.dateDiffRules
2952 result.done = true
2953 for (index = 0, len = rule.length; index < len; index++) {
2954 item = rule[index]
2955 if (diffTime >= item[1]) {
2956 if (index === len - 1) {
2957 result[item[0]] = diffTime || 0
2958 } else {
2959 result[item[0]] = Math.floor(diffTime / item[1])
2960 diffTime -= result[item[0]] * item[1]
2961 }
2962 } else {
2963 result[item[0]] = 0
2964 }
2965 }
2966 }
2967 }
2968 return result
2969 }
2970
2971 var dateExports = {
2972 now: now,
2973 timestamp: timestamp,
2974 isDateSame: isDateSame,
2975 toStringDate: toStringDate,
2976 toDateString: toDateString,
2977 getWhatYear: getWhatYear,
2978 getWhatMonth: getWhatMonth,
2979 getWhatWeek: getWhatWeek,
2980 getWhatDay: getWhatDay,
2981 getYearDay: getYearDay,
2982 getYearWeek: getYearWeek,
2983 getMonthWeek: getMonthWeek,
2984 getDayOfYear: getDayOfYear,
2985 getDayOfMonth: getDayOfMonth,
2986 getDateDiff: getDateDiff
2987 }
2988
2989 var $locat = typeof location === 'undefined' ? 0 : location
2990 var decode = decodeURIComponent
2991 var encode = encodeURIComponent
2992
2993 function parseURLQuery (uri) {
2994 return parseParams(uri.split('?')[1] || '')
2995 }
2996
2997 /**
2998 * 查询参数序列化
2999 *
3000 * @param {String} query 反序列化的字符串
3001 */
3002 function parseParams (str) {
3003 var items
3004 var result = {}
3005 if (str && baseExports.isString(str)) {
3006 baseExports.each(str.split('&'), function (param) {
3007 items = param.split('=')
3008 result[decode(items[0])] = decode(items[1] || '')
3009 })
3010 }
3011 return result
3012 }
3013
3014 function stringifyParams (resultVal, resultKey, isArr) {
3015 var _arr
3016 var result = []
3017 baseExports.each(resultVal, function (item, key) {
3018 _arr = baseExports.isArray(item)
3019 if (baseExports.isPlainObject(item) || _arr) {
3020 result = result.concat(stringifyParams(item, resultKey + '[' + key + ']', _arr))
3021 } else {
3022 result.push(encode(resultKey + '[' + (isArr ? '' : key) + ']') + '=' + encode(item === null ? '' : item))
3023 }
3024 })
3025 return result
3026 }
3027
3028 function getLocatOrigin () {
3029 return $locat ? ($locat.origin || ($locat.protocol + '//' + $locat.host)) : ''
3030 }
3031
3032 function getBaseURL () {
3033 if ($locat) {
3034 var pathname = $locat.pathname
3035 var lastIndex = baseExports.lastIndexOf(pathname, '/') + 1
3036 return getLocatOrigin() + (lastIndex === pathname.length ? pathname : pathname.substring(0, lastIndex))
3037 }
3038 return ''
3039 }
3040
3041 function parseUrl (url) {
3042 var hashs, portText, searchs, parsed
3043 var href = '' + url
3044 if (href.indexOf('//') === 0) {
3045 href = ($locat ? $locat.protocol : '') + href
3046 } else if (href.indexOf('/') === 0) {
3047 href = getLocatOrigin() + href
3048 }
3049 searchs = href.replace(/#.*/, '').match(/(?.*)/)
3050 parsed = {
3051 href: href,
3052 hash: '',
3053 host: '',
3054 hostname: '',
3055 protocol: '',
3056 port: '',
3057 search: searchs && searchs[1] && searchs[1].length > 1 ? searchs[1] : ''
3058 }
3059 parsed.path = href.replace(/^([a-z0-9.+-]*:)///, function (text, protocol) {
3060 parsed.protocol = protocol
3061 return ''
3062 }).replace(/^([a-z0-9.+-]*)(:d+)?/?/, function (text, hostname, port) {
3063 portText = port || ''
3064 parsed.port = portText.replace(':', '')
3065 parsed.hostname = hostname
3066 parsed.host = hostname + portText
3067 return '/'
3068 }).replace(/(#.*)/, function (text, hash) {
3069 parsed.hash = hash.length > 1 ? hash : ''
3070 return ''
3071 })
3072 hashs = parsed.hash.match(/#((.*)?|(.*))/)
3073 parsed.pathname = parsed.path.replace(/(?|#.*).*/, '')
3074 parsed.origin = parsed.protocol + '//' + parsed.host
3075 parsed.hashKey = hashs ? (hashs[2] || hashs[1] || '') : ''
3076 parsed.hashQuery = parseURLQuery(parsed.hash)
3077 parsed.searchQuery = parseURLQuery(parsed.search)
3078 return parsed
3079 }
3080
3081 /**
3082 * 获取地址栏信息
3083 *
3084 * @return Object
3085 */
3086 function locat () {
3087 return $locat ? parseUrl($locat.href) : {}
3088 }
3089
3090 /**
3091 * 查询参数序列化
3092 *
3093 * @param {Object} query 序列化的对象
3094 */
3095 function serialize (query) {
3096 var _arr
3097 var params = []
3098 baseExports.each(query, function (item, key) {
3099 if (item !== undefined) {
3100 _arr = baseExports.isArray(item)
3101 if (baseExports.isPlainObject(item) || _arr) {
3102 params = params.concat(stringifyParams(item, key, _arr))
3103 } else {
3104 params.push(encode(key) + '=' + encode(item === null ? '' : item))
3105 }
3106 }
3107 })
3108 return params.join('&').replace(/%20/g, '+')
3109 }
3110
3111 var locatExports = {
3112 parseUrl: parseUrl,
3113 getBaseURL: getBaseURL,
3114 locat: locat,
3115 serialize: serialize,
3116 unserialize: parseParams
3117 }
3118
3119 /**
3120 * 获取一个指定范围内随机数
3121 *
3122 * @param {Number} min 最小值
3123 * @param {Number} max 最大值
3124 * @return {Number}
3125 */
3126 function getRandom (min, max) {
3127 return min >= max ? min : ((min = min >> 0) + Math.round(Math.random() * ((max || 9) - min)))
3128 }
3129
3130 function createMinMax (handle) {
3131 return function (arr, iterate) {
3132 return handle(XEUtils.sortBy(baseExports.clone(arr), iterate, this))
3133 }
3134 }
3135
3136 /**
3137 * 获取最小值
3138 *
3139 * @param {Array} arr 数组
3140 * @param {Function} iterate(item, index, obj) 回调
3141 * @return {Number}
3142 */
3143 var arrayMin = createMinMax(function (result) {
3144 return result[0]
3145 })
3146
3147 /**
3148 * 获取最大值
3149 *
3150 * @param {Array} arr 数组
3151 * @param {Function} iterate(item, index, obj) 回调
3152 * @return {Number}
3153 */
3154 var arrayMax = createMinMax(function (result) {
3155 return result.reverse()[0]
3156 })
3157
3158 /**
3159 * 千分位分隔符、小数点
3160 *
3161 * @param {String/Number} num 数值
3162 * @param {Object} 参数 {spaceNumber: 分割位数(默认3), separator: 分隔符(默认,), fixed: 小数位数(默认null)}
3163 * @return {String}
3164 */
3165 function commafy (num, options) {
3166 num = ('' + num).replace(/,/g, '')
3167 if (num) {
3168 var opts = baseExports.assign({ spaceNumber: 3, separator: ',' }, options)
3169 var optFixed = opts.fixed
3170 var result = (optFixed ? stringToNumber(num).toFixed(optFixed) : num).split('.')
3171 return result[0].replace(new RegExp('(?=(?!(\b))(\d{' + opts.spaceNumber + '})+$)', 'g'), opts.separator) + (result[1] ? '.' + result[1] : '')
3172 }
3173 return num
3174 }
3175
3176 function createToNumber (handle) {
3177 return function (str) {
3178 if (str) {
3179 var num = handle(str)
3180 return isNaN(num) ? 0 : num
3181 }
3182 return 0
3183 }
3184 }
3185
3186 /**
3187 * 和 Number.toFixed 类似,区别就是不会对小数进行四舍五入,结果返回字符串
3188 *
3189 * @param { String/Number } str 数值
3190 * @return {String}
3191 */
3192 function toFixedString (str, digits) {
3193 var nums = ('' + toFixedNumber(str, digits)).split('.')
3194 return digits ? [nums[0], '.', XEUtils.padEnd(nums[1] || '', digits, '0')].join('') : nums[0]
3195 }
3196
3197 /**
3198 * 和 Number.toFixed 类似,区别就是不会对小数进行四舍五入,结果返回数值
3199 *
3200 * @param { String/Number } str 数值
3201 * @return {String}
3202 */
3203 function toFixedNumber (str, digits) {
3204 if (digits) {
3205 return stringToNumber(('' + stringToNumber(str)).replace(new RegExp('(\d+.\d{0,' + digits + '}).*'), '$1'))
3206 }
3207 return stringToInteger(str)
3208 }
3209
3210 /**
3211 * 转数值
3212 * @param { String/Number } str 数值
3213 *
3214 * @return {Number}
3215 */
3216 var stringToNumber = createToNumber(parseFloat)
3217
3218 /**
3219 * 转整数
3220 * @param { String/Number } str 数值
3221 *
3222 * @return {Number}
3223 */
3224 var stringToInteger = createToNumber(parseInt)
3225
3226 var numberExports = {
3227 random: getRandom,
3228 min: arrayMin,
3229 max: arrayMax,
3230 commafy: commafy,
3231 toFixedString: toFixedString,
3232 toFixedNumber: toFixedNumber,
3233 toNumber: stringToNumber,
3234 toInteger: stringToInteger
3235 }
3236
3237 /**
3238 * 去除字符串左右两边的空格
3239 *
3240 * @param {String} str 字符串
3241 * @return {String}
3242 */
3243 function stringTrim (str) {
3244 return str && str.trim ? str.trim() : stringTrimRight(stringTrimLeft(str))
3245 }
3246
3247 /**
3248 * 去除字符串左边的空格
3249 *
3250 * @param {String} str 字符串
3251 * @return {String}
3252 */
3253 function stringTrimLeft (str) {
3254 return str && str.trimLeft ? str.trimLeft() : ('' + str).replace(/^[suFEFFxA0]+/g, '')
3255 }
3256
3257 /**
3258 * 去除字符串右边的空格
3259 *
3260 * @param {String} str 字符串
3261 * @return {String}
3262 */
3263 function stringTrimRight (str) {
3264 return str && str.trimRight ? str.trimRight() : ('' + str).replace(/[suFEFFxA0]+$/g, '')
3265 }
3266
3267 var escapeMap = {
3268 '&': '&',
3269 '<': '<',
3270 '>': '>',
3271 '"': '"',
3272 "'": ''',
3273 '`': '`'
3274 }
3275
3276 var unescapeMap = {}
3277 baseExports.each(escapeMap, function (item, key) {
3278 unescapeMap[escapeMap[key]] = key
3279 })
3280
3281 function formatEscaper (dataMap) {
3282 var replaceRegexp = new RegExp('(?:' + baseExports.keys(dataMap).join('|') + ')', 'g')
3283 return function (str) {
3284 return ('' + str).replace(replaceRegexp, function (match) {
3285 return dataMap[match]
3286 })
3287 }
3288 }
3289
3290 /**
3291 * 转义HTML字符串,替换&, <, >, ", ', `字符
3292 *
3293 * @param {String} str 字符串
3294 * @return {String}
3295 */
3296 var escape = formatEscaper(escapeMap)
3297
3298 /**
3299 * 反转escape
3300 *
3301 * @param {String} str 字符串
3302 * @return {String}
3303 */
3304 var unescape = formatEscaper(unescapeMap)
3305
3306 /**
3307 * 将带字符串转成驼峰字符串,例如: project-name 转为 projectName
3308 *
3309 * @param {String} str 字符串
3310 * @return {String}
3311 */
3312 function camelCase (str) {
3313 return ('' + str).replace(/(-[a-zA-Z])/g, function (text, u) {
3314 return u.substring(1).toLocaleUpperCase()
3315 })
3316 }
3317
3318 /**
3319 * 将带驼峰字符串转成字符串,例如: projectName 转为 project-name
3320 *
3321 * @param {String} str 字符串
3322 * @return {String}
3323 */
3324 function kebabCase (str) {
3325 return ('' + str).replace(/([A-Z])/g, function (text, u) {
3326 return '-' + u.toLowerCase()
3327 })
3328 }
3329
3330 /**
3331 * 将字符串重复 n次
3332 *
3333 * @param {String} str 字符串
3334 * @param {Number} count 次数
3335 * @return {String}
3336 */
3337 function stringRepeat (str, count) {
3338 var rest = '' + str
3339 if (str.repeat) {
3340 return str.repeat(count)
3341 }
3342 var list = isNaN(count) ? [] : new Array(parseInt(count))
3343 return list.join(rest) + (list.length > 0 ? rest : '')
3344 }
3345
3346 /**
3347 * 用指定字符从前面开始补全字符串
3348 *
3349 * @param {String} str 字符串
3350 * @param {Number} targetLength 结果长度
3351 * @param {Number} padString 补全字符
3352 * @return {String}
3353 */
3354 function stringPadStart (str, targetLength, padString, UNDEFINED) {
3355 var rest = '' + str
3356 targetLength = targetLength >> 0
3357 padString = padString === UNDEFINED ? ' ' : '' + padString
3358 if (rest.padStart) {
3359 return rest.padStart(targetLength, padString)
3360 }
3361 if (targetLength > rest.length) {
3362 targetLength -= rest.length
3363 if (targetLength > padString.length) {
3364 padString += stringRepeat(padString, targetLength / padString.length)
3365 }
3366 return padString.slice(0, targetLength) + rest
3367 }
3368 return rest
3369 }
3370
3371 /**
3372 * 用指定字符从后面开始补全字符串
3373 *
3374 * @param {String} str 字符串
3375 * @param {Number} targetLength 结果长度
3376 * @param {Number} padString 补全字符
3377 * @return {String}
3378 */
3379 function stringPadEnd (str, targetLength, padString, UNDEFINED) {
3380 var rest = '' + str
3381 targetLength = targetLength >> 0
3382 padString = padString === UNDEFINED ? ' ' : '' + padString
3383 if (rest.padEnd) {
3384 return rest.padEnd(targetLength, padString)
3385 }
3386 if (targetLength > rest.length) {
3387 targetLength -= rest.length
3388 if (targetLength > padString.length) {
3389 padString += stringRepeat(padString, targetLength / padString.length)
3390 }
3391 return rest + padString.slice(0, targetLength)
3392 }
3393 return rest
3394 }
3395
3396 /**
3397 * 判断字符串是否在源字符串的头部
3398 *
3399 * @param {String} str 字符串
3400 * @param {String/Number} val 值
3401 * @param {Number} startIndex 开始索引
3402 * @return {String}
3403 */
3404 function stringStartsWith (str, val, startIndex) {
3405 var rest = '' + str
3406 return (arguments.length === 1 ? rest : rest.substring(startIndex)).indexOf(val) === 0
3407 }
3408
3409 /**
3410 * 判断字符串是否在源字符串的尾部
3411 *
3412 * @param {String} str 字符串
3413 * @param {String/Number} val 值
3414 * @param {Number} startIndex 开始索引
3415 * @return {String}
3416 */
3417 function stringEndsWith (str, val, startIndex) {
3418 var rest = '' + str
3419 return arguments.length === 1 ? rest.indexOf(val) === rest.length - 1 : rest.substring(0, startIndex).indexOf(val) === startIndex - 1
3420 }
3421
3422 var stringExports = {
3423 trim: stringTrim,
3424 trimLeft: stringTrimLeft,
3425 trimRight: stringTrimRight,
3426 escape: escape,
3427 unescape: unescape,
3428 camelCase: camelCase,
3429 kebabCase: kebabCase,
3430 repeat: stringRepeat,
3431 padStart: stringPadStart,
3432 padEnd: stringPadEnd,
3433 startsWith: stringStartsWith,
3434 endsWith: stringEndsWith
3435 }
3436
3437 var methodExports = {}
3438
3439 baseExports.assign(
3440 methodExports,
3441 arrayExports,
3442 baseExports,
3443 browseExports,
3444 cookieExports,
3445 dateExports,
3446 locatExports,
3447 numberExports,
3448 stringExports
3449 )
3450
3451 /**
3452 * functions of mixing
3453 *
3454 * @param {Object} methods
3455 */
3456 XEUtils.mixin = function (methods) {
3457 methodExports.each(methods, function (fn, name) {
3458 XEUtils[name] = methodExports.isFunction(fn) && fn._c !== false ? function () {
3459 var result = fn.apply(XEUtils.$context, arguments)
3460 XEUtils.$context = null
3461 return result
3462 } : fn
3463 })
3464 return XEUtils
3465 }
3466
3467 XEUtils.setup = function (options) {
3468 methodExports.assign(setupDefaults, options)
3469 }
3470
3471 XEUtils.mixin(methodExports)
3472
3473 return XEUtils
3474 }))