/**
 * nothing.js
 * version: v1.0.1
 * author: dengs
 * mail: cbtak@hotmail.com
 * github: https://github.com/cbtak/nothing
 * create date: 2017-6-18
 *
 * 说明：平时积累常用的一些系统对象扩展、功能函数集
 * 在程序入口直接引入即可：
 * import './utils/nothing'
 *
 * 浏览器环境：window.nothing 或 window.$n
 * 小程序环境：wx.nothing 或 wx.$n
 * import方式：import nothing from './utils/nothing'
 *
 * 更新日志：
 * modify date: 【2018-10-13】更新代码风格（去除“;”号、“"”改为“'”、去除未使用的变量等...），以兼容ESlint校验
 * modify date: 【2018-10-15】调整部分语法，以兼容小程序
 */
const $nt = {
  /**
   * 对象拷贝
   * 示例：
   * let a = {name:'this is a'}
   * let b = _copy()
   */
  _copy: function (source) {
    let result = source instanceof Array ? [] : {}
    // 日期类型直接返回
    if (source instanceof Date) {
      return source
    }
    for (let key in source) {
      result[key] = source[key] && typeof source[key] === 'object' ? $nt._copy(source[key]) : source[key]
    }
    return result
  },
  /**
   * 验证是否空值
   * 示例：
   * let checkMsg = $nt._isNull(var) ? 'var is null' : 'var not null'
   * @param {*} val
   */
  _isNull: function (val) {
    return val === null || val === '' || val === undefined
  },
  /**
   * 验证是否非空值
   * 示例：
   * let checkMsg = _isNotNull(var) ? 'var not null' : 'var is null'
   * @param {*} val
   */
  _isNotNull: function (val) {
    return val !== null && val !== '' && val !== undefined
  },
  /**
   * 空值处理(类oracle nvl2)
   * 如果val为空，则返回val1，不为空时，则验证val2是否为空，val2不为空时返回val2，否则返回val
   * 示例：
   * let val = _ifNull(val, 'val1', 'val2')
   * @param {*} val
   * @param {*} val1
   * @param {*} val2
   */
  _ifNull: function (val, val1, val2) {
    return $nt._isNull(val) ? val1 : ($nt._isNull(val2) ? val : val2)
  },
  /**
   * 数值舍入处理（可指定小数位数和舍入模式）
   * @param {*} num       要格式化的数值
   * @param {*} precision 小数保留位数
   * @param {*} mode      舍入模式：0:Math.round  1:Math.ceil  -1:Math.floor
   */
  _toFixed: function (num, precision, mode) {
    num = Number(num)
    precision = Number(precision || 0)
    mode = [0, 1, -1]._contains(mode) ? mode : 0
    // 舍入处理
    num = $nt._caseValue(mode,
      0, (precision ? Math.round(num * Math.pow(10, precision)) * (1 / Math.pow(10, precision)) : Math.round(num)),
      1, (precision ? Math.ceil(num * Math.pow(10, precision)) * (1 / Math.pow(10, precision)) : Math.ceil(num)),
      -1, (precision ? Math.floor(num * Math.pow(10, precision)) * (1 / Math.pow(10, precision)) : Math.floor(num))
    )
    return Number(num.toFixed(precision))
  },
  /**
   * 数值格式化
   * @param {*} num       要格式化的数值
   * @param {*} params    参数对象
   * 参数对象说明：
   * num              要格式化的数值
   * params.mode      舍入模式：0:Math.round  1:Math.ceil  -1:Math.floor
   * params.thousands 是否显示千分位
   * params.precision 保留小数位数
   * 示例：
   * _numberFormat(12806.123)                                                返回：12806
   * _numberFormat(12806.123, {mode: 0, thousands: true, precision: 2})      返回：12,806.12
   * _numberFormat(12806.123, {mode: 1, precision: 2})                       返回：12806.13
   * _numberFormat(12806.126, {mode: -1, thousands: false, precision: 2})    返回：12806.12
   */
  _numberFormat: function (num, params) {
    if ($nt._isNull(num)) return num
    num = Number(num)
    params = params || {}
    // 舍入模式：0:Math.round  1:Math.ceil  -1:Math.floor
    let mode = [0, 1, -1]._contains(params.mode) ? params.mode : 0
    // 是否显示千分位
    let thousands = $nt._isNull(params.thousands) ? false : params.thousands
    // 显示小数位数
    let precision = $nt._isNull(params.precision) ? 0 : params.precision
    // 舍入处理
    num = $nt._caseValue(mode,
      0, (precision ? Math.round(num * Math.pow(10, precision)) * (1 / Math.pow(10, precision)) : Math.round(num)),
      1, (precision ? Math.ceil(num * Math.pow(10, precision)) * (1 / Math.pow(10, precision)) : Math.ceil(num)),
      -1, (precision ? Math.floor(num * Math.pow(10, precision)) * (1 / Math.pow(10, precision)) : Math.floor(num))
    )
    // 按小数点分割为数组
    let tempArr = num.toString().split('.')
    // 小数点后的数值处理
    tempArr[1] = tempArr[1] || ''
    if (precision) {
      // 截去多余位数
      tempArr[1] = tempArr[1].substr(0, precision)
      // 小数位数处理（不够位数补0）
      tempArr[1] = '.' + tempArr[1] + new Array(precision - tempArr[1].length + 1).join('0')
    }
    // 根据是否显示千分位格式化返回
    // return (thousands ? Number(tempArr[0]).toLocaleString() : tempArr[0]) + (precision ? tempArr[1] : '')
    return (thousands ? Number(tempArr[0]).replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') : tempArr[0]) + (precision ? tempArr[1] : '')
  },
  /**
   * 获取地址栏参数
   * 示例：
   * let userid = _getParam('userid')
   * @param {*} key
   */
  _getParam: function (key) {
    let reg = new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i')
    let r = window.location.search.substr(1).match(reg)
    return r ? unescape(r[2]) : null
  },
  /**
   * 匹配函数，类似 oracle 中的 decode
   * 说明：取第一个参数与后续偶数位置的参数进行比较，如匹配则返回当前比较的偶数位置下一个参数作为结果
   * 如未找到匹配项目，并且参数个数大于3而且为偶数，则取最后一个参数作为默认值返回
   * 注：参数为动态参数，参数个数最少为3，否则无意义
   *     偶数位置被比较的参数可以为数组
   *     比较使用 === 及 indexOf() 严格匹配值
   * 示例：
   * 1. _caseValue('A', 'A', value1, 'B', value2) // 返回 value1
   * 2. _caseValue('A', 'B', value1, 'A', value2) // 返回 value2
   * 3. _caseValue('A', 'B', value1, 'C', value2, defaultValue) // 返回 defaultValue
   * 4. _caseValue('A', 'B', value1, ['A','C'], value2, defaultValue) // 返回 value2
   *
   * @param {*} args 动态参数
   */
  _caseValue: function (...args) {
    if (!args || args.length < 3) {
      return null
    }
    let caseKey = args[0]
    for (let i = 1; i < args.length; i++) {
      if ((i % 2) && i !== args.length - 1 && (args[i] === caseKey || (Array.isArray(args[i]) && args[i].indexOf(caseKey) !== -1))) {
        return args[i + 1] === undefined ? null : args[i + 1]
      }
    }
    return args.length > 3 && !(args.length % 2) ? args[args.length - 1] : null
  },
  /**
   * 构建树型数据
   * @param {*} params
   */
  _buildTree: function (params) {
    if (!params.treeArray) {
      params.treeArray = []
    }
    if (params.element === null) {
      params.elementArray.forEach(function (item, index, array) {
        if (item[params.parentKey] === params.rootParentValue) {
          params.treeArray[params.treeArray.length] = item
        } else {
          $nt._buildTree({
            element: item,
            elementArray: params.elementArray,
            treeArray: params.treeArray,
            elementKey: params.elementKey,
            parentKey: params.parentKey,
            childKey: params.childKey,
            rootParentValue: params.rootParentValue
          })
        }
      })
    } else {
      params.elementArray.forEach(function (item, index, array) {
        if (params.element[params.parentKey] === item[params.elementKey]) {
          item[params.childKey] = item[params.childKey] || []
          item[params.childKey][item[params.childKey].length] = params.element
          // params.element.parentElement = item
        }
      })
    }
  },
  /**
   * 验证手机号码
   * @param {*} mobile
   */
  _validateMobile: function (mobile) {
    return /^[1][3,4,5,7,8][0-9]{9}$/.test(mobile)
  },
  /**
   * 数值型验证
   * @param {*} val
   */
  _validateNumber: function (val) {
    return /^\d+(\.\d+)?$/.test(val)
  },
  /**
   * 系统对象功能扩展
   */
  _extend: function () {
    /**
     * 字符串清除左右空格扩展
     * 示例：
     * let str = ' this is string '
     * let trimStr = str._trim()
     */
    String.prototype._trim = function () {
      return this.replace(/(^\s*)|(\s*$)/g, '')
    }
    /**
     * 字符串替换所有
     * 示例：
     * let str = ' this is string '
     * let replaceStr = str.replaceAll('i','')
     */
    String.prototype.replaceAll = function (s1, s2) {
      return this.replace(new RegExp(s1, 'gm'), s2)
    }
    /**
     * 字符串包含检查
     * @param {*} str
     */
    String.prototype._contains = function (str) {
      return this.indexOf(str) !== -1
    }
    /**
     * 字符串转byte数组
     */
    String.prototype._toByte = function () {
      let bytes = []
      let len
      let c
      len = this.length
      for (let i = 0; i < len; i++) {
        c = this.charCodeAt(i)
        if (c >= 0x010000 && c <= 0x10FFFF) {
          bytes.push(((c >> 18) & 0x07) | 0xF0)
          bytes.push(((c >> 12) & 0x3F) | 0x80)
          bytes.push(((c >> 6) & 0x3F) | 0x80)
          bytes.push((c & 0x3F) | 0x80)
        } else if (c >= 0x000800 && c <= 0x00FFFF) {
          bytes.push(((c >> 12) & 0x0F) | 0xE0)
          bytes.push(((c >> 6) & 0x3F) | 0x80)
          bytes.push((c & 0x3F) | 0x80)
        } else if (c >= 0x000080 && c <= 0x0007FF) {
          bytes.push(((c >> 6) & 0x1F) | 0xC0)
          bytes.push((c & 0x3F) | 0x80)
        } else {
          bytes.push(c & 0xFF)
        }
      }
      return bytes
    }
    /**
     * byte数组转换字符串
     * @param {*} bytes
     */
    String._fromByte = function (bytes) {
      if (!Array.isArray(bytes)) return null
      let str = ''
      let _arr = bytes
      for (let i = 0; i < _arr.length; i++) {
        let one = _arr[i].toString(2)
        let v = one.match(/^1+?(?=0)/)
        if (v && one.length === 8) {
          let bytesLength = v[0].length
          let store = _arr[i].toString(2).slice(7 - bytesLength)
          for (let st = 1; st < bytesLength; st++) {
            store += _arr[st + i].toString(2).slice(2)
          }
          str += String.fromCharCode(parseInt(store, 2))
          i += bytesLength - 1
        } else {
          str += String.fromCharCode(_arr[i])
        }
      }
      return str
    }
    /**
     * Number对象扩展数值格式化
     * @param {*} params 参数对象
     *
     * 参数对象说明：
     * params.mode      舍入模式：0:Math.round  1:Math.ceil  -1:Math.floor
     * params.thousands 是否显示千分位
     * params.precision 保留小数位数
     * 示例：
     * Number(12806.123)._format()                                              返回：12806
     * Number(12806.123)._format({mode: 0, thousands: true, precision: 2})      返回：12,806.12
     * Number(12806.123)._format({mode: 1, precision: 2})                       返回：12806.13
     * Number(12806.126)._format({mode: -1, thousands: false, precision: 2})    返回：12806.12
     */
    Number.prototype._format = function (params) {
      return $nt._numberFormat(this, params)
    }
    /**
   * 数值舍入处理（可指定小数位数和舍入模式）
   * @param {*} precision 小数保留位数
   * @param {*} mode      舍入模式：0:Math.round  1:Math.ceil  -1:Math.floor
   */
    Number.prototype._toFixed = function (precision, mode) {
      return $nt._toFixed(this, precision, mode)
    }
    /**
     * 日期格式化
     * @param {*} fmt 日期格式
     */
    Date.prototype._format = function (fmt) {
      if (fmt) {
        fmt = fmt.replace('H', 'h').replace('H', 'h')
      }
      let o = {
        'M+': this.getMonth() + 1, // 月份
        'd+': this.getDate(), // 日
        'h+': this.getHours(), // 小时
        'm+': this.getMinutes(), // 分
        's+': this.getSeconds(), // 秒
        'q+': Math.floor((this.getMonth() + 3) / 3), // 季度
        'S': this.getMilliseconds() // 毫秒
      }
      if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
      for (let k in o) {
        if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
      }
      return fmt
    }
    /**
     * 日期计算
     * @param {*} interval
     * @param {*} number
     */
    Date.prototype._add = function (interval, number) {
      // let cloneDate = JSON.parse(JSON.stringify({date : this}))
      // let d = new Date(cloneDate.date)
      let d = new Date(this)
      let k = {
        'y': 'FullYear',
        'q': 'Month',
        'm': 'Month',
        'w': 'Date',
        'd': 'Date',
        'h': 'Hours',
        'n': 'Minutes',
        's': 'Seconds',
        'ms': 'MilliSeconds'
      }
      let n = {
        'q': 3,
        'w': 7
      }
      interval = (interval || '').toLowerCase()
      d['set' + k[interval]](d['get' + k[interval]]() + ((n[interval] || 1) * number))
      return d
    }
    /**
     * 日期差异
     * @param {*} interval
     * @param {*} objDate2
     */
    Date.prototype._diff = function (interval, diffDate) {
      let d = this
      let i = {}
      let t = d.getTime()
      let t2 = diffDate.getTime()
      i['y'] = diffDate.getFullYear() - d.getFullYear()
      i['q'] = i['y'] * 4 + Math.floor(diffDate.getMonth() / 4) - Math.floor(d.getMonth() / 4)
      i['m'] = i['y'] * 12 + diffDate.getMonth() - d.getMonth()
      i['ms'] = diffDate.getTime() - d.getTime()
      i['w'] = Math.floor((t2 + 345600000) / (604800000)) - Math.floor((t + 345600000) / (604800000))
      i['d'] = Math.floor(t2 / 86400000) - Math.floor(t / 86400000)
      i['h'] = Math.floor(t2 / 3600000) - Math.floor(t / 3600000)
      i['n'] = Math.floor(t2 / 60000) - Math.floor(t / 60000)
      i['s'] = Math.floor(t2 / 1000) - Math.floor(t / 1000)
      return i[interval]
    }
    /**
     * 数组为空校验
     * @param {*} array
     */
    Array._isEmpty = function (array) {
      return !array || !array.length
    }
    /**
     * 数组不为空校验
     * @param {*} array
     */
    Array._isNotEmpty = function (array) {
      return array && array.length
    }
    /**
     * 数组对象扩展-为空校验
     */
    Array.prototype._isEmpty = function () {
      return Array._isEmpty(this)
    }
    /**
     * 数组对象扩展-不为空校验
     */
    Array.prototype._isNotEmpty = function () {
      return Array._isNotEmpty(this)
    }
    /**
     * 数组是否包含元素
     * @param {*} array
     * @param {*} element
     */
    Array._contains = function (array, element) {
      return !array && array.indexOf(element) !== -1
    }
    /**
     * 数组对象扩展-是否包含元素
     * @param {*} element
     */
    Array.prototype._contains = function (element) {
      return this.indexOf(element) !== -1
    }
    /**
     * 数组对象扩展-添加元素（可指定位置）
     * @param {*} item  元素
     * @param {*} index 添加位置(可选，为空时添加到数组末尾)
     */
    Array.prototype._add = function (item, index) {
      if ($nt._isNotNull(index)) {
        this.splice(index, 0, item)
      } else {
        this.push(item)
      }
    }
    /**
     * 数组对象扩展-批量添加元素（可指定位置）
     * @param {*} items  元素数组
     * @param {*} index 添加位置(可选，为空时添加到数组末尾)
     */
    Array.prototype._addAll = function (items, index) {
      this.splice($nt._ifNull(index, this.length), 0, ...items)
    }
    /**
     * 数组对象扩展-添加元素到数据第一个位置
     * @param {*} item 元素
     */
    Array.prototype._addFirst = function (item) {
      this._add(item, 0)
    }
    /**
     * 数组对象扩展-获取数组第一个元素
     */
    Array.prototype._first = function () {
      return this[0]
    }
    /**
     * 数组对象扩展-获取数组最后一个元素
     */
    Array.prototype._last = function () {
      return this[this.length - 1]
    }
    /**
     * 数组对象扩展-汇总数组元素（数值型有效）
     * @param {*} beginIndex    开始位置
     * @param {*} endIndex      结束位置
     */
    Array.prototype._sum = function (beginIndex, endIndex) {
      let total = 0
      beginIndex = $nt._isNull(beginIndex) ? 0 : beginIndex
      endIndex = $nt._isNull(endIndex) ? this.length : endIndex
      for (let i = 0; i < this.length; i++) {
        if (i >= beginIndex && i < endIndex) {
          total += Number(this[i] || 0)
        }
      }
      return total
    }
    /**
     * 数组对象扩展-汇总数组元素对象指定属性（数值型有效）
     * @param {*} attribute     属性
     * @param {*} beginIndex    开始位置
     * @param {*} endIndex      结束位置
     */
    Array.prototype._sumAttr = Array.prototype._sumObjectAttr = function (attribute, beginIndex, endIndex) {
      let total = 0
      beginIndex = $nt._isNull(beginIndex) ? 0 : beginIndex
      endIndex = $nt._isNull(endIndex) ? this.length : endIndex
      for (let i = 0; i < this.length; i++) {
        if (i >= beginIndex && i < endIndex) {
          total += Number(this[i][attribute] || 0)
        }
      }
      return total
    }
    /**
     * 数组对象扩展-移除元素
     * @param {*} element
     */
    // Array.prototype._remove = function (element) {
    //   this.splice(this.findIndex(item => item === element), 1)
    //   return this
    // }
    Object.defineProperty(Array.prototype, '_remove', {
      value: function (element) {
        return this.splice(this.findIndex(item => item === element), 1)
      }
    })
    /**
     * 数组对象扩展-批量获取属性值
     * 示例：
     * let jsonArray = [{a:1,b:1},{a:2,b:2},{a:3,b:3},{a:4,b:4},{a:5,b:5}]
     * let valueArray = jsonArray._getObjectAttr('a') 或 _getObjectAttr('a')
     * let valueArray = jsonArray._getObjectAttr('a', 1, 3) 或 _getObjectAttr('a', 1, 3)
     * @param {*} attribute
     * @param {*} beginIndex
     * @param {*} endIndex
     */
    Array.prototype._getAttr = Array.prototype._getObjectAttr = Array.prototype._getObjectAttribute = function (attribute, beginIndex, endIndex) {
      let valArray = []
      beginIndex = $nt._isNull(beginIndex) ? 0 : beginIndex
      endIndex = $nt._isNull(endIndex) ? this.length : endIndex
      for (let i = 0; i < this.length; i++) {
        if (i >= beginIndex && i < endIndex) {
          let val = (typeof this[i][attribute] === 'object' && !(this[i][attribute] instanceof Date) ? $nt._copy(this[i][attribute]) : this[i][attribute]) || null
          valArray.push(val)
        }
      }
      return valArray
    }
    /**
     * 数组对象扩展-批量设置属性值
     * 示例：
     * let jsonArray = [{a:1,b:1},{a:2,b:2},{a:3,b:3},{a:4,b:4},{a:5,b:5}]
     * jsonArray._setObjectAttr('c', '10') 或 _setObjectAttribute('c', '10')
     * jsonArray._setObjectAttr('c', '10', 1, 3) 或 _setObjectAttribute('c', '10', 1, 3)
     * @param {*} attribute     属性
     * @param {*} beginIndex    开始位置
     * @param {*} endIndex      结束位置
     */
    Array.prototype._setObjectAttr = Array.prototype._setObjectAttribute = function (attribute, value, beginIndex, endIndex) {
      beginIndex = $nt._isNull(beginIndex) ? 0 : beginIndex
      endIndex = $nt._isNull(endIndex) ? this.length : endIndex
      for (let i = 0; i < this.length; i++) {
        if (i >= beginIndex && i < endIndex && typeof this[i] === 'object' && !(this[i] instanceof Date)) {
          this[i][attribute] = value
        }
      }
      return this
    }
    /**
     * 数组对象扩展-批量设置对象本身属性到指定属性
     * @param {*} sourceAttribute   源属性
     * @param {*} targetAttribute   目标属性
     * @param {*} beginIndex        开始位置
     * @param {*} endIndex          结束位置
     */
    Array.prototype._setObjectAttrToAttr = Array.prototype._setObjectAttributeToAttribute = function (sourceAttribute, targetAttribute, beginIndex, endIndex) {
      beginIndex = $nt._isNull(beginIndex) ? 0 : beginIndex
      endIndex = $nt._isNull(endIndex) ? this.length : endIndex
      for (let i = 0; i < this.length; i++) {
        if (i >= beginIndex && i < endIndex && typeof this[i] === 'object' && !(this[i] instanceof Date)) {
          this[i][targetAttribute] = this[i][sourceAttribute]
        }
      }
      return this
    }
    /**
     * JSON.__proto__._serializeArray 目前与VUE.JS不兼容，使用 JSON._serializeArray 代替
     */
    JSON._serializeArray = function (json) {
      let _arr = []
      let _toArray = function (json, jsonArray, prefix) {
        for (let key in json) {
          if (typeof json[key] === 'function') {
            continue
          }
          let newKey = (prefix ? prefix + '.' : '') + key
          if (typeof json[key] === 'object' && !(json[key] instanceof Array)) {
            _toArray(json[key], jsonArray, newKey)
          } else {
            jsonArray[jsonArray.length] = {
              name: newKey,
              value: json[key]
            }
          }
        }
      }
      _toArray(json, _arr)
      return _arr
    }
    /**
     * JSON.__proto__._propertyLength 目前与VUE.JS不兼容，使用 JSON._propertyLength 代替
     */
    JSON._propertyLength = function (json) {
      let length = 0
      let keys = []
      for (let key in json) {
        length++
        keys.push(key)
      }
      return length
    }
    /**
     * 清空JSON对象
     * @param {*} json
     */
    JSON._clear = function (json) {
      for (let key in json) {
        delete json[key]
      }
    }
    /**
     * 移除JSON对象指定属性
     * @param {*} json
     * @param {*} key
     */
    JSON._removeKey = function (json, key) {
      delete json[key]
    }
    /**
     * 传入JSON数据对象，构建新JSON对象（attrs指定动态属性集）
     * @param {*} json
     * @param {*} attrs
     */
    JSON._new = function (json, ...attrs) {
      let newJSON = {}
      if (json && attrs && attrs.length) {
        let tempJSON = $nt._copy(json)
        for (let i = 0; i < attrs.length; i++) {
          if (attrs[i]._contains('.')) {
            let childAttrs = attrs[i].split('.')
            let childJSON = newJSON[childAttrs[0]] = newJSON[childAttrs[0]] || {}
            let tempChildJSON = tempJSON[childAttrs[0]] || {}
            for (let ii = 1; ii < childAttrs.length; ii++) {
              if (ii === childAttrs.length - 1) {
                childJSON[childAttrs[ii]] =  $nt._isNotNull(tempChildJSON) ? tempChildJSON[childAttrs[ii]] : null
              } else {
                childJSON = childJSON[childAttrs[ii]] = childJSON[childAttrs[ii]] || {}
                tempChildJSON = $nt._isNotNull(tempChildJSON) ? tempChildJSON[childAttrs[ii]] : null
              }
            }
          } else {
            newJSON[attrs[i]] = tempJSON[attrs[i]]
          }
        }
      }
      return newJSON
    }
    /**
     * Storage 对象扩展
     */
    if (window && window.Storage) {
      /**
       * 扩展 Storage 增加setJSON方法
       * @param {*} key
       * @param {*} value
       */
      window.Storage.prototype.setJSON = function (key, value) {
        this.setItem(key, $nt._isNotNull(value) ? JSON.stringify(value) : value)
      }
      /**
       * 扩展 Storage 增加getJSON方法
       * @param {Object} key
       */
      window.Storage.prototype.getJSON = function (key) {
        let value = this.getItem(key)
        return $nt._isNotNull(value) ? JSON.parse(value) : null
      }
    }
  }
}
/**
 * 执行系统对象功能扩展
 */
$nt._extend()

if (typeof wx !== 'undefined' && !wx.miniProgram) {
  // 小程序环境
  wx.nothing = wx.$n = $nt
} else {
  window.nothing = window.$n = $nt
  Object.assign(window, $nt)
}

export default $nt
