UNPKG

114 kBJavaScriptView Raw
1/**
2 * xe-utils.js v3.4.3
3 * MIT License.
4 * @preserve
5 */
6(function (global, factory) {
7 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8 typeof define === 'function' && define.amd ? define(factory) :
9 (global.XEUtils = factory());
10}(this, function () {'use strict'
11
12
13var setupDefaults = {
14 cookies: {
15 path: '/'
16 },
17 treeOptions: {
18 parentKey: 'parentId',
19 key: 'id',
20 children: 'children'
21 },
22 formatString: 'yyyy-MM-dd HH:mm:ss',
23 dateDiffRules: [
24 ['yyyy', 31536000000],
25 ['MM', 2592000000],
26 ['dd', 86400000],
27 ['HH', 3600000],
28 ['mm', 60000],
29 ['ss', 1000],
30 ['S', 0]
31 ]
32}
33
34
35
36
37
38
39var XEUtils = function () {}
40
41function mixin () {
42 arrayEach(arguments, function (methods) {
43 each(methods, function (fn, name) {
44 XEUtils[name] = isFunction(fn) ? function () {
45 var result = fn.apply(XEUtils.$context, arguments)
46 XEUtils.$context = null
47 return result
48 } : fn
49 })
50 })
51}
52
53function setup (options) {
54 return assign(setupDefaults, options)
55}
56
57XEUtils.VERSION = '3.4.2'
58XEUtils.mixin = mixin
59XEUtils.setup = setup
60
61
62
63function helperCreateGetObjects (name, getIndex) {
64 var proMethod = Object[name]
65 return function (obj) {
66 var result = []
67 if (obj) {
68 if (proMethod) {
69 return proMethod(obj)
70 }
71 each(obj, getIndex > 1 ? function (key) {
72 result.push(['' + key, obj[key]])
73 } : function () {
74 result.push(arguments[getIndex])
75 })
76 }
77 return result
78 }
79}
80
81
82
83function helperCreateIndexOf (name, callback) {
84 return function (obj, val) {
85 if (obj) {
86 if (obj[name]) {
87 return obj[name](val)
88 }
89 if (isString(obj) || isArray(obj)) {
90 return callback(obj, val)
91 }
92 for (var key in obj) {
93 if (hasOwnProp(obj, key)) {
94 if (val === obj[key]) {
95 return key
96 }
97 }
98 }
99 }
100 return -1
101 }
102}
103
104
105
106function helperCreateInInObjectString (type) {
107 return function (obj) {
108 return '[object ' + type + ']' === objectToString.call(obj)
109 }
110}
111
112
113/* eslint-disable valid-typeof */
114function helperCreateInTypeof (type) {
115 return function (obj) {
116 return typeof obj === type
117 }
118}
119
120
121
122function helperCreateIterateHandle (prop, useArray, restIndex, matchValue, defaultValue) {
123 return function (obj, iterate, context) {
124 if (obj && iterate) {
125 if (prop && obj[prop]) {
126 return obj[prop](iterate, context)
127 } else {
128 if (useArray && isArray(obj)) {
129 for (var index = 0, len = obj.length; index < len; index++) {
130 if (!!iterate.call(context, obj[index], index, obj) === matchValue) {
131 return [true, false, index, obj[index]][restIndex]
132 }
133 }
134 } else {
135 for (var key in obj) {
136 if (hasOwnProp(obj, key)) {
137 if (!!iterate.call(context, obj[key], key, obj) === matchValue) {
138 return [true, false, key, obj[key]][restIndex]
139 }
140 }
141 }
142 }
143 }
144 }
145 return defaultValue
146 }
147}
148
149
150
151function helperCreateiterateIndexOf (callback) {
152 return function (obj, iterate, context) {
153 if (obj && isFunction(iterate)) {
154 if (isArray(obj) || isString(obj)) {
155 return callback(obj, iterate, context)
156 }
157 for (var key in obj) {
158 if (hasOwnProp(obj, key)) {
159 if (iterate.call(context, obj[key], key, obj)) {
160 return key
161 }
162 }
163 }
164 }
165 return -1
166 }
167}
168
169
170
171
172function helperCreateMathNumber(name) {
173 return function (num, digits) {
174 var numRest = toNumber(num)
175 var rest = numRest
176 if (numRest) {
177 digits = digits >> 0
178 var numStr = toNumberString(numRest)
179 var nums = numStr.split('.')
180 var intStr = nums[0]
181 var floatStr = nums[1] || ''
182 var fStr = floatStr.substring(0, digits + 1)
183 var subRest = intStr + (fStr ? ('.' + fStr) : '')
184 if (digits >= floatStr.length) {
185 return toNumber(subRest)
186 }
187 subRest = numRest
188 if (digits > 0) {
189 var ratio = Math.pow(10, digits)
190 rest = Math[name](helperMultiply(subRest, ratio)) / ratio
191 } else {
192 rest = Math[name](subRest)
193 }
194 }
195 return rest
196 }
197}
198
199
200
201
202function helperCreateMinMax (handle) {
203 return function (arr, iterate) {
204 if (arr && arr.length) {
205 var rest, itemIndex
206 arrayEach(arr, function (itemVal, index) {
207 if (iterate) {
208 itemVal = isFunction(iterate) ? iterate(itemVal, index, arr) : get(itemVal, iterate)
209 }
210 if (!eqNull(itemVal) && (eqNull(rest) || handle(rest, itemVal))) {
211 itemIndex = index
212 rest = itemVal
213 }
214 })
215 return arr[itemIndex]
216 }
217 return rest
218 }
219}
220
221
222
223function helperCreatePickOmit (case1, case2) {
224 return function (obj, callback) {
225 var item, index
226 var rest = {}
227 var result = []
228 var context = this
229 var args = arguments
230 var len = args.length
231 if (!isFunction(callback)) {
232 for (index = 1; index < len; index++) {
233 item = args[index]
234 result.push.apply(result, isArray(item) ? item : [item])
235 }
236 callback = 0
237 }
238 each(obj, function (val, key) {
239 if ((callback ? callback.call(context, val, key, obj) : findIndexOf(result, function (name) {
240 return name === key
241 }) > -1) ? case1 : case2) {
242 rest[key] = val
243 }
244 })
245 return rest
246 }
247}
248
249
250function helperCreateToNumber (handle) {
251 return function (str) {
252 if (str) {
253 var num = handle(str)
254 if (!isNaN(num)) {
255 return num
256 }
257 }
258 return 0
259 }
260}
261
262
263function helperCreateTreeFunc (handle) {
264 return function (obj, iterate, options, context) {
265 var opts = options || {}
266 var optChildren = opts.children || 'children'
267 return handle(null, obj, iterate, context, [], [], optChildren, opts)
268 }
269}
270
271
272function helperDefaultCompare (v1, v2) {
273 return v1 === v2
274}
275
276
277function helperDeleteProperty (obj, property) {
278 try {
279 delete obj[property]
280 } catch (e) {
281 obj[property] = undefined
282 }
283}
284
285
286
287
288function helperEqualCompare (val1, val2, compare, func, key, obj1, obj2) {
289 if (val1 === val2) {
290 return true
291 }
292 if (val1 && val2 && !isNumber(val1) && !isNumber(val2) && !isString(val1) && !isString(val2)) {
293 if (isRegExp(val1)) {
294 return compare('' + val1, '' + val2, key, obj1, obj2)
295 } if (isDate(val1) || isBoolean(val1)) {
296 return compare(+val1, +val2, key, obj1, obj2)
297 } else {
298 var result, val1Keys, val2Keys
299 var isObj1Arr = isArray(val1)
300 var isObj2Arr = isArray(val2)
301 if (isObj1Arr || isObj2Arr ? isObj1Arr && isObj2Arr : val1.constructor === val2.constructor) {
302 val1Keys = keys(val1)
303 val2Keys = keys(val2)
304 if (func) {
305 result = func(val1, val2, key)
306 }
307 if (val1Keys.length === val2Keys.length) {
308 return isUndefined(result) ? every(val1Keys, function (key, index) {
309 return key === val2Keys[index] && helperEqualCompare(val1[key], val2[val2Keys[index]], compare, func, isObj1Arr || isObj2Arr ? index : key, val1, val2)
310 }) : !!result
311 }
312 return false
313 }
314 }
315 }
316 return compare(val1, val2, key, obj1, obj2)
317}
318
319
320
321function helperFormatEscaper (dataMap) {
322 var replaceRegexp = new RegExp('(?:' + keys(dataMap).join('|') + ')', 'g')
323 return function (str) {
324 return toValueString(str).replace(replaceRegexp, function (match) {
325 return dataMap[match]
326 })
327 }
328}
329
330
331function helperGetDateFullYear (date) {
332 return date.getFullYear()
333}
334
335
336function helperGetDateMonth (date) {
337 return date.getMonth()
338}
339
340
341function helperGetDateTime (date) {
342 return date.getTime()
343}
344
345
346function helperGetHGSKeys (property) {
347 // 以最快的方式判断数组,可忽略准确性
348 return property ? (property.splice && property.join ? property : ('' + property).replace(/(\[\d+\])\.?/g,'$1.').replace(/\.$/, '').split('.')) : []
349}
350
351
352
353function helperGetLocatOrigin () {
354 return staticLocation ? (staticLocation.origin || (staticLocation.protocol + '//' + staticLocation.host)) : ''
355}
356
357
358function helperGetUTCDateTime (resMaps) {
359 return Date.UTC(resMaps.y, resMaps.M || 0, resMaps.d || 1, resMaps.H || 0, resMaps.m || 0, resMaps.s || 0, resMaps.S || 0)
360}
361
362
363
364function helperGetYMD (date) {
365 return new Date(helperGetDateFullYear(date), helperGetDateMonth(date), date.getDate())
366}
367
368
369
370function helperGetYMDTime (date) {
371 return helperGetDateTime(helperGetYMD(date))
372}
373
374
375
376function helperMultiply (multiplier, multiplicand) {
377 var str1 = toNumberString(multiplier)
378 var str2 = toNumberString(multiplicand)
379 return parseInt(str1.replace('.', '')) * parseInt(str2.replace('.', '')) / Math.pow(10, helperNumberDecimal(str1) + helperNumberDecimal(str2))
380}
381
382
383function helperNewDate () {
384 return new Date()
385}
386
387
388
389function helperNumberAdd (addend, augend) {
390 var str1 = toNumberString(addend)
391 var str2 = toNumberString(augend)
392 var ratio = Math.pow(10, Math.max(helperNumberDecimal(str1), helperNumberDecimal(str2)))
393 return (multiply(addend, ratio) + multiply(augend, ratio)) / ratio
394}
395
396
397function helperNumberDecimal (numStr) {
398 return (numStr.split('.')[1] || '').length
399}
400
401
402
403function helperNumberDivide (divisor, dividend) {
404 var str1 = toNumberString(divisor)
405 var str2 = toNumberString(dividend)
406 var divisorDecimal = helperNumberDecimal(str1)
407 var dividendDecimal = helperNumberDecimal(str2)
408 var powY = dividendDecimal - divisorDecimal
409 var isMinus = powY < 0
410 var multiplicand = Math.pow(10, isMinus ? Math.abs(powY) : powY)
411 return multiply(str1.replace('.', '') / str2.replace('.', ''), isMinus ? 1 / multiplicand : multiplicand)
412}
413
414
415function helperNumberOffsetPoint (str, offsetIndex) {
416 return str.substring(0, offsetIndex) + '.' + str.substring(offsetIndex, str.length)
417}
418
419
420function helperStringLowerCase (str) {
421 return str.toLowerCase()
422}
423
424
425
426function helperStringRepeat (str, count) {
427 if (str.repeat) {
428 return str.repeat(count)
429 }
430 var list = isNaN(count) ? [] : new Array(staticParseInt(count))
431 return list.join(str) + (list.length > 0 ? str : '')
432}
433
434
435function helperStringSubstring (str, start, end) {
436 return str.substring(start, end)
437}
438
439
440function helperStringUpperCase (str) {
441 return str.toUpperCase()
442}
443
444
445var staticStrUndefined = 'undefined'
446
447
448var staticStrLast = 'last'
449
450
451var staticStrFirst = 'first'
452
453
454var staticDayTime = 86400000
455
456
457
458var staticWeekTime = staticDayTime * 7
459
460
461
462/* eslint-disable valid-typeof */
463var staticLocation = typeof location === staticStrUndefined ? 0 : location
464
465
466
467/* eslint-disable valid-typeof */
468var staticWindow = typeof window === staticStrUndefined ? 0 : window
469
470
471
472/* eslint-disable valid-typeof */
473var staticDocument = typeof document === staticStrUndefined ? 0 : document
474
475
476var staticEncodeURIComponent = encodeURIComponent
477
478
479var staticDecodeURIComponent = decodeURIComponent
480
481
482var objectToString = Object.prototype.toString
483
484
485var staticParseInt = parseInt
486
487
488var staticEscapeMap = {
489 '&': '&amp;',
490 '<': '&lt;',
491 '>': '&gt;',
492 '"': '&quot;',
493 "'": '&#x27;',
494 '`': '&#x60;'
495}
496
497
498var staticHGKeyRE = /(.+)?\[(\d+)\]$/
499
500
501
502var objectAssignFns = Object.assign
503
504function handleAssign (destination, args, isClone) {
505 var len = args.length
506 for (var source, index = 1; index < len; index++) {
507 source = args[index]
508 arrayEach(keys(args[index]), isClone ? function (key) {
509 destination[key] = clone(source[key], isClone)
510 } : function (key) {
511 destination[key] = source[key]
512 })
513 }
514 return destination
515}
516
517/**
518 * 将一个或多个源对象复制到目标对象中
519 *
520 * @param {Object} target 目标对象
521 * @param {...Object}
522 * @return {Boolean}
523 */
524var assign = function (target) {
525 if (target) {
526 var args = arguments
527 if (target === true) {
528 if (args.length > 1) {
529 target = isArray(target[1]) ? [] : {}
530 return handleAssign(target, args, true)
531 }
532 } else {
533 return objectAssignFns ? objectAssignFns.apply(Object, args) : handleAssign(target, args)
534 }
535 }
536 return target
537}
538
539
540
541/**
542 * 指定方法后的返回值组成的新对象
543 *
544 * @param {Object} obj 对象/数组
545 * @param {Function} iterate(item, index, obj) 回调
546 * @param {Object} context 上下文
547 * @return {Object}
548 */
549function objectMap (obj, iterate, context) {
550 var result = {}
551 if (obj) {
552 if (iterate) {
553 if (!isFunction(iterate)) {
554 iterate = property(iterate)
555 }
556 each(obj, function (val, index) {
557 result[index] = iterate.call(context, val, index, obj)
558 })
559 } else {
560 return obj
561 }
562 }
563 return result
564}
565
566
567
568function objectEach (obj, iterate, context) {
569 if (obj) {
570 for (var key in obj) {
571 if (hasOwnProp(obj, key)) {
572 iterate.call(context, obj[key], key, obj)
573 }
574 }
575 }
576}
577
578
579
580function lastObjectEach (obj, iterate, context) {
581 lastArrayEach(keys(obj), function (key) {
582 iterate.call(context, obj[key], key, obj)
583 })
584}
585
586
587
588function handleMerge (target, source) {
589 if ((isPlainObject(target) && isPlainObject(source)) || (isArray(target) && isArray(source))) {
590 each(source, function (obj, key) {
591 target[key] = handleMerge(target[key], obj)
592 })
593 return target
594 }
595 return source
596}
597
598/**
599 * 将一个或多个源对象合并到目标对象中
600 *
601 * @param {Object} target 目标对象
602 * @param {...Object}
603 * @return {Boolean}
604 */
605 var merge = function (target) {
606 if (!target) {
607 target = {}
608 }
609 var args = arguments
610 var len = args.length
611 for (var source, index = 1; index < len; index++) {
612 source = args[index]
613 if (source) {
614 handleMerge(target, source)
615 }
616 }
617 return target
618}
619
620
621
622/**
623 * 数组去重
624 *
625 * @param {Array} array 数组
626 * @return {Array}
627 */
628function uniq (array) {
629 var result = []
630 each(array, function (value) {
631 if (!includes(result, value)) {
632 result.push(value)
633 }
634 })
635 return result
636}
637
638
639
640/**
641 * 将多个数的值返回唯一的并集数组
642 *
643 * @param {...Array} 数组
644 * @return {Array}
645 */
646function union () {
647 var args = arguments
648 var result = []
649 var index = 0
650 var len = args.length
651 for (; index < len; index++) {
652 result = result.concat(toArray(args[index]))
653 }
654 return uniq(result)
655}
656
657
658
659var sortBy = orderBy
660
661
662
663
664var ORDER_PROP_ASC = 'asc'
665var ORDER_PROP_DESC = 'desc'
666
667// function handleSort (v1, v2) {
668// return v1 > v2 ? 1 : -1
669// }
670
671// '' < 数字 < 字符 < null < undefined
672function handleSort (v1, v2) {
673 if (isUndefined(v1)) {
674 return 1
675 }
676 if (isNull(v1)) {
677 return isUndefined(v2) ? -1 : 1
678 }
679 return v1 && v1.localeCompare ? v1.localeCompare(v2) : (v1 > v2 ? 1 : -1)
680}
681
682function buildMultiOrders (name, confs, compares) {
683 return function (item1, item2) {
684 var v1 = item1[name]
685 var v2 = item2[name]
686 if (v1 === v2) {
687 return compares ? compares(item1, item2) : 0
688 }
689 return confs.order === ORDER_PROP_DESC ? handleSort(v2, v1) : handleSort(v1, v2)
690 }
691}
692
693function getSortConfs (arr, list, fieldConfs, context) {
694 var sortConfs = []
695 fieldConfs = isArray(fieldConfs) ? fieldConfs : [fieldConfs]
696 arrayEach(fieldConfs, function (handle, index) {
697 if (handle) {
698 var field = handle
699 var order
700 if (isArray(handle)) {
701 field = handle[0]
702 order = handle[1]
703 } else if (isPlainObject(handle)) {
704 field = handle.field
705 order = handle.order
706 }
707 sortConfs.push({
708 field: field,
709 order: order || ORDER_PROP_ASC
710 })
711 arrayEach(list, isFunction(field) ? function (item, key) {
712 item[index] = field.call(context, item.data, key, arr)
713 } : function (item) {
714 item[index] = field ? get(item.data, field) : item.data
715 })
716 }
717 })
718 return sortConfs
719}
720
721/**
722 * 将数组进行排序
723 *
724 * @param {Array} arr 数组
725 * @param {Function/String/Array} fieldConfs 方法或属性
726 * @param {Object} context 上下文
727 * @return {Array}
728 */
729function orderBy (arr, fieldConfs, context) {
730 if (arr) {
731 if (eqNull(fieldConfs)) {
732 return toArray(arr).sort(handleSort)
733 }
734 var compares
735 var list = map(arr, function (item) {
736 return { data: item }
737 })
738 var sortConfs = getSortConfs(arr, list, fieldConfs, context)
739 var len = sortConfs.length - 1
740 while (len >= 0) {
741 compares = buildMultiOrders(len, sortConfs[len], compares)
742 len--
743 }
744 if (compares) {
745 list = list.sort(compares)
746 }
747 return map(list, property('data'))
748 }
749 return []
750}
751
752
753
754
755/**
756 * 将一个数组随机打乱,返回一个新的数组
757 *
758 * @param {Array} array 数组
759 * @return {Array}
760 */
761function shuffle (array) {
762 var index
763 var result = []
764 var list = values(array)
765 var len = list.length - 1
766 for (; len >= 0; len--) {
767 index = len > 0 ? random(0, len) : 0
768 result.push(list[index])
769 list.splice(index, 1)
770 }
771 return result
772}
773
774
775
776/**
777 * 从一个数组中随机返回几个元素
778 *
779 * @param {Array} array 数组
780 * @param {Number} number 个数
781 * @return {Array}
782 */
783function sample (array, number) {
784 var result = shuffle(array)
785 if (arguments.length <= 1) {
786 return result[0]
787 }
788 if (number < result.length) {
789 result.length = number || 0
790 }
791 return result
792}
793
794
795
796/**
797 * 对象中的值中的每一项运行给定函数,如果函数对任一项返回true,则返回true,否则返回false
798 *
799 * @param {Object} obj 对象/数组
800 * @param {Function} iterate(item, index, obj) 回调
801 * @param {Object} context 上下文
802 * @return {Boolean}
803 */
804var some = helperCreateIterateHandle('some', 1, 0, true, false)
805
806
807
808/**
809 * 对象中的值中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true,否则返回false
810 *
811 * @param {Object} obj 对象/数组
812 * @param {Function} iterate(item, index, obj) 回调
813 * @param {Object} context 上下文
814 * @return {Boolean}
815 */
816var every = helperCreateIterateHandle('every', 1, 1, false, true)
817
818
819
820/**
821 * 裁剪 Arguments 或数组 array,从 start 位置开始到 end 结束,但不包括 end 本身的位置
822 * @param {Array/Arguments} array 数组或Arguments
823 * @param {Number} startIndex 开始索引
824 * @param {Number} endIndex 结束索引
825 */
826function slice (array, startIndex, endIndex) {
827 var result = []
828 var argsSize = arguments.length
829 if (array) {
830 startIndex = argsSize >= 2 ? toNumber(startIndex) : 0
831 endIndex = argsSize >= 3 ? toNumber(endIndex) : array.length
832 if (array.slice) {
833 return array.slice(startIndex, endIndex)
834 }
835 for (; startIndex < endIndex; startIndex++) {
836 result.push(array[startIndex])
837 }
838 }
839 return result
840}
841
842
843
844/**
845 * 根据回调过滤数据
846 *
847 * @param {Object} obj 对象/数组
848 * @param {Function} iterate(item, index, obj) 回调
849 * @param {Object} context 上下文
850 * @return {Object}
851 */
852function filter (obj, iterate, context) {
853 var result = []
854 if (obj && iterate) {
855 if (obj.filter) {
856 return obj.filter(iterate, context)
857 }
858 each(obj, function (val, key) {
859 if (iterate.call(context, val, key, obj)) {
860 result.push(val)
861 }
862 })
863 }
864 return result
865}
866
867
868
869/**
870 * 从左至右遍历,匹配最近的一条数据
871 *
872 * @param {Object} obj 对象/数组
873 * @param {Function} iterate(item, index, obj) 回调
874 * @param {Object} context 上下文
875 * @return {Object}
876 */
877var find = helperCreateIterateHandle('find', 1, 3, true)
878
879
880
881/**
882 * 从右至左遍历,匹配最近的一条数据
883 *
884 * @param {Object} obj 对象/数组
885 * @param {Function} iterate(item, index, obj) 回调
886 * @param {Object} context 上下文
887 * @return {Object}
888 */
889function findLast (obj, iterate, context) {
890 if (obj) {
891 if (!isArray(obj)) {
892 obj = values(obj)
893 }
894 for (var len = obj.length - 1; len >= 0; len--) {
895 if (iterate.call(context, obj[len], len, obj)) {
896 return obj[len]
897 }
898 }
899 }
900}
901
902
903
904/**
905 * 查找匹配第一条数据的键
906 *
907 * @param {Object} obj 对象/数组
908 * @param {Function} iterate(item, index, obj) 回调
909 * @param {Object} context 上下文
910 * @return {Object}
911 */
912var findKey = helperCreateIterateHandle('', 0, 2, true)
913
914
915
916/**
917 * 判断对象是否包含该值,成功返回true否则false
918 *
919 * @param {Object} obj 对象
920 * @param {Object} val 值
921 * @return {Boolean}
922 */
923function includes (obj, val) {
924 if (obj) {
925 if (obj.includes) {
926 return obj.includes(val)
927 }
928 for (var key in obj) {
929 if (hasOwnProp(obj, key)) {
930 if (val === obj[key]) {
931 return true
932 }
933 }
934 }
935 }
936 return false
937}
938
939
940function arrayIndexOf (list, val) {
941 if (list.indexOf) {
942 return list.indexOf(val)
943 }
944 for (var index = 0, len = list.length; index < len; index++) {
945 if (val === list[index]) {
946 return index
947 }
948 }
949}
950
951
952function arrayLastIndexOf (list, val) {
953 if (list.lastIndexOf) {
954 return list.lastIndexOf(val)
955 }
956 for (var len = list.length - 1; len >= 0; len--) {
957 if (val === list[len]) {
958 return len
959 }
960 }
961 return -1
962}
963
964
965
966/**
967 * 指定方法后的返回值组成的新数组
968 *
969 * @param {Object} obj 对象/数组
970 * @param {Function} iterate(item, index, obj) 回调
971 * @param {Object} context 上下文
972 * @return {Array}
973 */
974function map (obj, iterate, context) {
975 var result = []
976 if (obj && arguments.length > 1) {
977 if (obj.map) {
978 return obj.map(iterate, context)
979 } else {
980 each(obj, function () {
981 result.push(iterate.apply(context, arguments))
982 })
983 }
984 }
985 return result
986}
987
988
989
990/**
991 * 接收一个函数作为累加器,数组中的每个值(从左到右)开始合并,最终为一个值。
992 *
993 * @param {Array} array 数组
994 * @param {Function} callback 方法
995 * @param {Object} initialValue 初始值
996 * @return {Number}
997 */
998function reduce (array, callback, initialValue) {
999 if (array) {
1000 var len, reduceMethod
1001 var index = 0
1002 var context = null
1003 var previous = initialValue
1004 var isInitialVal = arguments.length > 2
1005 var keyList = keys(array)
1006 if (array.length && array.reduce) {
1007 reduceMethod = function () {
1008 return callback.apply(context, arguments)
1009 }
1010 if (isInitialVal) {
1011 return array.reduce(reduceMethod, previous)
1012 }
1013 return array.reduce(reduceMethod)
1014 }
1015 if (isInitialVal) {
1016 index = 1
1017 previous = array[keyList[0]]
1018 }
1019 for (len = keyList.length; index < len; index++) {
1020 previous = callback.call(context, previous, array[keyList[index]], index, array)
1021 }
1022 return previous
1023 }
1024}
1025
1026
1027
1028/**
1029 * 浅复制数组的一部分到同一数组中的另一个位置,数组大小不变
1030 *
1031 * @param {Array} array 数组
1032 * @param {Number} target 从该位置开始替换数据
1033 * @param {Number} start 从该位置开始读取数据,默认为 0 。如果为负值,表示倒数
1034 * @param {Number} end 到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数
1035 * @return {Array}
1036 */
1037function copyWithin (array, target, start, end) {
1038 if (isArray(array) && array.copyWithin) {
1039 return array.copyWithin(target, start, end)
1040 }
1041 var replaceIndex, replaceArray
1042 var targetIndex = target >> 0
1043 var startIndex = start >> 0
1044 var len = array.length
1045 var endIndex = arguments.length > 3 ? end >> 0 : len
1046 if (targetIndex < len) {
1047 targetIndex = targetIndex >= 0 ? targetIndex : len + targetIndex
1048 if (targetIndex >= 0) {
1049 startIndex = startIndex >= 0 ? startIndex : len + startIndex
1050 endIndex = endIndex >= 0 ? endIndex : len + endIndex
1051 if (startIndex < endIndex) {
1052 for (replaceIndex = 0, replaceArray = array.slice(startIndex, endIndex); targetIndex < len; targetIndex++) {
1053 if (replaceArray.length <= replaceIndex) {
1054 break
1055 }
1056 array[targetIndex] = replaceArray[replaceIndex++]
1057 }
1058 }
1059 }
1060 }
1061 return array
1062}
1063
1064
1065
1066/**
1067 * 将一个数组分割成大小的组。如果数组不能被平均分配,那么最后一块将是剩下的元素
1068 *
1069 * @param {Array} array 数组
1070 * @param {Number} size 每组大小
1071 * @return {Array}
1072 */
1073function chunk (array, size) {
1074 var index
1075 var result = []
1076 var arrLen = size >> 0 || 1
1077 if (isArray(array)) {
1078 if (arrLen >= 0 && array.length > arrLen) {
1079 index = 0
1080 while (index < array.length) {
1081 result.push(array.slice(index, index + arrLen))
1082 index += arrLen
1083 }
1084 } else {
1085 result = array.length ? [array] : array
1086 }
1087 }
1088 return result
1089}
1090
1091
1092
1093/**
1094 * 将每个数组中相应位置的值合并在一起
1095 *
1096 * @param {Array*} array 数组
1097 */
1098function zip () {
1099 return unzip(arguments)
1100}
1101
1102
1103
1104
1105/**
1106 * 与 zip 相反
1107 *
1108 * @param {Array} arrays 数组集合
1109 */
1110function unzip (arrays) {
1111 var index, maxItem, len
1112 var result = []
1113 if (arrays && arrays.length) {
1114 index = 0
1115 maxItem = max(arrays, function (item) {
1116 return item ? item.length : 0
1117 })
1118 for (len = maxItem ? maxItem.length : 0; index < len; index++) {
1119 result.push(pluck(arrays, index))
1120 }
1121 }
1122 return result
1123}
1124
1125
1126
1127/**
1128 * 根据键数组、值数组对转换为对象
1129 *
1130 * @param {Array} props 键数组
1131 * @param {Number} arr 值数组
1132 * @return {Object}
1133 */
1134function zipObject (props, arr) {
1135 var result = {}
1136 arr = arr || []
1137 each(values(props), function (val, key) {
1138 result[val] = arr[key]
1139 })
1140 return result
1141}
1142
1143
1144
1145function flattenDeep (array, deep) {
1146 var result = []
1147 arrayEach(array, function (vals) {
1148 result = result.concat(isArray(vals) ? (deep ? flattenDeep(vals, deep) : vals) : [vals])
1149 })
1150 return result
1151}
1152
1153/**
1154 * 将一个多维数组铺平
1155 * @param {Array} array 数组
1156 * @param {Boolean} deep 是否深层
1157 * @return {Array}
1158 */
1159function flatten (array, deep) {
1160 if (isArray(array)) {
1161 return flattenDeep(array, deep)
1162 }
1163 return []
1164}
1165
1166
1167
1168/**
1169 * 将对象或者伪数组转为新数组
1170 *
1171 * @param {Array} list 数组
1172 * @return {Array}
1173 */
1174function toArray (list) {
1175 return map(list, function (item) {
1176 return item
1177 })
1178}
1179
1180
1181
1182/**
1183 * 判断数组是否包含另一数组
1184 *
1185 * @param {Array} array1 数组
1186 * @param {Array} array2 被包含数组
1187 * @return {Boolean}
1188 */
1189function includeArrays (array1, array2) {
1190 var len
1191 var index = 0
1192 if (isArray(array1) && isArray(array2)) {
1193 for (len = array2.length; index < len; index++) {
1194 if (!includes(array1, array2[index])) {
1195 return false
1196 }
1197 }
1198 return true
1199 }
1200 return includes(array1, array2)
1201}
1202
1203
1204
1205/**
1206 * 获取数组对象中某属性值,返回一个数组
1207 *
1208 * @param {Array} array 数组
1209 * @param {String} key 属性值
1210 * @return {Array}
1211 */
1212function pluck (obj, key) {
1213 return map(obj, property(key))
1214}
1215
1216
1217
1218
1219function deepGetObj (obj, path) {
1220 var index = 0
1221 var len = path.length
1222 while (obj && index < len) {
1223 obj = obj[path[index++]]
1224 }
1225 return len && obj ? obj : 0
1226}
1227
1228/**
1229 * 在list的每个元素上执行方法,任何传递的额外参数都会在调用方法的时候传递给它
1230 *
1231 * @param {Array} list
1232 * @param {Array/String/Function} path
1233 * @param {...Object} arguments
1234 * @return {Array}
1235 */
1236function invoke (list, path) {
1237 var func
1238 var args = arguments
1239 var params = []
1240 var paths = []
1241 var index = 2
1242 var len = args.length
1243 for (; index < len; index++) {
1244 params.push(args[index])
1245 }
1246 if (isArray(path)) {
1247 len = path.length - 1
1248 for (index = 0; index < len; index++) {
1249 paths.push(path[index])
1250 }
1251 path = path[len]
1252 }
1253 return map(list, function (context) {
1254 if (paths.length) {
1255 context = deepGetObj(context, paths)
1256 }
1257 func = context[path] || path
1258 if (func && func.apply) {
1259 return func.apply(context, params)
1260 }
1261 })
1262}
1263
1264
1265function arrayEach (list, iterate, context) {
1266 if (list) {
1267 if (list.forEach) {
1268 list.forEach(iterate, context)
1269 } else {
1270 for (var index = 0, len = list.length; index < len; index++) {
1271 iterate.call(context, list[index], index, list)
1272 }
1273 }
1274 }
1275}
1276
1277
1278function lastArrayEach (obj, iterate, context) {
1279 for (var len = obj.length - 1; len >= 0; len--) {
1280 iterate.call(context, obj[len], len, obj)
1281 }
1282}
1283
1284
1285
1286
1287
1288
1289function strictTree (array, optChildren) {
1290 each(array, function (item) {
1291 if (item.children && !item.children.length) {
1292 remove(item, optChildren)
1293 }
1294 })
1295}
1296
1297/**
1298 * 将一个带层级的数据列表转成树结构
1299 *
1300 * @param {Array} array 数组
1301 * @param {Object} options {strict: false, parentKey: 'parentId', key: 'id', children: 'children', mapChildren: 'children', data: 'data'}
1302 * @return {Array}
1303 */
1304function toArrayTree (array, options) {
1305 var opts = assign({}, setupDefaults.treeOptions, options)
1306 var optStrict = opts.strict
1307 var optKey = opts.key
1308 var optParentKey = opts.parentKey
1309 var optChildren = opts.children
1310 var optMapChildren = opts.mapChildren
1311 var optSortKey = opts.sortKey
1312 var optReverse = opts.reverse
1313 var optData = opts.data
1314 var result = []
1315 var treeMap = {}
1316 var idList, id, treeData, parentId
1317
1318 if (optSortKey) {
1319 array = orderBy(clone(array), optSortKey)
1320 if (optReverse) {
1321 array = array.reverse()
1322 }
1323 }
1324
1325 idList = map(array, function (item) {
1326 return item[optKey]
1327 })
1328
1329 each(array, function (item) {
1330 id = item[optKey]
1331
1332 if (optData) {
1333 treeData = {}
1334 treeData[optData] = item
1335 } else {
1336 treeData = item
1337 }
1338
1339 parentId = item[optParentKey]
1340 treeMap[id] = treeMap[id] || []
1341 treeMap[parentId] = treeMap[parentId] || []
1342 treeMap[parentId].push(treeData)
1343 treeData[optKey] = id
1344 treeData[optParentKey] = parentId
1345 treeData[optChildren] = treeMap[id]
1346 if (optMapChildren) {
1347 treeData[optMapChildren] = treeMap[id]
1348 }
1349
1350 if (!optStrict || (optStrict && !parentId)) {
1351 if (!includes(idList, parentId)) {
1352 result.push(treeData)
1353 }
1354 }
1355 })
1356
1357 if (optStrict) {
1358 strictTree(array, optChildren)
1359 }
1360
1361 return result
1362}
1363
1364
1365
1366
1367
1368function unTreeList (result, array, opts) {
1369 var optChildren = opts.children
1370 var optData = opts.data
1371 var optClear = opts.clear
1372 each(array, function (item) {
1373 var children = item[optChildren]
1374 if (optData) {
1375 item = item[optData]
1376 }
1377 result.push(item)
1378 if (children && children.length) {
1379 unTreeList(result, children, opts)
1380 }
1381 if (optClear) {
1382 delete item[optChildren]
1383 }
1384 })
1385 return result
1386}
1387
1388/**
1389 * 将一个树结构转成数组列表
1390 *
1391 * @param {Array} array 数组
1392 * @param {Object} options { children: 'children', data: 'data', clear: false }
1393 * @return {Array}
1394 */
1395function toTreeArray (array, options) {
1396 return unTreeList([], array, assign({}, setupDefaults.treeOptions, options))
1397}
1398
1399
1400
1401function findTreeItem (parent, obj, iterate, context, path, node, parseChildren, opts) {
1402 if (obj) {
1403 var item, index, len, paths, nodes, match
1404 for (index = 0, len = obj.length; index < len; index++) {
1405 item = obj[index]
1406 paths = path.concat(['' + index])
1407 nodes = node.concat([item])
1408 if (iterate.call(context, item, index, obj, paths, parent, nodes)) {
1409 return { index: index, item: item, path: paths, items: obj, parent: parent, nodes: nodes }
1410 }
1411 if (parseChildren && item) {
1412 match = findTreeItem(item, item[parseChildren], iterate, context, paths.concat([parseChildren]), nodes, parseChildren, opts)
1413 if (match) {
1414 return match
1415 }
1416 }
1417 }
1418 }
1419}
1420
1421/**
1422 * 从树结构中查找匹配第一条数据的键、值、路径
1423 *
1424 * @param {Object} obj 对象/数组
1425 * @param {Function} iterate(item, index, items, path, parent, nodes) 回调
1426 * @param {Object} options {children: 'children'}
1427 * @param {Object} context 上下文
1428 * @return {Object} { item, index, items, path, parent, nodes }
1429 */
1430var findTree = helperCreateTreeFunc(findTreeItem)
1431
1432
1433
1434function eachTreeItem (parent, obj, iterate, context, path, node, parseChildren, opts) {
1435 var paths, nodes
1436 each(obj, function (item, index) {
1437 paths = path.concat(['' + index])
1438 nodes = node.concat([item])
1439 iterate.call(context, item, index, obj, paths, parent, nodes)
1440 if (item && parseChildren) {
1441 paths.push(parseChildren)
1442 eachTreeItem(item, item[parseChildren], iterate, context, paths, nodes, parseChildren, opts)
1443 }
1444 })
1445}
1446
1447/**
1448 * 从树结构中遍历数据的键、值、路径
1449 *
1450 * @param {Object} obj 对象/数组
1451 * @param {Function} iterate(item, index, items, path, parent, nodes) 回调
1452 * @param {Object} options {children: 'children', mapChildren: 'children}
1453 * @param {Object} context 上下文
1454 */
1455var eachTree = helperCreateTreeFunc(eachTreeItem)
1456
1457
1458
1459
1460function mapTreeItem (parent, obj, iterate, context, path, node, parseChildren, opts) {
1461 var paths, nodes, rest
1462 var mapChildren = opts.mapChildren || parseChildren
1463 return map(obj, function (item, index) {
1464 paths = path.concat(['' + index])
1465 nodes = node.concat([item])
1466 rest = iterate.call(context, item, index, obj, paths, parent, nodes)
1467 if (rest && item && parseChildren && item[parseChildren]) {
1468 rest[mapChildren] = mapTreeItem(item, item[parseChildren], iterate, context, paths, nodes, parseChildren, opts)
1469 }
1470 return rest
1471 })
1472}
1473
1474/**
1475 * 从树结构中指定方法后的返回值组成的新数组
1476 *
1477 * @param {Object} obj 对象/数组
1478 * @param {Function} iterate(item, index, items, path, parent, nodes) 回调
1479 * @param {Object} options {children: 'children'}
1480 * @param {Object} context 上下文
1481 * @return {Object/Array}
1482 */
1483var mapTree = helperCreateTreeFunc(mapTreeItem)
1484
1485
1486
1487/**
1488 * 从树结构中根据回调过滤数据
1489 *
1490 * @param {Object} obj 对象/数组
1491 * @param {Function} iterate(item, index, items, path, parent) 回调
1492 * @param {Object} options {children: 'children'}
1493 * @param {Object} context 上下文
1494 * @return {Array}
1495 */
1496function filterTree (obj, iterate, options, context) {
1497 var result = []
1498 if (obj && iterate) {
1499 eachTree(obj, function (item, index, items, path, parent, nodes) {
1500 if (iterate.call(context, item, index, items, path, parent, nodes)) {
1501 result.push(item)
1502 }
1503 }, options)
1504 }
1505 return result
1506}
1507
1508
1509
1510
1511
1512function searchTreeItem (parentAllow, parent, obj, iterate, context, path, node, parseChildren, opts) {
1513 var paths, nodes, rest, isAllow, hasChild
1514 var rests = []
1515 var hasOriginal = opts.original
1516 var sourceData = opts.data
1517 var mapChildren = opts.mapChildren || parseChildren
1518 arrayEach(obj, function (item, index) {
1519 paths = path.concat(['' + index])
1520 nodes = node.concat([item])
1521 isAllow = parentAllow || iterate.call(context, item, index, obj, paths, parent, nodes)
1522 hasChild = parseChildren && item[parseChildren]
1523 if (isAllow || hasChild) {
1524 if (hasOriginal) {
1525 rest = item
1526 } else {
1527 rest = assign({}, item)
1528 if (sourceData) {
1529 rest[sourceData] = item
1530 }
1531 }
1532 rest[mapChildren] = searchTreeItem(isAllow, item, item[parseChildren], iterate, context, paths, nodes, parseChildren, opts)
1533 if (isAllow || rest[mapChildren].length) {
1534 rests.push(rest)
1535 }
1536 } else if (isAllow) {
1537 rests.push(rest)
1538 }
1539 })
1540 return rests
1541}
1542
1543/**
1544 * 从树结构中根据回调查找数据
1545 *
1546 * @param {Object} obj 对象/数组
1547 * @param {Function} iterate(item, index, items, path, parent, nodes) 回调
1548 * @param {Object} options {children: 'children'}
1549 * @param {Object} context 上下文
1550 * @return {Array}
1551 */
1552var searchTree = helperCreateTreeFunc(function (parent, obj, iterate, context, path, nodes, parseChildren, opts) {
1553 return searchTreeItem(0, parent, obj, iterate, context, path, nodes, parseChildren, opts)
1554})
1555
1556
1557/**
1558 * 判断对象自身属性中是否具有指定的属性
1559 *
1560 * @param {Object} obj 对象
1561 * @param {String/Number} key 键值
1562 * @return {Boolean}
1563 */
1564function hasOwnProp (obj, key) {
1565 return obj && obj.hasOwnProperty ? obj.hasOwnProperty(key) : false
1566}
1567
1568
1569
1570/**
1571 * 判断是否 undefined 和 null
1572 * @param {Object} obj 对象
1573 * @return {Boolean}
1574 */
1575function eqNull (obj) {
1576 return isNull(obj) || isUndefined(obj)
1577}
1578
1579
1580
1581/* eslint-disable eqeqeq */
1582function isNumberNaN (obj) {
1583 return isNumber(obj) && isNaN(obj)
1584}
1585
1586
1587
1588function isNumberFinite (obj) {
1589 return isNumber(obj) && isFinite(obj)
1590}
1591
1592
1593
1594
1595/**
1596 * 判断是否Undefined
1597 *
1598 * @param {Object} obj 对象
1599 * @return {Boolean}
1600 */
1601var isUndefined = helperCreateInTypeof(staticStrUndefined)
1602
1603
1604
1605/**
1606 * 判断是否数组
1607 *
1608 * @param {Object} obj 对象
1609 * @return {Boolean}
1610 */
1611var isArray = Array.isArray || helperCreateInInObjectString('Array')
1612
1613
1614
1615/**
1616 * 判断是否小数
1617 *
1618 * @param {Number} obj 数值
1619 * @return {Boolean}
1620 */
1621function isFloat (obj) {
1622 return !isNull(obj) && !isNaN(obj) && !isArray(obj) && !isInteger(obj)
1623}
1624
1625
1626
1627/**
1628 * 判断是否整数
1629 *
1630 * @param {Number, String} number 数值
1631 * @return {Boolean}
1632 */
1633var isInteger = function (obj) {
1634 return !isNull(obj) && !isNaN(obj) && !isArray(obj) && obj % 1 === 0
1635}
1636
1637
1638
1639/**
1640 * 判断是否方法
1641 *
1642 * @param {Object} obj 对象
1643 * @return {Boolean}
1644 */
1645var isFunction = helperCreateInTypeof('function')
1646
1647
1648
1649/**
1650 * 判断是否Boolean对象
1651 *
1652 * @param {Object} obj 对象
1653 * @return {Boolean}
1654 */
1655var isBoolean = helperCreateInTypeof('boolean')
1656
1657
1658
1659/**
1660 * 判断是否String对象
1661 *
1662 * @param {Object} obj 对象
1663 * @return {Boolean}
1664 */
1665var isString = helperCreateInTypeof('string')
1666
1667
1668
1669/**
1670 * 判断是否Number对象
1671 *
1672 * @param {Object} obj 对象
1673 * @return {Boolean}
1674 */
1675var isNumber = helperCreateInTypeof('number')
1676
1677
1678
1679/**
1680 * 判断是否RegExp对象
1681 *
1682 * @param {Object} obj 对象
1683 * @return {Boolean}
1684 */
1685var isRegExp = helperCreateInInObjectString('RegExp')
1686
1687
1688
1689/**
1690 * 判断是否Object对象
1691 *
1692 * @param {Object} obj 对象
1693 * @return {Boolean}
1694 */
1695var isObject = helperCreateInTypeof('object')
1696
1697
1698/**
1699 * 判断是否对象
1700 *
1701 * @param {Object} obj 对象
1702 * @return {Boolean}
1703 */
1704function isPlainObject (obj) {
1705 return obj ? obj.constructor === Object : false
1706}
1707
1708
1709
1710/**
1711 * 判断是否Date对象
1712 *
1713 * @param {Object} obj 对象
1714 * @return {Boolean}
1715 */
1716var isDate = helperCreateInInObjectString('Date')
1717
1718
1719
1720/**
1721 * 判断是否Error对象
1722 *
1723 * @param {Object} obj 对象
1724 * @return {Boolean}
1725 */
1726var isError = helperCreateInInObjectString('Error')
1727
1728
1729/**
1730 * 判断是否TypeError对象
1731 *
1732 * @param {Object} obj 对象
1733 * @return {Boolean}
1734 */
1735function isTypeError (obj) {
1736 return obj ? obj.constructor === TypeError : false
1737}
1738
1739
1740/**
1741 * 判断是否为空对象
1742 *
1743 * @param {Object} obj 对象
1744 * @return {Boolean}
1745 */
1746function isEmpty (obj) {
1747 for (var key in obj) {
1748 return false
1749 }
1750 return true
1751}
1752
1753
1754/**
1755 * 判断是否为Null
1756 *
1757 * @param {Object} obj 对象
1758 * @return {Boolean}
1759 */
1760function isNull (obj) {
1761 return obj === null
1762}
1763
1764
1765/* eslint-disable valid-typeof */
1766
1767/**
1768 * 判断是否Symbol对象
1769 *
1770 * @param {Object} obj 对象
1771 * @return {Boolean}
1772 */
1773var supportSymbol = typeof Symbol !== staticStrUndefined
1774function isSymbol (obj) {
1775 return supportSymbol && Symbol.isSymbol ? Symbol.isSymbol(obj) : (typeof obj === 'symbol')
1776}
1777
1778
1779
1780/**
1781 * 判断是否Arguments对象
1782 *
1783 * @param {Object} obj 对象
1784 * @return {Boolean}
1785 */
1786var isArguments = helperCreateInInObjectString('Arguments')
1787
1788
1789
1790/**
1791 * 判断是否Element对象
1792 *
1793 * @param {Object} obj 对象
1794 * @return {Boolean}
1795 */
1796function isElement (obj) {
1797 return !!(obj && isString(obj.nodeName) && isNumber(obj.nodeType))
1798}
1799
1800
1801
1802/**
1803 * 判断是否Document对象
1804 *
1805 * @param {Object} obj 对象
1806 * @return {Boolean}
1807 */
1808function isDocument (obj) {
1809 return !!(obj && staticDocument && obj.nodeType === 9)
1810}
1811
1812
1813
1814/**
1815 * 判断是否Window对象
1816 *
1817 * @param {Object} obj 对象
1818 * @return {Boolean}
1819 */
1820function isWindow (obj) {
1821 return staticWindow && !!(obj && obj === obj.window)
1822}
1823
1824
1825/* eslint-disable valid-typeof */
1826
1827/**
1828 * 判断是否FormData对象
1829 *
1830 * @param {Object} obj 对象
1831 * @return {Boolean}
1832 */
1833var supportFormData = typeof FormData !== staticStrUndefined
1834function isFormData (obj) {
1835 return supportFormData && obj instanceof FormData
1836}
1837
1838
1839/* eslint-disable valid-typeof */
1840
1841/**
1842 * 判断是否Map对象
1843 *
1844 * @param {Object} obj 对象
1845 * @return {Boolean}
1846 */
1847var supportMap = typeof Map !== staticStrUndefined
1848function isMap (obj) {
1849 return supportMap && obj instanceof Map
1850}
1851
1852
1853/* eslint-disable valid-typeof */
1854
1855/**
1856 * 判断是否WeakMap对象
1857 *
1858 * @param {Object} obj 对象
1859 * @return {Boolean}
1860 */
1861var supportWeakMap = typeof WeakMap !== staticStrUndefined
1862function isWeakMap (obj) {
1863 return supportWeakMap && obj instanceof WeakMap
1864}
1865
1866
1867/* eslint-disable valid-typeof */
1868
1869/**
1870 * 判断是否Set对象
1871 *
1872 * @param {Object} obj 对象
1873 * @return {Boolean}
1874 */
1875var supportSet = typeof Set !== staticStrUndefined
1876function isSet (obj) {
1877 return supportSet && obj instanceof Set
1878}
1879
1880
1881/* eslint-disable valid-typeof */
1882
1883/**
1884 * 判断是否WeakSet对象
1885 *
1886 * @param {Object} obj 对象
1887 * @return {Boolean}
1888 */
1889var supportWeakSet = typeof WeakSet !== staticStrUndefined
1890function isWeakSet (obj) {
1891 return supportWeakSet && obj instanceof WeakSet
1892}
1893
1894
1895
1896
1897/**
1898 * 判断是否闰年
1899 *
1900 * @param {Date} date 日期或数字
1901 * @return {Boolean}
1902 */
1903function isLeapYear (date) {
1904 var year
1905 var currentDate = date ? toStringDate(date) : helperNewDate()
1906 if (isDate(currentDate)) {
1907 year = currentDate.getFullYear()
1908 return (year % 4 === 0) && (year % 100 !== 0 || year % 400 === 0)
1909 }
1910 return false
1911}
1912
1913
1914
1915
1916/**
1917 * 判断属性中的键和值是否包含在对象中
1918 *
1919 * @param {Object/Array} obj 对象
1920 * @param {Object} source 值
1921 * @return {Boolean}
1922 */
1923function isMatch (obj, source) {
1924 var objKeys = keys(obj)
1925 var sourceKeys = keys(source)
1926 if (sourceKeys.length) {
1927 if (includeArrays(objKeys, sourceKeys)) {
1928 return some(sourceKeys, function (key2) {
1929 return findIndexOf(objKeys, function (key1) {
1930 return key1 === key2 && isEqual(obj[key1], source[key2])
1931 }) > -1
1932 })
1933 }
1934 } else {
1935 return true
1936 }
1937 return isEqual(obj, source)
1938}
1939
1940
1941
1942/**
1943 * 深度比较两个对象之间的值是否相等
1944 *
1945 * @param {Object} obj1 值1
1946 * @param {Object} obj2 值2
1947 * @return {Boolean}
1948 */
1949function isEqual (obj1, obj2) {
1950 return helperEqualCompare(obj1, obj2, helperDefaultCompare)
1951}
1952
1953
1954
1955
1956/**
1957 * 深度比较两个对象之间的值是否相等,使用自定义比较函数
1958 *
1959 * @param {Object} obj1 值1
1960 * @param {Object} obj2 值2
1961 * @param {Function} func 自定义函数
1962 * @return {Boolean}
1963 */
1964function isEqualWith (obj1, obj2, func) {
1965 if (isFunction(func)) {
1966 return helperEqualCompare(obj1, obj2, function (v1, v2, key, obj1, obj2) {
1967 var result = func(v1, v2, key, obj1, obj2)
1968 return isUndefined(result) ? helperDefaultCompare(v1, v2) : !!result
1969 }, func)
1970 }
1971 return helperEqualCompare(obj1, obj2, helperDefaultCompare)
1972}
1973
1974
1975
1976/**
1977 * 获取对象类型
1978 *
1979 * @param {Object} obj 对象
1980 * @return {String}
1981 */
1982function getType (obj) {
1983 if (isNull(obj)) {
1984 return 'null'
1985 }
1986 if (isSymbol(obj)) {
1987 return 'symbol'
1988 }
1989 if (isDate(obj)) {
1990 return 'date'
1991 }
1992 if (isArray(obj)) {
1993 return 'array'
1994 }
1995 if (isRegExp(obj)) {
1996 return 'regexp'
1997 }
1998 if (isError(obj)) {
1999 return 'error'
2000 }
2001 return typeof obj
2002}
2003
2004
2005/**
2006 * 获取一个全局唯一标识
2007 *
2008 * @param {String} prefix 前缀
2009 * @return {Number}
2010 */
2011var __uniqueId = 0
2012function uniqueId (prefix) {
2013 return [prefix, ++__uniqueId].join('')
2014}
2015
2016
2017
2018/**
2019 * 返回对象的长度
2020 *
2021 * @param {Object} obj 对象
2022 * @return {Number}
2023 */
2024function getSize (obj) {
2025 var len = 0
2026 if (isString(obj) || isArray(obj)) {
2027 return obj.length
2028 }
2029 each(obj, function () {
2030 len++
2031 })
2032 return len
2033}
2034
2035
2036
2037
2038/**
2039 * 返回对象第一个索引值
2040 *
2041 * @param {Object} obj 对象
2042 * @param {Object} val 值
2043 * @return {Number}
2044 */
2045var indexOf = helperCreateIndexOf('indexOf', arrayIndexOf)
2046
2047
2048
2049
2050/**
2051 * 从最后开始的索引值,返回对象第一个索引值
2052 *
2053 * @param {Object} array 对象
2054 * @param {Object} val 值
2055 * @return {Number}
2056 */
2057var lastIndexOf = helperCreateIndexOf('lastIndexOf', arrayLastIndexOf)
2058
2059
2060
2061/**
2062 * 返回对象第一个索引值
2063 *
2064 * @param {Object} obj 对象/数组
2065 * @param {Function} iterate(item, index, obj) 回调
2066 * @param {Object} context 上下文
2067 * @return {Object}
2068 */
2069var findIndexOf = helperCreateiterateIndexOf(function (obj, iterate, context) {
2070 for (var index = 0, len = obj.length; index < len; index++) {
2071 if (iterate.call(context, obj[index], index, obj)) {
2072 return index
2073 }
2074 }
2075 return -1
2076})
2077
2078
2079
2080/**
2081 * 从最后开始的索引值,返回对象第一个索引值
2082 *
2083 * @param {Object} obj 对象/数组
2084 * @param {Function} iterate(item, index, obj) 回调
2085 * @param {Object} context 上下文
2086 * @return {Object}
2087 */
2088var findLastIndexOf = helperCreateiterateIndexOf(function (obj, iterate, context) {
2089 for (var len = obj.length - 1; len >= 0; len--) {
2090 if (iterate.call(context, obj[len], len, obj)) {
2091 return len
2092 }
2093 }
2094 return -1
2095})
2096
2097
2098
2099/**
2100 * 字符串转JSON
2101 *
2102 * @param {String} str 字符串
2103 * @return {Object} 返回转换后对象
2104 */
2105function toStringJSON (str) {
2106 if (isPlainObject(str)) {
2107 return str
2108 } else if (isString(str)) {
2109 try {
2110 return JSON.parse(str)
2111 } catch (e) {}
2112 }
2113 return {}
2114}
2115
2116
2117
2118/**
2119 * JSON转字符串
2120 *
2121 * @param {Object} obj 对象
2122 * @return {String} 返回字符串
2123 */
2124function toJSONString (obj) {
2125 return eqNull(obj) ? '' : JSON.stringify(obj)
2126}
2127
2128
2129
2130/**
2131 * 获取对象所有属性
2132 *
2133 * @param {Object} obj 对象/数组
2134 * @return {Array}
2135 */
2136var keys = helperCreateGetObjects('keys', 1)
2137
2138
2139
2140/**
2141 * 获取对象所有值
2142 *
2143 * @param {Object} obj 对象/数组
2144 * @return {Array}
2145 */
2146var values = helperCreateGetObjects('values', 0)
2147
2148
2149
2150/**
2151 * 获取对象所有属性、值
2152 *
2153 * @param {Object} obj 对象/数组
2154 * @return {Array}
2155 */
2156var entries = helperCreateGetObjects('entries', 2)
2157
2158
2159
2160/**
2161 * 根据 key 过滤指定的属性值,返回一个新的对象
2162 *
2163 * @param {Object} obj 对象
2164 * @param {String/Array} key 键数组
2165 * @return {Object}
2166 */
2167var pick = helperCreatePickOmit(1, 0)
2168
2169
2170
2171/**
2172 * 根据 key 排除指定的属性值,返回一个新的对象
2173 *
2174 * @param {Object} obj 对象
2175 * @param {String/Array} key 键数组
2176 * @return {Object}
2177 */
2178var omit = helperCreatePickOmit(0, 1)
2179
2180
2181
2182/**
2183 * 获取对象第一个值
2184 *
2185 * @param {Object} obj 对象/数组
2186 * @return {Object}
2187 */
2188function first (obj) {
2189 return values(obj)[0]
2190}
2191
2192
2193
2194/**
2195 * 获取对象最后一个值
2196 *
2197 * @param {Object} obj 对象/数组
2198 * @return {Object}
2199 */
2200function last (obj) {
2201 var list = values(obj)
2202 return list[list.length - 1]
2203}
2204
2205
2206
2207/**
2208 * 迭代器
2209 *
2210 * @param {Object} obj 对象/数组
2211 * @param {Function} iterate(item, index, obj) 回调
2212 * @param {Object} context 上下文
2213 * @return {Object}
2214 */
2215function each (obj, iterate, context) {
2216 if (obj) {
2217 return (isArray(obj) ? arrayEach : objectEach)(obj, iterate, context)
2218 }
2219 return obj
2220}
2221
2222
2223
2224/**
2225 * 已废弃,被 some, every 替换
2226 * @deprecated
2227 */
2228function forOf (obj, iterate, context) {
2229 if (obj) {
2230 if (isArray(obj)) {
2231 for (var index = 0, len = obj.length; index < len; index++) {
2232 if (iterate.call(context, obj[index], index, obj) === false) {
2233 break
2234 }
2235 }
2236 } else {
2237 for (var key in obj) {
2238 if (hasOwnProp(obj, key)) {
2239 if (iterate.call(context, obj[key], key, obj) === false) {
2240 break
2241 }
2242 }
2243 }
2244 }
2245 }
2246}
2247
2248
2249
2250/**
2251 * 已废弃
2252 * @deprecated
2253 */
2254function lastForOf (obj, iterate, context) {
2255 if (obj) {
2256 var len, list
2257 if (isArray(obj)) {
2258 for (len = obj.length - 1; len >= 0; len--) {
2259 if (iterate.call(context, obj[len], len, obj) === false) {
2260 break
2261 }
2262 }
2263 } else {
2264 list = keys(obj)
2265 for (len = list.length - 1; len >= 0; len--) {
2266 if (iterate.call(context, obj[list[len]], list[len], obj) === false) {
2267 break
2268 }
2269 }
2270 }
2271 }
2272}
2273
2274
2275
2276/**
2277 * 迭代器,从最后开始迭代
2278 *
2279 * @param {Object} obj 对象/数组
2280 * @param {Function} iterate(item, index, obj) 回调
2281 * @param {Object} context 上下文
2282 * @return {Object}
2283 */
2284function lastEach (obj, iterate, context) {
2285 if (obj) {
2286 return (isArray(obj) ? lastArrayEach : lastObjectEach)(obj, iterate, context)
2287 }
2288 return obj
2289}
2290
2291
2292
2293
2294
2295/**
2296 * 检查键、路径是否是该对象的属性
2297 *
2298 * @param {Object/Array} data 对象
2299 * @param {String/Function} property 键、路径
2300 * @return {Boolean}
2301 */
2302function has (obj, property) {
2303 if (obj) {
2304 if (hasOwnProp(obj, property)) {
2305 return true
2306 } else {
2307 var prop, arrIndex, objProp, matchs, rest, isHas
2308 var props = helperGetHGSKeys(property)
2309 var index = 0
2310 var len = props.length
2311 for (rest = obj; index < len; index++) {
2312 isHas = false
2313 prop = props[index]
2314 matchs = prop ? prop.match(staticHGKeyRE) : ''
2315 if (matchs) {
2316 arrIndex = matchs[1]
2317 objProp = matchs[2]
2318 if (arrIndex) {
2319 if (rest[arrIndex]) {
2320 if (hasOwnProp(rest[arrIndex], objProp)) {
2321 isHas = true
2322 rest = rest[arrIndex][objProp]
2323 }
2324 }
2325 } else {
2326 if (hasOwnProp(rest, objProp)) {
2327 isHas = true
2328 rest = rest[objProp]
2329 }
2330 }
2331 } else {
2332 if (hasOwnProp(rest, prop)) {
2333 isHas = true
2334 rest = rest[prop]
2335 }
2336 }
2337 if (isHas) {
2338 if (index === len - 1) {
2339 return true
2340 }
2341 } else {
2342 break
2343 }
2344 }
2345 }
2346 }
2347 return false
2348}
2349
2350
2351
2352
2353/**
2354 * 获取对象的属性的值,如果值为 undefined,则返回默认值
2355 * @param {Object/Array} obj 对象
2356 * @param {String/Function} property 键、路径
2357 * @param {Object} defaultValue 默认值
2358 * @return {Object}
2359 */
2360function get (obj, property, defaultValue) {
2361 if (eqNull(obj)) {
2362 return defaultValue
2363 }
2364 var result = getValueByPath(obj, property)
2365 return isUndefined(result) ? defaultValue : result
2366}
2367
2368function getDeepProps (obj, key) {
2369 var matchs = key ? key.match(staticHGKeyRE) : ''
2370 return matchs ? (matchs[1] ? (obj[matchs[1]] ? obj[matchs[1]][matchs[2]] : undefined) : obj[matchs[2]]) : obj[key]
2371}
2372
2373function getValueByPath (obj, property) {
2374 if (obj) {
2375 var rest, props, len
2376 var index = 0
2377 if (obj[property] || hasOwnProp(obj, property)) {
2378 return obj[property]
2379 } else {
2380 props = helperGetHGSKeys(property)
2381 len = props.length
2382 if (len) {
2383 for (rest = obj; index < len; index++) {
2384 rest = getDeepProps(rest, props[index])
2385 if (eqNull(rest)) {
2386 if (index === len - 1) {
2387 return rest
2388 }
2389 return
2390 }
2391 }
2392 }
2393 return rest
2394 }
2395 }
2396}
2397
2398
2399
2400
2401
2402var sKeyRE = /(.+)?\[(\d+)\]$/
2403
2404function setDeepProps (obj, key, isEnd, nextKey, value) {
2405 if (obj[key]) {
2406 if (isEnd) {
2407 obj[key] = value
2408 }
2409 } else {
2410 var index
2411 var rest
2412 var currMatchs = key ? key.match(sKeyRE) : null
2413 if (isEnd) {
2414 rest = value
2415 } else {
2416 var nextMatchs = nextKey ? nextKey.match(sKeyRE) : null
2417 rest = nextMatchs && !nextMatchs[1] ? new Array(staticParseInt(nextMatchs[2]) + 1) : {}
2418 }
2419 if (currMatchs) {
2420 if (currMatchs[1]) {
2421 // 如果为对象中数组
2422 index = staticParseInt(currMatchs[2])
2423 if (obj[currMatchs[1]]) {
2424 obj[currMatchs[1]][index] = rest
2425 } else {
2426 obj[currMatchs[1]] = new Array(index + 1)
2427 obj[currMatchs[1]][index] = rest
2428 }
2429 } else {
2430 // 如果为数组
2431 obj[currMatchs[2]] = rest
2432 }
2433 } else {
2434 // 如果为对象
2435 obj[key] = rest
2436 }
2437 return rest
2438 }
2439 return obj[key]
2440}
2441
2442/**
2443 * 设置对象属性上的值。如果属性不存在则创建它
2444 * @param {Object/Array} obj 对象
2445 * @param {String/Function} property 键、路径
2446 * @param {Object} value 值
2447 */
2448function set (obj, property, value) {
2449 if (obj) {
2450 if ((obj[property] || hasOwnProp(obj, property)) && !isPrototypePolluted(property)) {
2451 obj[property] = value
2452 } else {
2453 var rest = obj
2454 var props = helperGetHGSKeys(property)
2455 var len = props.length
2456 for (var index = 0; index < len; index++) {
2457 if (isPrototypePolluted(props[index])) {
2458 continue
2459 }
2460 var isEnd = index === len - 1
2461 rest = setDeepProps(rest, props[index], isEnd, isEnd ? null : props[index + 1], value)
2462 }
2463 }
2464 }
2465 return obj
2466}
2467
2468/**
2469 * Blacklist certain keys to prevent Prototype Pollution
2470 * @param {string} key
2471 */
2472function isPrototypePolluted(key) {
2473 return key === '__proto__' || key === 'constructor' || key === 'prototype'
2474}
2475
2476
2477
2478function createiterateEmpty (iterate) {
2479 return function () {
2480 return isEmpty(iterate)
2481 }
2482}
2483
2484/**
2485 * 集合分组,默认使用键值分组,如果有iterate则使用结果进行分组
2486 *
2487 * @param {Array} obj 对象
2488 * @param {Function} iterate 回调/对象属性
2489 * @param {Object} context 上下文
2490 * @return {Object}
2491 */
2492function groupBy (obj, iterate, context) {
2493 var groupKey
2494 var result = {}
2495 if (obj) {
2496 if (iterate && isObject(iterate)) {
2497 iterate = createiterateEmpty(iterate)
2498 } else if (!isFunction(iterate)) {
2499 iterate = property(iterate)
2500 }
2501 each(obj, function (val, key) {
2502 groupKey = iterate ? iterate.call(context, val, key, obj) : val
2503 if (result[groupKey]) {
2504 result[groupKey].push(val)
2505 } else {
2506 result[groupKey] = [val]
2507 }
2508 })
2509 }
2510 return result
2511}
2512
2513
2514
2515
2516/**
2517 * 集合分组统计,返回各组中对象的数量统计
2518 *
2519 * @param {Array} obj 对象
2520 * @param {Function} iterate 回调/对象属性
2521 * @param {Object} context 上下文
2522 * @return {Object}
2523 */
2524function countBy (obj, iterate, context) {
2525 var result = groupBy(obj, iterate, context || this)
2526 objectEach(result, function (item, key) {
2527 result[key] = item.length
2528 })
2529 return result
2530}
2531
2532
2533
2534
2535function getCtorObject (val, args) {
2536 var Ctor = val.__proto__.constructor
2537 return args ? new Ctor(args) : new Ctor()
2538}
2539
2540function handleValueClone (item, isDeep) {
2541 return isDeep ? copyValue(item, isDeep) : item
2542}
2543
2544function copyValue (val, isDeep) {
2545 if (val) {
2546 switch(objectToString.call(val)) {
2547 case "[object Object]":
2548 case "[object Arguments]": {
2549 var restObj = getCtorObject(val)
2550 objectEach(val, function (item, key) {
2551 restObj[key] = handleValueClone(item, isDeep)
2552 })
2553 return restObj
2554 }
2555 case "[object Date]":
2556 case "[object RegExp]": {
2557 return getCtorObject(val, val.valueOf())
2558 }
2559 case "[object Array]": {
2560 var restArr = []
2561 arrayEach(val, function (item) {
2562 restArr.push(handleValueClone(item, isDeep))
2563 })
2564 return restArr
2565 }
2566 case "[object Set]": {
2567 var restSet = getCtorObject(val)
2568 restSet.forEach(function (item) {
2569 restSet.add(handleValueClone(item, isDeep))
2570 })
2571 return restSet
2572 }
2573 case "[object Map]": {
2574 var restMap = getCtorObject(val)
2575 restMap.forEach(function (item, key) {
2576 restMap.set(handleValueClone(item, isDeep))
2577 })
2578 return restMap
2579 }
2580 }
2581 }
2582 return val
2583}
2584
2585/**
2586 * 浅拷贝/深拷贝
2587 *
2588 * @param {Object} obj 对象/数组
2589 * @param {Boolean} deep 是否深拷贝
2590 * @return {Object}
2591 */
2592function clone (obj, deep) {
2593 if (obj) {
2594 return copyValue(obj, deep)
2595 }
2596 return obj
2597}
2598
2599
2600
2601
2602/**
2603 * 清空对象
2604 *
2605 * @param {Object} obj 对象
2606 * @param {*} defs 默认值,如果不传(清空所有属性)、如果传对象(清空并继承)、如果传值(给所有赋值)
2607 * @param {Object/Array} assigns 默认值
2608 * @return {Object}
2609 */
2610function clear (obj, defs, assigns) {
2611 if (obj) {
2612 var len
2613 var isDefs = arguments.length > 1 && (isNull(defs) || !isObject(defs))
2614 var extds = isDefs ? assigns : defs
2615 if (isPlainObject(obj)) {
2616 objectEach(obj, isDefs ? function (val, key) {
2617 obj[key] = defs
2618 } : function (val, key) {
2619 helperDeleteProperty(obj, key)
2620 })
2621 if (extds) {
2622 assign(obj, extds)
2623 }
2624 } else if (isArray(obj)) {
2625 if (isDefs) {
2626 len = obj.length
2627 while (len > 0) {
2628 len--
2629 obj[len] = defs
2630 }
2631 } else {
2632 obj.length = 0
2633 }
2634 if (extds) {
2635 obj.push.apply(obj, extds)
2636 }
2637 }
2638 }
2639 return obj
2640}
2641
2642
2643
2644
2645function pluckProperty (name) {
2646 return function (obj, key) {
2647 return key === name
2648 }
2649}
2650
2651/**
2652 * 移除对象属性
2653 *
2654 * @param {Object/Array} obj 对象/数组
2655 * @param {Function/String} iterate 方法或属性
2656 * @param {Object} context 上下文
2657 * @return {Object/Array}
2658 */
2659function remove (obj, iterate, context) {
2660 if (obj) {
2661 if (!eqNull(iterate)) {
2662 var removeKeys = []
2663 var rest = []
2664 if (!isFunction(iterate)) {
2665 iterate = pluckProperty(iterate)
2666 }
2667 each(obj, function (item, index, rest) {
2668 if (iterate.call(context, item, index, rest)) {
2669 removeKeys.push(index)
2670 }
2671 })
2672 if (isArray(obj)) {
2673 lastEach(removeKeys, function (item, key) {
2674 rest.push(obj[item])
2675 obj.splice(item, 1)
2676 })
2677 } else {
2678 rest = {}
2679 arrayEach(removeKeys, function (key) {
2680 rest[key] = obj[key]
2681 helperDeleteProperty(obj, key)
2682 })
2683 }
2684 return rest
2685 }
2686 return clear(obj)
2687 }
2688 return obj
2689}
2690
2691
2692/**
2693 * 序号列表生成函数
2694 *
2695 * @param {Number} start 起始值
2696 * @param {Number} stop 结束值
2697 * @param {Number} step 自增值
2698 * @return {Object}
2699 */
2700function range (start, stop, step) {
2701 var index, len
2702 var result = []
2703 var args = arguments
2704 if (args.length < 2) {
2705 stop = args[0]
2706 start = 0
2707 }
2708 index = start >> 0
2709 len = stop >> 0
2710 if (index < stop) {
2711 step = step >> 0 || 1
2712 for (; index < len; index += step) {
2713 result.push(index)
2714 }
2715 }
2716 return result
2717}
2718
2719
2720
2721
2722
2723/**
2724 * 将一个或者多个对象值解构到目标对象
2725 *
2726 * @param {Object} destination 目标对象
2727 * @param {...Object}
2728 * @return {Boolean}
2729 */
2730function destructuring (destination, sources) {
2731 if (destination && sources) {
2732 var rest = assign.apply(this, [{}].concat(slice(arguments, 1)))
2733 var restKeys = keys(rest)
2734 arrayEach(keys(destination), function (key) {
2735 if (includes(restKeys, key)) {
2736 destination[key] = rest[key]
2737 }
2738 })
2739 }
2740 return destination
2741}
2742
2743
2744/**
2745 * 获取一个指定范围内随机数
2746 *
2747 * @param {Number} minVal 最小值
2748 * @param {Number} maxVal 最大值
2749 * @return {Number}
2750 */
2751function random (minVal, maxVal) {
2752 return minVal >= maxVal ? minVal : ((minVal = minVal >> 0) + Math.round(Math.random() * ((maxVal || 9) - minVal)))
2753}
2754
2755
2756
2757/**
2758 * 获取最小值
2759 *
2760 * @param {Array} arr 数组
2761 * @param {Function} iterate(item, index, obj) 回调
2762 * @return {Number}
2763 */
2764var min = helperCreateMinMax(function (rest, itemVal) {
2765 return rest > itemVal
2766})
2767
2768
2769
2770/**
2771 * 获取最大值
2772 *
2773 * @param {Array} arr 数组
2774 * @param {Function} iterate(item, index, obj) 回调
2775 * @return {Number}
2776 */
2777var max = helperCreateMinMax(function (rest, itemVal) {
2778 return rest < itemVal
2779})
2780
2781
2782
2783
2784
2785/**
2786 * 千分位分隔符、小数点
2787 *
2788 * @param {String/Number} num 数值
2789 * @param {CommafyOptions} options 参数
2790 * @return {String}
2791 */
2792function commafy(num, options) {
2793 var opts = options || {}
2794 var optDigits = opts.digits
2795 var isNum = isNumber(num)
2796 var rest, result, isNegative, intStr, floatStr
2797 if (isNum) {
2798 rest = (opts.ceil ? ceil : (opts.floor ? floor : round))(num, optDigits)
2799 result = toNumberString(optDigits ? toFixed(rest, optDigits) : rest).split('.')
2800 intStr = result[0]
2801 floatStr = result[1]
2802 isNegative = intStr && rest < 0
2803 if (isNegative) {
2804 intStr = intStr.substring(1, intStr.length)
2805 }
2806 } else {
2807 rest = toValueString(num).replace(/,/g, '')
2808 result = rest ? [rest] : []
2809 intStr = result[0]
2810 }
2811 if (result.length) {
2812 return (isNegative ? '-' : '') + intStr.replace(new RegExp('(?=(?!(\\b))(.{' + (opts.spaceNumber || 3) + '})+$)', 'g'), (opts.separator || ',')) + (floatStr ? ('.' + floatStr) : '')
2813 }
2814 return rest
2815}
2816
2817
2818
2819/**
2820 * 将数值四舍五入
2821 *
2822 * @param {string|number} num 数值
2823 * @param {number} digits 小数保留位数
2824 * @return {number}
2825 */
2826var round = helperCreateMathNumber('round')
2827
2828
2829
2830/**
2831 * 将数值向上舍入
2832 *
2833 * @param {string|number} num 数值
2834 * @param {number} digits 小数保留位数
2835 * @return {number}
2836 */
2837var ceil = helperCreateMathNumber('ceil')
2838
2839
2840
2841/**
2842 * 将数值向下舍入
2843 *
2844 * @param {string|number} num 数值
2845 * @param {number} digits 小数保留位数
2846 * @return {number}
2847 */
2848var floor = helperCreateMathNumber('floor')
2849
2850
2851
2852
2853/**
2854 * 将数值四舍五入并格式化为固定小数位的字符串
2855 *
2856 * @param {string|number} num 数值
2857 * @param {number} digits 小数保留位数
2858 * @return {String}
2859 */
2860function toFixed (num, digits) {
2861 digits = digits >> 0
2862 var str = toValueString(round(num, digits))
2863 var nums = str.split('.')
2864 var intStr = nums[0]
2865 var floatStr = nums[1] || ''
2866 var digitOffsetIndex = digits - floatStr.length
2867 if (digits) {
2868 if (digitOffsetIndex > 0) {
2869 return intStr + '.' + floatStr + helperStringRepeat('0', digitOffsetIndex)
2870 }
2871 return intStr + helperNumberOffsetPoint(floatStr, Math.abs(digitOffsetIndex))
2872 }
2873 return intStr
2874}
2875
2876
2877
2878/**
2879 * 转数值
2880 * @param { String/Number } str 数值
2881 *
2882 * @return {Number}
2883 */
2884var toNumber = helperCreateToNumber(parseFloat)
2885
2886
2887
2888/**
2889 * 数值转字符串,科学计数转字符串
2890 * @param { Number } num 数值
2891 *
2892 * @return {Number}
2893 */
2894function toNumberString(num) {
2895 var rest = '' + num
2896 var scienceMatchs = rest.match(/^([-+]?)((\d+)|((\d+)?[.](\d+)?))e([-+]{1})([0-9]+)$/)
2897 if (scienceMatchs) {
2898 var isNegative = num < 0
2899 var absFlag = isNegative ? '-' : ''
2900 var intNumStr = scienceMatchs[3] || ''
2901 var dIntNumStr = scienceMatchs[5] || ''
2902 var dFloatNumStr = scienceMatchs[6] || ''
2903 var sciencFlag = scienceMatchs[7]
2904 var scienceNumStr = scienceMatchs[8]
2905 var floatOffsetIndex = scienceNumStr - dFloatNumStr.length
2906 var intOffsetIndex = scienceNumStr - intNumStr.length
2907 var dIntOffsetIndex = scienceNumStr - dIntNumStr.length
2908 if (sciencFlag === '+') {
2909 if (intNumStr) {
2910 return absFlag + intNumStr + helperStringRepeat('0', scienceNumStr)
2911 }
2912 if (floatOffsetIndex > 0) {
2913 return absFlag + dIntNumStr + dFloatNumStr + helperStringRepeat('0', floatOffsetIndex)
2914 }
2915 return absFlag + dIntNumStr + helperNumberOffsetPoint(dFloatNumStr, scienceNumStr)
2916 }
2917 if (intNumStr) {
2918 if (intOffsetIndex > 0) {
2919 return absFlag + '0.' + helperStringRepeat('0', Math.abs(intOffsetIndex)) + intNumStr
2920 }
2921 return absFlag + helperNumberOffsetPoint(intNumStr, intOffsetIndex)
2922 }
2923 if (dIntOffsetIndex > 0) {
2924 return absFlag + '0.' + helperStringRepeat('0', Math.abs(dIntOffsetIndex)) + dIntNumStr + dFloatNumStr
2925 }
2926 return absFlag + helperNumberOffsetPoint(dIntNumStr, dIntOffsetIndex) + dFloatNumStr
2927 }
2928 return rest
2929}
2930
2931
2932
2933
2934/**
2935 * 转整数
2936 * @param { String/Number } str 数值
2937 *
2938 * @return {Number}
2939 */
2940var toInteger = helperCreateToNumber(staticParseInt)
2941
2942
2943
2944/**
2945 * 加法运算
2946 *
2947 * @param { Number } num1 被加数
2948 * @param { Number } num2 加数
2949 * @return {Number}
2950 */
2951function add (num1, num2) {
2952 return helperNumberAdd(toNumber(num1), toNumber(num2))
2953}
2954
2955
2956
2957/**
2958 * 减法运算
2959 *
2960 * @param { Number } num1 被减数
2961 * @param { Number } num2 减数
2962 * @return {Number}
2963 */
2964function subtract (num1, num2) {
2965 var subtrahend = toNumber(num1)
2966 var minuend = toNumber(num2)
2967 var str1 = toNumberString(subtrahend)
2968 var str2 = toNumberString(minuend)
2969 var digit1 = helperNumberDecimal(str1)
2970 var digit2 = helperNumberDecimal(str2)
2971 var ratio = Math.pow(10, Math.max(digit1, digit2))
2972 var precision = (digit1 >= digit2) ? digit1 : digit2
2973 return parseFloat(toFixed((subtrahend * ratio - minuend * ratio) / ratio, precision))
2974}
2975
2976
2977
2978
2979/**
2980 * 乘法运算
2981 *
2982 * @param { Number } num1 数值1
2983 * @param { Number } num2 数值2
2984 * @return {Number}
2985 */
2986function multiply (num1, num2) {
2987 var multiplier = toNumber(num1)
2988 var multiplicand = toNumber(num2)
2989 return helperMultiply(multiplier, multiplicand)
2990}
2991
2992
2993
2994/**
2995 * 除法运算
2996 *
2997 * @param { Number } num1 数值1
2998 * @param { Number } num2 数值2
2999 * @return {Number}
3000 */
3001function divide (num1, num2) {
3002 return helperNumberDivide(toNumber(num1), toNumber(num2))
3003}
3004
3005
3006
3007
3008/**
3009 * 求和函数,将数值相加
3010 *
3011 * @param {Array} array 数组
3012 * @param {Function/String} iterate 方法或属性
3013 * @param {Object} context 上下文
3014 * @return {Number}
3015 */
3016function sum (array, iterate, context) {
3017 var result = 0
3018 each(array, iterate ? isFunction(iterate) ? function () {
3019 result = helperNumberAdd(result, iterate.apply(context, arguments))
3020 } : function (val) {
3021 result = helperNumberAdd(result, get(val, iterate))
3022 } : function (val) {
3023 result = helperNumberAdd(result, val)
3024 })
3025 return result
3026}
3027
3028
3029
3030
3031
3032/**
3033 * 求平均值函数
3034 *
3035 * @param {Array} array 数组
3036 * @param {Function/String} iterate 方法或属性
3037 * @param {Object} context 上下文
3038 * @return {Number}
3039 */
3040function mean (array, iterate, context) {
3041 return helperNumberDivide(sum(array, iterate, context), getSize(array))
3042}
3043
3044
3045
3046/**
3047 * 返回当前时间戳
3048 *
3049 * @returns Number
3050 */
3051var now = Date.now || function () {
3052 return helperGetDateTime(helperNewDate())
3053}
3054
3055
3056
3057
3058
3059/**
3060 * 将日期格式化为时间戳
3061 *
3062 * @param {String/Number/Date} str 日期或数字
3063 * @param {String} format 解析日期格式
3064 * @returns Number
3065 */
3066var timestamp = function (str, format) {
3067 if (str) {
3068 var date = toStringDate(str, format)
3069 return isDate(date) ? helperGetDateTime(date) : date
3070 }
3071 return now()
3072}
3073
3074
3075
3076/**
3077 * 判断是否有效的Date对象
3078 *
3079 * @param {any} val 对象
3080 * @return {boolean}
3081 */
3082function isValidDate (val) {
3083 return isDate(val) && !isNaN(helperGetDateTime(val))
3084}
3085
3086
3087
3088/**
3089 * 比较两个日期
3090 *
3091 * @param {Number/String/Date} date1 日期
3092 * @param {Number/String/Date} date2 日期
3093 * @param {String} format 对比格式
3094 */
3095function isDateSame (date1, date2, format) {
3096 if (date1 && date2) {
3097 date1 = toDateString(date1, format)
3098 return date1 !== 'Invalid Date' && date1 === toDateString(date2, format)
3099 }
3100 return false
3101}
3102
3103
3104
3105
3106
3107function getParseRule (txt) {
3108 return '(\\d{' + txt + '})'
3109}
3110
3111function toParseMs (num) {
3112 if (num < 10) {
3113 return num * 100
3114 } else if (num < 100) {
3115 return num * 10
3116 }
3117 return num
3118}
3119
3120function toParseNum (num) {
3121 return isNaN(num) ? num : staticParseInt(num)
3122}
3123
3124var d2 = getParseRule('2')
3125var d1or2 = getParseRule('1,2')
3126var d1or3 = getParseRule('1,3')
3127var d3or4 = getParseRule('3,4')
3128var place = '.{1}'
3129var d1Or2RE = place + d1or2
3130var dzZ = '(([zZ])|([-+]\\d{2}:?\\d{2}))'
3131
3132var defaulParseStrs = [d3or4, d1Or2RE, d1Or2RE, d1Or2RE, d1Or2RE, d1Or2RE, place + d1or3, dzZ]
3133var defaulParseREs = []
3134
3135for (var len = defaulParseStrs.length - 1; len >= 0; len--) {
3136 var rule = ''
3137 for (var i = 0; i < len + 1; i++) {
3138 rule += defaulParseStrs[i]
3139 }
3140 defaulParseREs.push(new RegExp('^' + rule + '$'))
3141}
3142
3143/**
3144 * 解析默认格式
3145 */
3146function parseDefaultRules (str) {
3147 var matchRest, resMaps = {}
3148 for (var i = 0, dfrLen = defaulParseREs.length; i < dfrLen; i++) {
3149 matchRest = str.match(defaulParseREs[i])
3150 if (matchRest) {
3151 resMaps.y = matchRest[1]
3152 resMaps.M = matchRest[2]
3153 resMaps.d = matchRest[3]
3154 resMaps.H = matchRest[4]
3155 resMaps.m = matchRest[5]
3156 resMaps.s = matchRest[6]
3157 resMaps.S = matchRest[7]
3158 resMaps.Z = matchRest[8]
3159 break
3160 }
3161 }
3162 return resMaps
3163}
3164
3165var customParseStrs = [
3166 ['yyyy', d3or4],
3167 ['yy', d2],
3168 ['MM', d2],
3169 ['M', d1or2],
3170 ['dd', d2],
3171 ['d', d1or2],
3172 ['HH', d2],
3173 ['H', d1or2],
3174 ['mm', d2],
3175 ['m', d1or2],
3176 ['ss', d2],
3177 ['s', d1or2],
3178 ['SSS', getParseRule('3')],
3179 ['S', d1or3],
3180 ['Z', dzZ]
3181]
3182var parseRuleMaps = {}
3183var parseRuleKeys = ['\\[([^\\]]+)\\]']
3184
3185for (var i = 0; i < customParseStrs.length; i++) {
3186 var itemRule = customParseStrs[i]
3187 parseRuleMaps[itemRule[0]] = itemRule[1] + '?'
3188 parseRuleKeys.push(itemRule[0])
3189}
3190
3191var customParseRes = new RegExp(parseRuleKeys.join('|'), 'g')
3192var cacheFormatMaps = {}
3193
3194/**
3195 * 解析自定义格式
3196 */
3197function parseCustomRules (str, format) {
3198 var cacheItem = cacheFormatMaps[format]
3199 if (!cacheItem) {
3200 var posIndexs = []
3201 var re = format.replace(/([$(){}*+.?\\^|])/g, "\\$1").replace(customParseRes, function (text, val) {
3202 var firstChar = text.charAt(0)
3203 // 如果为转义符号:[关键字]
3204 if (firstChar === '[') {
3205 return val
3206 }
3207 posIndexs.push(firstChar)
3208 return parseRuleMaps[text]
3209 })
3210 cacheItem = cacheFormatMaps[format] = {
3211 _i: posIndexs,
3212 _r: new RegExp(re)
3213 }
3214 }
3215 var resMaps = {}
3216 var matchRest = str.match(cacheItem._r)
3217 if (matchRest) {
3218 var _i = cacheItem._i
3219 for (var i = 1, len = matchRest.length; i < len; i++) {
3220 resMaps[_i[i - 1]] = matchRest[i]
3221 }
3222 return resMaps
3223 }
3224 return resMaps
3225}
3226
3227/**
3228 * 解析时区
3229 */
3230function parseTimeZone (resMaps) {
3231 // 如果为UTC 时间
3232 if (/^[zZ]/.test(resMaps.Z)) {
3233 return new Date(helperGetUTCDateTime(resMaps))
3234 } else {
3235 // 如果指定时区,时区转换
3236 var matchRest = resMaps.Z.match(/([-+])(\d{2}):?(\d{2})/)
3237 if (matchRest) {
3238 return new Date(helperGetUTCDateTime(resMaps) - (matchRest[1] === '-' ? -1 : 1) * staticParseInt(matchRest[2]) * 3600000 + staticParseInt(matchRest[3]) * 60000)
3239 }
3240 }
3241 return new Date('')
3242}
3243
3244/**
3245 * 字符串转为日期
3246 *
3247 * @param {String/Number/Date} str 日期或数字
3248 * @param {String} format 解析日期格式(yyyy年份、MM月份、dd天、hh(12)HH(24)小时、mm分钟、ss秒、SSS毫秒、Z时区)
3249 * @return {Date}
3250 */
3251function toStringDate (str, format) {
3252 if (str) {
3253 var isDType = isDate(str)
3254 if (isDType || (!format && /^[0-9]{11,15}$/.test(str))) {
3255 return new Date(isDType ? helperGetDateTime(str) : staticParseInt(str))
3256 }
3257 if (isString(str)) {
3258 var resMaps = format ? parseCustomRules(str, format) : parseDefaultRules(str)
3259 if (resMaps.y) {
3260 if (resMaps.M) {
3261 resMaps.M = toParseNum(resMaps.M) - 1
3262 }
3263 if (resMaps.S) {
3264 resMaps.S = toParseMs(toParseNum(resMaps.S))
3265 }
3266 if (resMaps.Z) {
3267 return parseTimeZone(resMaps)
3268 } else {
3269 return new Date(resMaps.y, resMaps.M || 0, resMaps.d || 1, resMaps.H || 0, resMaps.m || 0, resMaps.s || 0, resMaps.S || 0)
3270 }
3271 }
3272 }
3273 }
3274 return new Date('')
3275}
3276
3277
3278
3279
3280
3281
3282
3283
3284function handleCustomTemplate (date, formats, match, value) {
3285 var format = formats[match]
3286 if (format) {
3287 if (isFunction(format)) {
3288 return format(value, match, date)
3289 } else {
3290 return format[value]
3291 }
3292 }
3293 return value
3294}
3295
3296function formatDayE (day) {
3297 return day === 0 ? 7 : day
3298}
3299
3300/**
3301 * 日期格式化为字符串,转义符号 []
3302 *
3303 * @param {Date} date 日期或数字
3304 * @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时区)
3305 * @param {Object} options {formats: {q: ['日', '一', '二', '三', '四', '五', '六'], E: function (value, match, date) {return '三'}, }} 自定义格式化模板
3306 * @return {String}
3307 */
3308var dateFormatRE = /\[([^\]]+)]|y{2,4}|M{1,2}|d{1,2}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|S{1,3}|Z{1,2}|W{1,2}|D{1,3}|[aAeEq]/g
3309function toDateString (date, format, options) {
3310 if (date) {
3311 date = toStringDate(date)
3312 if (isValidDate(date)) {
3313 var result = format || setupDefaults.formatString
3314 var hours = date.getHours()
3315 var apm = hours < 12 ? 'am' : 'pm'
3316 var formats = assign({}, setupDefaults.formatStringMatchs, options ? options.formats : null)
3317 var fy = function (match, length) {
3318 return ('' + helperGetDateFullYear(date)).substr(4 - length)
3319 }
3320 var fM = function (match, length) {
3321 return padStart(helperGetDateMonth(date) + 1, length, '0')
3322 }
3323 var fd = function (match, length) {
3324 return padStart(date.getDate(), length, '0')
3325 }
3326 var fH = function (match, length) {
3327 return padStart(hours, length, '0')
3328 }
3329 var fh = function (match, length) {
3330 return padStart(hours <= 12 ? hours : hours - 12, length, '0')
3331 }
3332 var fm = function (match, length) {
3333 return padStart(date.getMinutes(), length, '0')
3334 }
3335 var fs = function (match, length) {
3336 return padStart(date.getSeconds(), length, '0')
3337 }
3338 var fS = function (match, length) {
3339 return padStart(date.getMilliseconds(), length, '0')
3340 }
3341 var fZ = function (match, length) {
3342 var zoneHours = date.getTimezoneOffset() / 60 * -1
3343 return handleCustomTemplate(date, formats, match, (zoneHours >= 0 ? '+' : '-') + padStart(zoneHours, 2, '0') + (length === 1 ? ':' : '') + '00')
3344 }
3345 var fW = function (match, length) {
3346 return padStart(handleCustomTemplate(date, formats, match, getYearWeek(date)), length, '0')
3347 }
3348 var fD = function (match, length) {
3349 return padStart(handleCustomTemplate(date, formats, match, getYearDay(date)), length, '0')
3350 }
3351 var parseDates = {
3352 yyyy: fy,
3353 yy: fy,
3354 MM: fM,
3355 M: fM,
3356 dd: fd,
3357 d: fd,
3358 HH: fH,
3359 H: fH,
3360 hh: fh,
3361 h: fh,
3362 mm: fm,
3363 m: fm,
3364 ss: fs,
3365 s: fs,
3366 SSS: fS,
3367 S: fS,
3368 ZZ: fZ,
3369 Z: fZ,
3370 WW: fW,
3371 W: fW,
3372 DDD: fD,
3373 D: fD,
3374 a: function (match) {
3375 return handleCustomTemplate(date, formats, match, apm)
3376 },
3377 A: function (match) {
3378 return handleCustomTemplate(date, formats, match, helperStringUpperCase(apm))
3379 },
3380 e: function (match) {
3381 return handleCustomTemplate(date, formats, match, date.getDay())
3382 },
3383 E: function (match) {
3384 return handleCustomTemplate(date, formats, match, formatDayE(date.getDay()))
3385 },
3386 q: function (match) {
3387 return handleCustomTemplate(date, formats, match, Math.floor((helperGetDateMonth(date) + 3) / 3))
3388 }
3389 }
3390 return result.replace(dateFormatRE, function (match, skip) {
3391 return skip || (parseDates[match] ? parseDates[match](match, match.length) : match)
3392 })
3393 }
3394 return 'Invalid Date'
3395 }
3396 return ''
3397}
3398
3399
3400
3401
3402
3403/**
3404 * 返回前几年或后几年的日期
3405 *
3406 * @param {Date} date 日期或数字
3407 * @param {Number} offset 年(默认当前年)、前几个年(数值)、后几个年(数值)
3408 * @param {Number/String} month 获取哪月(null默认当前年)、年初(first)、年末(last)、指定月份(0-11)
3409 * @return {Date}
3410 */
3411function getWhatYear (date, offset, month) {
3412 var number
3413 date = toStringDate(date)
3414 if (isValidDate(date)) {
3415 if (offset) {
3416 number = offset && !isNaN(offset) ? offset : 0
3417 date.setFullYear(helperGetDateFullYear(date) + number)
3418 }
3419 if (month || !isNaN(month)) {
3420 if (month === staticStrFirst) {
3421 return new Date(helperGetDateFullYear(date), 0, 1)
3422 } else if (month === staticStrLast) {
3423 date.setMonth(11)
3424 return getWhatMonth(date, 0, staticStrLast)
3425 } else {
3426 date.setMonth(month)
3427 }
3428 }
3429 }
3430 return date
3431}
3432
3433
3434
3435
3436
3437function getQuarterNumber (date) {
3438 var month = date.getMonth()
3439 if (month < 3) {
3440 return 1
3441 } else if (month < 6) {
3442 return 2
3443 } else if (month < 9) {
3444 return 3
3445 }
3446 return 4
3447}
3448
3449/**
3450 * 返回前几季度或后几季度的日期
3451 *
3452 * @param {Date} date 日期
3453 * @param {Number} offset 季度(默认当前季度)、前几季度、后几季度
3454 * @param {Number} day 获取哪天:月初(first)、月末(last)、指定天数(数值),如果为空,但超过指定月份的天数时,则默认单月最后一天
3455 * @return {Date}
3456 */
3457function getWhatQuarter (date, offset, day) {
3458 var currMonth, monthOffset = offset && !isNaN(offset) ? offset * 3 : 0
3459 date = toStringDate(date)
3460 if (isValidDate(date)) {
3461 currMonth = (getQuarterNumber(date) - 1) * 3
3462 date.setMonth(currMonth)
3463 return getWhatMonth(date, monthOffset, day)
3464 }
3465 return date
3466}
3467
3468
3469
3470
3471
3472/**
3473 * 返回前几月或后几月的日期
3474 *
3475 * @param {Date} date 日期或数字
3476 * @param {Number} offset 月(默认当前月)、前几个月、后几个月
3477 * @param {Number/String} day 获取哪天:月初(first)、月末(last)、指定天数(数值),如果为空,但超过指定月份的天数时,则默认单月最后一天
3478 * @return {Date}
3479 */
3480function getWhatMonth (date, offset, day) {
3481 var monthOffset = offset && !isNaN(offset) ? offset : 0
3482 date = toStringDate(date)
3483 if (isValidDate(date)) {
3484 if (day === staticStrFirst) {
3485 return new Date(helperGetDateFullYear(date), helperGetDateMonth(date) + monthOffset, 1)
3486 } else if (day === staticStrLast) {
3487 return new Date(helperGetDateTime(getWhatMonth(date, monthOffset + 1, staticStrFirst)) - 1)
3488 } else if (isNumber(day)) {
3489 date.setDate(day)
3490 }
3491 if (monthOffset) {
3492 var currDate = date.getDate()
3493 date.setMonth(helperGetDateMonth(date) + monthOffset)
3494 if (currDate !== date.getDate()) {
3495 // 当为指定天数,且被跨月了,则默认单月最后一天
3496 date.setDate(1)
3497 return new Date(helperGetDateTime(date) - staticDayTime)
3498 }
3499 }
3500 }
3501 return date
3502}
3503
3504
3505
3506
3507
3508
3509/**
3510 * 返回前几周或后几周的星期几
3511 *
3512 * @param {Date} date 日期
3513 * @param {Number} offset 周(默认当前周)、前几周、后几周
3514 * @param {Number} day 星期天(默认0)、星期一(1)、星期二(2)、星期三(3)、星期四(4)、星期五(5)、星期六(6)
3515 * @return {Date}
3516 */
3517function getWhatWeek (date, offset, day) {
3518 var time, whatDayTime, currentDay, customDay
3519 date = toStringDate(date)
3520 if (isValidDate(date)) {
3521 customDay = staticParseInt(/^[0-7]$/.test(day) ? day : date.getDay())
3522 currentDay = date.getDay()
3523 time = helperGetDateTime(date)
3524 whatDayTime = time + ((customDay === 0 ? 7 : customDay) - (currentDay === 0 ? 7 : currentDay)) * staticDayTime
3525 if (offset && !isNaN(offset)) {
3526 whatDayTime += offset * staticWeekTime
3527 }
3528 return new Date(whatDayTime)
3529 }
3530 return date
3531}
3532
3533
3534
3535
3536
3537/**
3538 * 返回前几天或后几天的日期
3539 *
3540 * @param {Date} date 日期或数字
3541 * @param {Number} offset 天(默认当天)、前几天、后几天
3542 * @param {String} mode 获取时分秒(null默认当前时分秒)、日初(first)、日末(last)
3543 * @return {Date}
3544 */
3545function getWhatDay (date, offset, mode) {
3546 date = toStringDate(date)
3547 if (isValidDate(date) && !isNaN(offset)) {
3548 date.setDate(date.getDate() + staticParseInt(offset))
3549 if (mode === staticStrFirst) {
3550 return new Date(helperGetDateFullYear(date), helperGetDateMonth(date), date.getDate())
3551 } else if (mode === staticStrLast) {
3552 return new Date(helperGetDateTime(getWhatDay(date, 1, staticStrFirst)) - 1)
3553 }
3554 }
3555 return date
3556}
3557
3558
3559
3560
3561
3562
3563/**
3564 * 返回某个年份的第几天
3565 *
3566 * @param {Date} date 日期或数字
3567 * @return {Number}
3568 */
3569function getYearDay (date) {
3570 date = toStringDate(date)
3571 if (isValidDate(date)) {
3572 return Math.floor((helperGetYMDTime(date) - helperGetYMDTime(getWhatYear(date, 0, staticStrFirst))) / staticDayTime) + 1
3573 }
3574 return NaN
3575}
3576
3577
3578
3579
3580
3581/**
3582 * 返回某个年份的第几周
3583 *
3584 * @param {Date} date 日期或数字
3585 * @return {Number}
3586 */
3587function getYearWeek (date) {
3588 date = toStringDate(date)
3589 if (isValidDate(date)) {
3590 date.setHours(0, 0, 0, 0)
3591 date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7)
3592 var week = new Date(date.getFullYear(), 0, 4)
3593 return Math.round(((date.getTime() - week.getTime()) / staticDayTime + (week.getDay() + 6) % 7 - 3) / 7) + 1
3594 }
3595 return NaN
3596}
3597
3598
3599
3600
3601
3602
3603/**
3604 * 返回某个月的第几周
3605 *
3606 * @param {Date} date 日期或数字
3607 * @return {Number}
3608 */
3609function getMonthWeek (date) {
3610 var monthFirst, monthFirstWeek
3611 var currentDate = toStringDate(date)
3612 if (isValidDate(currentDate)) {
3613 monthFirst = getWhatMonth(currentDate, 0, staticStrFirst)
3614 monthFirstWeek = getWhatWeek(monthFirst, 0, 1)
3615 if (monthFirstWeek < monthFirst) {
3616 monthFirstWeek = getWhatWeek(monthFirst, 1, 1)
3617 }
3618 if (currentDate >= monthFirstWeek) {
3619 return Math.floor((helperGetYMDTime(currentDate) - helperGetYMDTime(monthFirstWeek)) / staticWeekTime) + 1
3620 }
3621 return getMonthWeek(getWhatWeek(currentDate, 0, 1))
3622 }
3623 return NaN
3624}
3625
3626
3627
3628
3629/**
3630 * 返回某个年份的天数
3631 *
3632 * @param {Date} date 日期或数字
3633 * @param {Number} offset 年(默认当年)、前几个年、后几个年
3634 * @return {Number}
3635 */
3636function getDayOfYear (date, year) {
3637 date = toStringDate(date)
3638 if (isValidDate(date)) {
3639 return isLeapYear(getWhatYear(date, year)) ? 366 : 365
3640 }
3641 return NaN
3642}
3643
3644
3645
3646
3647
3648
3649/**
3650 * 返回某个月份的天数
3651 *
3652 * @param {Date} date 日期或数字
3653 * @param {Number} offset 月(默认当月)、前几个月、后几个月
3654 * @return {Number}
3655 */
3656function getDayOfMonth (date, month) {
3657 date = toStringDate(date)
3658 if (isValidDate(date)) {
3659 return Math.floor((helperGetDateTime(getWhatMonth(date, month, staticStrLast)) - helperGetDateTime(getWhatMonth(date, month, staticStrFirst))) / staticDayTime) + 1
3660 }
3661 return NaN
3662}
3663
3664
3665
3666
3667
3668
3669/**
3670 * 返回两个日期之间差距,如果结束日期小于开始日期done为fasle
3671 *
3672 * @param {Date} startDate 开始日期
3673 * @param {Date} endDate 结束日期或当期日期
3674 * @param {Date} rule 自定义计算规则
3675 * @return {Object}
3676 */
3677function getDateDiff (startDate, endDate, rules) {
3678 var startTime, endTime, item, diffTime, rule, len, index
3679 var result = { done: false, time: 0 }
3680 startDate = toStringDate(startDate)
3681 endDate = endDate ? toStringDate(endDate) : helperNewDate()
3682 if (isValidDate(startDate) && isValidDate(endDate)) {
3683 startTime = helperGetDateTime(startDate)
3684 endTime = helperGetDateTime(endDate)
3685 if (startTime < endTime) {
3686 diffTime = result.time = endTime - startTime
3687 rule = rules && rules.length > 0 ? rules : setupDefaults.dateDiffRules
3688 result.done = true
3689 for (index = 0, len = rule.length; index < len; index++) {
3690 item = rule[index]
3691 if (diffTime >= item[1]) {
3692 if (index === len - 1) {
3693 result[item[0]] = diffTime || 0
3694 } else {
3695 result[item[0]] = Math.floor(diffTime / item[1])
3696 diffTime -= result[item[0]] * item[1]
3697 }
3698 } else {
3699 result[item[0]] = 0
3700 }
3701 }
3702 }
3703 }
3704 return result
3705}
3706
3707
3708
3709/**
3710 * 去除字符串左右两边的空格
3711 *
3712 * @param {String} str 字符串
3713 * @return {String}
3714 */
3715function trim (str) {
3716 return str && str.trim ? str.trim() : trimRight(trimLeft(str))
3717}
3718
3719
3720
3721/**
3722 * 去除字符串左边的空格
3723 *
3724 * @param {String} str 字符串
3725 * @return {String}
3726 */
3727function trimLeft (str) {
3728 return str && str.trimLeft ? str.trimLeft() : toValueString(str).replace(/^[\s\uFEFF\xA0]+/g, '')
3729}
3730
3731
3732
3733/**
3734 * 去除字符串右边的空格
3735 *
3736 * @param {String} str 字符串
3737 * @return {String}
3738 */
3739function trimRight (str) {
3740 return str && str.trimRight ? str.trimRight() : toValueString(str).replace(/[\s\uFEFF\xA0]+$/g, '')
3741}
3742
3743
3744
3745
3746/**
3747 * 转义HTML字符串,替换&, <, >, ", ', `字符
3748 *
3749 * @param {String} str 字符串
3750 * @return {String}
3751 */
3752var escape = helperFormatEscaper(staticEscapeMap)
3753
3754
3755
3756
3757
3758var unescapeMap = {}
3759each(staticEscapeMap, function (item, key) {
3760 unescapeMap[staticEscapeMap[key]] = key
3761})
3762
3763/**
3764 * 反转escape
3765 *
3766 * @param {String} str 字符串
3767 * @return {String}
3768 */
3769var unescape = helperFormatEscaper(unescapeMap)
3770
3771
3772
3773var camelCacheMaps = {}
3774
3775/**
3776 * 将带字符串转成驼峰字符串,例如: project-name 转为 projectName
3777 *
3778 * @param {String} str 字符串
3779 * @return {String}
3780 */
3781function camelCase (str) {
3782 str = toValueString(str)
3783 if (camelCacheMaps[str]) {
3784 return camelCacheMaps[str]
3785 }
3786 var strLen = str.length
3787 var rest = str.replace(/([-]+)/g, function (text, flag, index) {
3788 return index && index + flag.length < strLen ? '-' : ''
3789 })
3790 strLen = rest.length
3791 rest = rest.replace(/([A-Z]+)/g, function (text, upper, index) {
3792 var upperLen = upper.length
3793 upper = helperStringLowerCase(upper)
3794 if (index) {
3795 if (upperLen > 2 && index + upperLen < strLen) {
3796 return helperStringUpperCase(helperStringSubstring(upper, 0, 1)) + helperStringSubstring(upper, 1, upperLen - 1) + helperStringUpperCase(helperStringSubstring(upper, upperLen - 1, upperLen))
3797 }
3798 return helperStringUpperCase(helperStringSubstring(upper, 0, 1)) + helperStringSubstring(upper, 1, upperLen)
3799 } else {
3800 if (upperLen > 1 && index + upperLen < strLen) {
3801 return helperStringSubstring(upper, 0, upperLen - 1) + helperStringUpperCase(helperStringSubstring(upper, upperLen - 1, upperLen))
3802 }
3803 }
3804 return upper
3805 }).replace(/(-[a-zA-Z])/g, function (text, upper) {
3806 return helperStringUpperCase(helperStringSubstring(upper, 1, upper.length))
3807 })
3808 camelCacheMaps[str] = rest
3809 return rest
3810}
3811
3812
3813
3814var kebabCacheMaps = {}
3815
3816/**
3817 * 将带驼峰字符串转成字符串,例如: projectName 转为 project-name
3818 *
3819 * @param {String} str 字符串
3820 * @return {String}
3821 */
3822function kebabCase (str) {
3823 str = toValueString(str)
3824 if (kebabCacheMaps[str]) {
3825 return kebabCacheMaps[str]
3826 }
3827 if (/^[A-Z]+$/.test(str)) {
3828 return helperStringLowerCase(str)
3829 }
3830 var rest = str.replace(/^([a-z])([A-Z]+)([a-z]+)$/, function (text, prevLower, upper, nextLower) {
3831 var upperLen = upper.length
3832 if (upperLen > 1) {
3833 return prevLower + '-' + helperStringLowerCase(helperStringSubstring(upper, 0, upperLen - 1)) + '-' + helperStringLowerCase(helperStringSubstring(upper, upperLen - 1, upperLen)) + nextLower
3834 }
3835 return helperStringLowerCase(prevLower + '-' + upper + nextLower)
3836 }).replace(/^([A-Z]+)([a-z]+)?$/, function (text, upper, nextLower) {
3837 var upperLen = upper.length
3838 return helperStringLowerCase(helperStringSubstring(upper, 0, upperLen - 1) + '-' + helperStringSubstring(upper, upperLen - 1, upperLen) + (nextLower || ''))
3839 }).replace(/([a-z]?)([A-Z]+)([a-z]?)/g, function (text, prevLower, upper, nextLower, index) {
3840 var upperLen = upper.length
3841 if (upperLen > 1) {
3842 if (prevLower) {
3843 prevLower += '-'
3844 }
3845 if (nextLower) {
3846 return (prevLower || '') + helperStringLowerCase(helperStringSubstring(upper, 0, upperLen - 1)) + '-' + helperStringLowerCase(helperStringSubstring(upper, upperLen - 1, upperLen)) + nextLower
3847 }
3848 }
3849 return (prevLower || '') + (index ? '-' : '') + helperStringLowerCase(upper) + (nextLower || '')
3850 })
3851 rest = rest.replace(/([-]+)/g, function (text, flag, index) {
3852 return index && index + flag.length < rest.length ? '-' : ''
3853 })
3854 kebabCacheMaps[str] = rest
3855 return rest
3856}
3857
3858
3859
3860
3861/**
3862 * 将字符串重复 n 次
3863 *
3864 * @param {String} str 字符串
3865 * @param {Number} count 次数
3866 * @return {String}
3867 */
3868function repeat (str, count) {
3869 return helperStringRepeat(toValueString(str), count)
3870}
3871
3872
3873
3874
3875
3876/**
3877 * 用指定字符从前面开始补全字符串
3878 *
3879 * @param {String} str 字符串
3880 * @param {Number} targetLength 结果长度
3881 * @param {Number} padString 补全字符
3882 * @return {String}
3883 */
3884function padStart (str, targetLength, padString) {
3885 var rest = toValueString(str)
3886 targetLength = targetLength >> 0
3887 padString = isUndefined(padString) ? ' ' : '' + padString
3888 if (rest.padStart) {
3889 return rest.padStart(targetLength, padString)
3890 }
3891 if (targetLength > rest.length) {
3892 targetLength -= rest.length
3893 if (targetLength > padString.length) {
3894 padString += helperStringRepeat(padString, targetLength / padString.length)
3895 }
3896 return padString.slice(0, targetLength) + rest
3897 }
3898 return rest
3899}
3900
3901
3902
3903
3904
3905/**
3906 * 用指定字符从后面开始补全字符串
3907 *
3908 * @param {String} str 字符串
3909 * @param {Number} targetLength 结果长度
3910 * @param {Number} padString 补全字符
3911 * @return {String}
3912 */
3913function padEnd (str, targetLength, padString) {
3914 var rest = toValueString(str)
3915 targetLength = targetLength >> 0
3916 padString = isUndefined(padString) ? ' ' : '' + padString
3917 if (rest.padEnd) {
3918 return rest.padEnd(targetLength, padString)
3919 }
3920 if (targetLength > rest.length) {
3921 targetLength -= rest.length
3922 if (targetLength > padString.length) {
3923 padString += helperStringRepeat(padString, targetLength / padString.length)
3924 }
3925 return rest + padString.slice(0, targetLength)
3926 }
3927 return rest
3928}
3929
3930
3931
3932/**
3933 * 判断字符串是否在源字符串的头部
3934 *
3935 * @param {String} str 字符串
3936 * @param {String/Number} val 值
3937 * @param {Number} startIndex 开始索引
3938 * @return {String}
3939 */
3940function startsWith (str, val, startIndex) {
3941 var rest = toValueString(str)
3942 return (arguments.length === 1 ? rest : rest.substring(startIndex)).indexOf(val) === 0
3943}
3944
3945
3946
3947/**
3948 * 判断字符串是否在源字符串的尾部
3949 *
3950 * @param {String} str 字符串
3951 * @param {String/Number} val 值
3952 * @param {Number} startIndex 开始索引
3953 * @return {String}
3954 */
3955function endsWith (str, val, startIndex) {
3956 var rest = toValueString(str)
3957 var argsLen = arguments.length
3958 return argsLen > 1 && (argsLen > 2 ? rest.substring(0, startIndex).indexOf(val) === startIndex - 1 : rest.indexOf(val) === rest.length - 1)
3959}
3960
3961
3962
3963
3964
3965/**
3966 * 解析动态字符串模板
3967 * @param {atring} str 字符串模板
3968 * @param {any | any[]} args 对象
3969 * @param {any} options
3970 */
3971function template (str, args, options) {
3972 return toValueString(str).replace((options || setupDefaults).tmplRE || /\{{2}([.\w[\]\s]+)\}{2}/g, function (match, key) {
3973 return get(args, trim(key))
3974 })
3975}
3976
3977
3978
3979/**
3980 * 字符串格式化占位符
3981 * @param { string } str
3982 * @param { object | any[] } obj
3983 */
3984function toFormatString (str, obj) {
3985 return template(str, obj,{ tmplRE: /\{([.\w[\]\s]+)\}/g })
3986}
3987
3988
3989
3990
3991
3992function toValueString (obj) {
3993 if (isNumber(obj)) {
3994 return toNumberString(obj)
3995 }
3996 return '' + (eqNull(obj) ? '' : obj)
3997}
3998
3999
4000/**
4001 * 一个空的方法,始终返回 undefined,可用于初始化值
4002 */
4003function noop () {}
4004
4005
4006
4007/**
4008 * 返回一个获取对象属性的函数
4009 *
4010 * @param {String} name 属性名
4011 * @param {Object} defs 空值
4012 */
4013function property (name, defs) {
4014 return function (obj) {
4015 return isNull(obj) ? defs : obj[name]
4016 }
4017}
4018
4019
4020
4021/**
4022 * 创建一个绑定上下文的函数
4023 *
4024 * @param {Function} callback 函数
4025 * @param {Object} context 上下文
4026 * @param {*} args 额外的参数
4027 * @return {Object}
4028 */
4029function bind (callback, context) {
4030 var args = slice(arguments, 2)
4031 return function () {
4032 return callback.apply(context, slice(arguments).concat(args))
4033 }
4034}
4035
4036
4037
4038/**
4039 * 创建一个只能调用一次的函数,只会返回第一次执行后的结果
4040 *
4041 * @param {Function} callback 函数
4042 * @param {Object} context 上下文
4043 * @param {*} args 额外的参数
4044 * @return {Object}
4045 */
4046function once (callback, context) {
4047 var done = false
4048 var rest = null
4049 var args = slice(arguments, 2)
4050 return function () {
4051 if (done) {
4052 return rest
4053 }
4054 rest = callback.apply(context, slice(arguments).concat(args))
4055 done = true
4056 return rest
4057 }
4058}
4059
4060
4061
4062/**
4063 * 创建一个函数, 调用次数超过 count 次之后执行回调并将所有结果记住后返回
4064 *
4065 * @param {Number} count 调用次数
4066 * @param {Function} callback 完成回调
4067 * @return {Object}
4068 */
4069function after (count, callback, context) {
4070 var runCount = 0
4071 var rests = []
4072 return function () {
4073 var args = arguments
4074 runCount++
4075 if (runCount <= count) {
4076 rests.push(args[0])
4077 }
4078 if (runCount >= count) {
4079 callback.apply(context, [rests].concat(slice(args)))
4080 }
4081 }
4082}
4083
4084
4085
4086/**
4087 * 创建一个函数, 调用次数不超过 count 次之前执行回调并将所有结果记住后返回
4088 *
4089 * @param {Number} count 调用次数
4090 * @param {Function} callback 完成回调
4091 * @return {Object}
4092 */
4093function before (count, callback, context) {
4094 var runCount = 0
4095 var rests = []
4096 context = context || this
4097 return function () {
4098 var args = arguments
4099 runCount++
4100 if (runCount < count) {
4101 rests.push(args[0])
4102 callback.apply(context, [rests].concat(slice(args)))
4103 }
4104 }
4105}
4106
4107
4108/**
4109 * 节流函数;当被调用 n 毫秒后才会执行,如果在这时间内又被调用则至少每隔 n 秒毫秒调用一次该函数
4110 *
4111 * @param {Function} callback 回调
4112 * @param {Number} wait 多少秒毫
4113 * @param {Object} options 参数{leading: 是否在之前执行, trailing: 是否在之后执行}
4114 * @return {Function}
4115 */
4116function throttle (callback, wait, options) {
4117 var args, context
4118 var opts = options || {}
4119 var runFlag = false
4120 var timeout = 0
4121 var optLeading = 'leading' in opts ? opts.leading : true
4122 var optTrailing = 'trailing' in opts ? opts.trailing : false
4123 var runFn = function () {
4124 runFlag = true
4125 callback.apply(context, args)
4126 timeout = setTimeout(endFn, wait)
4127 }
4128 var endFn = function () {
4129 timeout = 0
4130 if (!runFlag && optTrailing === true) {
4131 runFn()
4132 }
4133 }
4134 var cancelFn = function () {
4135 var rest = timeout !== 0
4136 clearTimeout(timeout)
4137 runFlag = false
4138 timeout = 0
4139 return rest
4140 }
4141 var throttled = function () {
4142 args = arguments
4143 context = this
4144 runFlag = false
4145 if (timeout === 0) {
4146 if (optLeading === true) {
4147 runFn()
4148 } else if (optTrailing === true) {
4149 timeout = setTimeout(endFn, wait)
4150 }
4151 }
4152 }
4153 throttled.cancel = cancelFn
4154 return throttled
4155}
4156
4157
4158/**
4159 * 函数去抖;当被调用 n 毫秒后才会执行,如果在这时间内又被调用则将重新计算执行时间
4160 *
4161 * @param {Function} callback 回调
4162 * @param {Number} wait 多少秒毫
4163 * @param {Object} options 参数{leading: 是否在之前执行, trailing: 是否在之后执行}
4164 * @return {Function}
4165 */
4166function debounce (callback, wait, options) {
4167 var args, context
4168 var opts = options || {}
4169 var runFlag = false
4170 var timeout = 0
4171 var isLeading = typeof options === 'boolean'
4172 var optLeading = 'leading' in opts ? opts.leading : isLeading
4173 var optTrailing = 'trailing' in opts ? opts.trailing : !isLeading
4174 var runFn = function () {
4175 runFlag = true
4176 timeout = 0
4177 callback.apply(context, args)
4178 }
4179 var endFn = function () {
4180 if (optLeading === true) {
4181 timeout = 0
4182 }
4183 if (!runFlag && optTrailing === true) {
4184 runFn()
4185 }
4186 }
4187 var cancelFn = function () {
4188 var rest = timeout !== 0
4189 clearTimeout(timeout)
4190 timeout = 0
4191 return rest
4192 }
4193 var debounced = function () {
4194 runFlag = false
4195 args = arguments
4196 context = this
4197 if (timeout === 0) {
4198 if (optLeading === true) {
4199 runFn()
4200 }
4201 } else {
4202 clearTimeout(timeout)
4203 }
4204 timeout = setTimeout(endFn, wait)
4205 }
4206 debounced.cancel = cancelFn
4207 return debounced
4208}
4209
4210
4211
4212/**
4213 * 该方法和 setTimeout 一样的效果,区别就是支持上下文和额外参数
4214 *
4215 * @param {Function} callback 函数
4216 * @param {Number} wait 延迟毫秒
4217 * @param {*} args 额外的参数
4218 * @return {Number}
4219 */
4220function delay (callback, wait) {
4221 var args = slice(arguments, 2)
4222 var context = this
4223 return setTimeout(function () {
4224 callback.apply(context, args)
4225 }, wait)
4226}
4227
4228
4229
4230
4231
4232function parseURLQuery (uri) {
4233 return unserialize(uri.split('?')[1] || '')
4234}
4235
4236function parseUrl (url) {
4237 var hashs, portText, searchs, parsed
4238 var href = '' + url
4239 if (href.indexOf('//') === 0) {
4240 href = (staticLocation ? staticLocation.protocol : '') + href
4241 } else if (href.indexOf('/') === 0) {
4242 href = helperGetLocatOrigin() + href
4243 }
4244 searchs = href.replace(/#.*/, '').match(/(\?.*)/)
4245 parsed = {
4246 href: href,
4247 hash: '',
4248 host: '',
4249 hostname: '',
4250 protocol: '',
4251 port: '',
4252 search: searchs && searchs[1] && searchs[1].length > 1 ? searchs[1] : ''
4253 }
4254 parsed.path = href.replace(/^([a-z0-9.+-]*:)\/\//, function (text, protocol) {
4255 parsed.protocol = protocol
4256 return ''
4257 }).replace(/^([a-z0-9.+-]*)(:\d+)?\/?/, function (text, hostname, port) {
4258 portText = port || ''
4259 parsed.port = portText.replace(':', '')
4260 parsed.hostname = hostname
4261 parsed.host = hostname + portText
4262 return '/'
4263 }).replace(/(#.*)/, function (text, hash) {
4264 parsed.hash = hash.length > 1 ? hash : ''
4265 return ''
4266 })
4267 hashs = parsed.hash.match(/#((.*)\?|(.*))/)
4268 parsed.pathname = parsed.path.replace(/(\?|#.*).*/, '')
4269 parsed.origin = parsed.protocol + '//' + parsed.host
4270 parsed.hashKey = hashs ? (hashs[2] || hashs[1] || '') : ''
4271 parsed.hashQuery = parseURLQuery(parsed.hash)
4272 parsed.searchQuery = parseURLQuery(parsed.search)
4273 return parsed
4274}
4275
4276
4277
4278
4279function stringifyParams (resultVal, resultKey, isArr) {
4280 var _arr
4281 var result = []
4282 each(resultVal, function (item, key) {
4283 _arr = isArray(item)
4284 if (isPlainObject(item) || _arr) {
4285 result = result.concat(stringifyParams(item, resultKey + '[' + key + ']', _arr))
4286 } else {
4287 result.push(staticEncodeURIComponent(resultKey + '[' + (isArr ? '' : key) + ']') + '=' + staticEncodeURIComponent(isNull(item) ? '' : item))
4288 }
4289 })
4290 return result
4291}
4292
4293/**
4294 * 序列化查询参数
4295 *
4296 * @param {Object} query 查询参数
4297 */
4298function serialize (query) {
4299 var _arr
4300 var params = []
4301 each(query, function (item, key) {
4302 if (!isUndefined(item)) {
4303 _arr = isArray(item)
4304 if (isPlainObject(item) || _arr) {
4305 params = params.concat(stringifyParams(item, key, _arr))
4306 } else {
4307 params.push(staticEncodeURIComponent(key) + '=' + staticEncodeURIComponent(isNull(item) ? '' : item))
4308 }
4309 }
4310 })
4311 return params.join('&').replace(/%20/g, '+')
4312}
4313
4314
4315
4316
4317
4318/**
4319 * 反序列化查询参数
4320 * @param {String} query 字符串
4321 */
4322function unserialize (str) {
4323 var items
4324 var result = {}
4325 if (str && isString(str)) {
4326 arrayEach(str.split('&'), function (param) {
4327 items = param.split('=')
4328 result[staticDecodeURIComponent(items[0])] = staticDecodeURIComponent(items[1] || '')
4329 })
4330 }
4331 return result
4332}
4333
4334
4335
4336
4337
4338function getBaseURL () {
4339 if (staticLocation) {
4340 var pathname = staticLocation.pathname
4341 var lastIndex = lastIndexOf(pathname, '/') + 1
4342 return helperGetLocatOrigin() + (lastIndex === pathname.length ? pathname : pathname.substring(0, lastIndex))
4343 }
4344 return ''
4345}
4346
4347
4348
4349
4350/**
4351 * 获取地址栏信息
4352 *
4353 * @return Object
4354 */
4355function locat () {
4356 return staticLocation ? parseUrl(staticLocation.href) : {}
4357}
4358
4359
4360
4361
4362/* eslint-disable valid-typeof */
4363function isBrowseStorage (storage) {
4364 try {
4365 var testKey = '__xe_t'
4366 storage.setItem(testKey, 1)
4367 storage.removeItem(testKey)
4368 return true
4369 } catch (e) {
4370 return false
4371 }
4372}
4373
4374function isBrowseType (type) {
4375 return navigator.userAgent.indexOf(type) > -1
4376}
4377
4378/**
4379 * 获取浏览器内核
4380 * @return Object
4381 */
4382function browse () {
4383 var $body, isChrome, isEdge
4384 var isMobile = false
4385 var result = {
4386 isNode: false,
4387 isMobile: isMobile,
4388 isPC: false,
4389 isDoc: !!staticDocument
4390 }
4391 if (!staticWindow && typeof process !== staticStrUndefined) {
4392 result.isNode = true
4393 } else {
4394 isEdge = isBrowseType('Edge')
4395 isChrome = isBrowseType('Chrome')
4396 isMobile = /(Android|webOS|iPhone|iPad|iPod|SymbianOS|BlackBerry|Windows Phone)/.test(navigator.userAgent)
4397 if (result.isDoc) {
4398 $body = staticDocument.body || staticDocument.documentElement
4399 arrayEach(['webkit', 'khtml', 'moz', 'ms', 'o'], function (core) {
4400 result['-' + core] = !!$body[core + 'MatchesSelector']
4401 })
4402 }
4403 assign(result, {
4404 edge: isEdge,
4405 firefox: isBrowseType('Firefox'),
4406 msie: !isEdge && result['-ms'],
4407 safari: !isChrome && !isEdge && isBrowseType('Safari'),
4408 isMobile: isMobile,
4409 isPC: !isMobile,
4410 isLocalStorage: isBrowseStorage(staticWindow.localStorage),
4411 isSessionStorage: isBrowseStorage(staticWindow.sessionStorage)
4412 })
4413 }
4414 return result
4415}
4416
4417
4418
4419
4420
4421
4422
4423function toCookieUnitTime (unit, expires) {
4424 var num = parseFloat(expires)
4425 var nowdate = helperNewDate()
4426 var time = helperGetDateTime(nowdate)
4427 switch (unit) {
4428 case 'y': return helperGetDateTime(getWhatYear(nowdate, num))
4429 case 'M': return helperGetDateTime(getWhatMonth(nowdate, num))
4430 case 'd': return helperGetDateTime(getWhatDay(nowdate, num))
4431 case 'h':
4432 case 'H': return time + num * 60 * 60 * 1000
4433 case 'm': return time + num * 60 * 1000
4434 case 's': return time + num * 1000
4435 }
4436 return time
4437}
4438
4439function toCookieUTCString (date) {
4440 return (isDate(date) ? date : new Date(date)).toUTCString()
4441}
4442
4443/**
4444 * cookie操作函数
4445 * @param {String/Array/Object} name 键/数组/对象
4446 * @param {String} value 值
4447 * @param {Object} options 参数
4448 * @param {String} name: 键
4449 * @param {Object} value: 值
4450 * @param {String} path: 路径
4451 * @param {String} domain: 作用域
4452 * @param {Boolean} secure: 设置为安全的,只能用https协议
4453 * @param {Number} expires: 过期时间,可以指定日期或者字符串,默认天
4454 */
4455function cookie (name, value, options) {
4456 if (staticDocument) {
4457 var opts, expires, values, result, cookies, keyIndex
4458 var inserts = []
4459 var args = arguments
4460 if (isArray(name)) {
4461 inserts = name
4462 } else if (args.length > 1) {
4463 inserts = [assign({ name: name, value: value }, options)]
4464 } else if (isObject(name)) {
4465 inserts = [name]
4466 }
4467 if (inserts.length > 0) {
4468 arrayEach(inserts, function (obj) {
4469 opts = assign({}, setupDefaults.cookies, obj)
4470 values = []
4471 if (opts.name) {
4472 expires = opts.expires
4473 values.push(staticEncodeURIComponent(opts.name) + '=' + staticEncodeURIComponent(isObject(opts.value) ? JSON.stringify(opts.value) : opts.value))
4474 if (expires) {
4475 if (isNaN(expires)) {
4476 // UTCString || Unit
4477 expires = expires.replace(/^([0-9]+)(y|M|d|H|h|m|s)$/, function (text, num, unit) {
4478 return toCookieUTCString(toCookieUnitTime(unit, num))
4479 })
4480 } else if (/^[0-9]{11,13}$/.test(expires) || isDate(expires)) {
4481 // Date || now
4482 expires = toCookieUTCString(expires)
4483 } else {
4484 // day
4485 expires = toCookieUTCString(toCookieUnitTime('d', expires))
4486 }
4487 opts.expires = expires
4488 }
4489 arrayEach(['expires', 'path', 'domain', 'secure'], function (key) {
4490 if (!isUndefined(opts[key])) {
4491 values.push(opts[key] && key === 'secure' ? key : (key + '=' + opts[key]))
4492 }
4493 })
4494 }
4495 staticDocument.cookie = values.join('; ')
4496 })
4497 return true
4498 } else {
4499 result = {}
4500 cookies = staticDocument.cookie
4501 if (cookies) {
4502 arrayEach(cookies.split('; '), function (val) {
4503 keyIndex = val.indexOf('=')
4504 result[staticDecodeURIComponent(val.substring(0, keyIndex))] = staticDecodeURIComponent(val.substring(keyIndex + 1) || '')
4505 })
4506 }
4507 return args.length === 1 ? result[name] : result
4508 }
4509 }
4510 return false
4511}
4512
4513function hasCookieItem (value) {
4514 return includes(cookieKeys(), value)
4515}
4516
4517function getCookieItem (name) {
4518 return cookie(name)
4519}
4520
4521function setCookieItem (name, value, options) {
4522 cookie(name, value, options)
4523 return cookie
4524}
4525
4526function removeCookieItem (name, options) {
4527 cookie(name, '', assign({ expires: -1 }, setupDefaults.cookies, options))
4528}
4529
4530function cookieKeys () {
4531 return keys(cookie())
4532}
4533
4534function cookieJson () {
4535 return cookie()
4536}
4537
4538assign(cookie, {
4539 has: hasCookieItem,
4540 set: setCookieItem,
4541 setItem: setCookieItem,
4542 get: getCookieItem,
4543 getItem: getCookieItem,
4544 remove: removeCookieItem,
4545 removeItem: removeCookieItem,
4546 keys: cookieKeys,
4547 getJSON: cookieJson
4548})
4549
4550
4551
4552// 核心
4553
4554// 对象相关的方法
4555
4556// 数组相关的方法
4557
4558// 基础方法
4559
4560// 数值相关方法
4561
4562// 日期相关的方法
4563
4564// 字符串相关的方法
4565
4566// 函数相关的方法
4567
4568// 地址相关的方法
4569
4570// 浏览器相关的方法
4571
4572assign(XEUtils, {
4573 // object
4574 assign: assign,
4575 objectEach: objectEach,
4576 lastObjectEach: lastObjectEach,
4577 objectMap: objectMap,
4578 merge: merge,
4579
4580 // array
4581 uniq: uniq,
4582 union: union,
4583 sortBy: sortBy,
4584 orderBy: orderBy,
4585 shuffle: shuffle,
4586 sample: sample,
4587 some: some,
4588 every: every,
4589 slice: slice,
4590 filter: filter,
4591 find: find,
4592 findLast: findLast,
4593 findKey: findKey,
4594 includes: includes,
4595 arrayIndexOf: arrayIndexOf,
4596 arrayLastIndexOf: arrayLastIndexOf,
4597 map: map,
4598 reduce: reduce,
4599 copyWithin: copyWithin,
4600 chunk: chunk,
4601 zip: zip,
4602 unzip: unzip,
4603 zipObject: zipObject,
4604 flatten: flatten,
4605 toArray: toArray,
4606 includeArrays: includeArrays,
4607 pluck: pluck,
4608 invoke: invoke,
4609 arrayEach: arrayEach,
4610 lastArrayEach: lastArrayEach,
4611 toArrayTree: toArrayTree,
4612 toTreeArray: toTreeArray,
4613 findTree: findTree,
4614 eachTree: eachTree,
4615 mapTree: mapTree,
4616 filterTree: filterTree,
4617 searchTree: searchTree,
4618
4619 // base
4620 hasOwnProp: hasOwnProp,
4621 eqNull: eqNull,
4622 isNaN: isNumberNaN,
4623 isFinite: isNumberFinite,
4624 isUndefined: isUndefined,
4625 isArray: isArray,
4626 isFloat: isFloat,
4627 isInteger: isInteger,
4628 isFunction: isFunction,
4629 isBoolean: isBoolean,
4630 isString: isString,
4631 isNumber: isNumber,
4632 isRegExp: isRegExp,
4633 isObject: isObject,
4634 isPlainObject: isPlainObject,
4635 isDate: isDate,
4636 isError: isError,
4637 isTypeError: isTypeError,
4638 isEmpty: isEmpty,
4639 isNull: isNull,
4640 isSymbol: isSymbol,
4641 isArguments: isArguments,
4642 isElement: isElement,
4643 isDocument: isDocument,
4644 isWindow: isWindow,
4645 isFormData: isFormData,
4646 isMap: isMap,
4647 isWeakMap: isWeakMap,
4648 isSet: isSet,
4649 isWeakSet: isWeakSet,
4650 isLeapYear: isLeapYear,
4651 isMatch: isMatch,
4652 isEqual: isEqual,
4653 isEqualWith: isEqualWith,
4654 getType: getType,
4655 uniqueId: uniqueId,
4656 getSize: getSize,
4657 indexOf: indexOf,
4658 lastIndexOf: lastIndexOf,
4659 findIndexOf: findIndexOf,
4660 findLastIndexOf: findLastIndexOf,
4661 toStringJSON: toStringJSON,
4662 toJSONString: toJSONString,
4663 keys: keys,
4664 values: values,
4665 entries: entries,
4666 pick: pick,
4667 omit: omit,
4668 first: first,
4669 last: last,
4670 each: each,
4671 forOf: forOf,
4672 lastForOf: lastForOf,
4673 lastEach: lastEach,
4674 has: has,
4675 get: get,
4676 set: set,
4677 groupBy: groupBy,
4678 countBy: countBy,
4679 clone: clone,
4680 clear: clear,
4681 remove: remove,
4682 range: range,
4683 destructuring: destructuring,
4684
4685 // number
4686 random: random,
4687 min: min,
4688 max: max,
4689 commafy: commafy,
4690 round: round,
4691 ceil: ceil,
4692 floor: floor,
4693 toFixed: toFixed,
4694 toNumber: toNumber,
4695 toNumberString: toNumberString,
4696 toInteger: toInteger,
4697 add: add,
4698 subtract: subtract,
4699 multiply: multiply,
4700 divide: divide,
4701 sum: sum,
4702 mean: mean,
4703
4704 // date
4705 now: now,
4706 timestamp: timestamp,
4707 isValidDate: isValidDate,
4708 isDateSame: isDateSame,
4709 toStringDate: toStringDate,
4710 toDateString: toDateString,
4711 getWhatYear: getWhatYear,
4712 getWhatQuarter: getWhatQuarter,
4713 getWhatMonth: getWhatMonth,
4714 getWhatWeek: getWhatWeek,
4715 getWhatDay: getWhatDay,
4716 getYearDay: getYearDay,
4717 getYearWeek: getYearWeek,
4718 getMonthWeek: getMonthWeek,
4719 getDayOfYear: getDayOfYear,
4720 getDayOfMonth: getDayOfMonth,
4721 getDateDiff: getDateDiff,
4722
4723 // string
4724 trim: trim,
4725 trimLeft: trimLeft,
4726 trimRight: trimRight,
4727 escape: escape,
4728 unescape: unescape,
4729 camelCase: camelCase,
4730 kebabCase: kebabCase,
4731 repeat: repeat,
4732 padStart: padStart,
4733 padEnd: padEnd,
4734 startsWith: startsWith,
4735 endsWith: endsWith,
4736 template: template,
4737 toFormatString: toFormatString,
4738 toString: toValueString,
4739 toValueString: toValueString,
4740
4741 // function
4742 noop: noop,
4743 property: property,
4744 bind: bind,
4745 once: once,
4746 after: after,
4747 before: before,
4748 throttle: throttle,
4749 debounce: debounce,
4750 delay: delay,
4751
4752 // url
4753 unserialize: unserialize,
4754 serialize: serialize,
4755 parseUrl: parseUrl,
4756
4757 // web
4758 getBaseURL: getBaseURL,
4759 locat: locat,
4760 browse: browse,
4761 cookie: cookie
4762})
4763
4764
4765 return XEUtils
4766}))