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     '&': '&amp;',
3269     '<': '&lt;',
3270     '>': '&gt;',
3271     '"': '&quot;',
3272     "'": '&#x27;',
3273     '`': '&#x60;'
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 }))

 

posted @ 2019-04-15 23:22  Honor_Chen  阅读(405)  评论(0编辑  收藏  举报