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