var oproto = Object.prototype var aproto = Array.prototype var serialize = oproto.toString var isFunction = function (fn) { return serialize.call(fn) === '[object Function]' } var isArray = Array.isArray || /* istanbul ignore next */ function (ary) { return serialize.call(ary) === '[object Array]' } var isPlainObject = function (obj) { return serialize.call(obj) === '[object Object]' && Object.getPrototypeOf(obj) === oproto } var i = 0 var utils = { uid: function () { return ++i }, noop: function () {}, bind: function (fn, context) { return function () { return fn.apply(context, arguments) } }, preventEvent: function (evt) { evt.preventDefault() }, stop: function (evt) { evt.preventDefault() evt.stopPropagation() }, nextTick: function (fn, context) { setTimeout(utils.bind(fn, context), 0) }, toArray: function (ary, start, end) { if (start === undefined) start = 0 if (end === undefined) end = ary.length return aproto.slice.call(ary, start, end) }, isPlainObject: isPlainObject, isFunction: isFunction, isArray: isArray, isObject: function (obj) { return Object(obj) === obj }, isString: function (s) { return typeof s === 'string' }, isUndefined: function (a) { return typeof a === 'undefined' }, isDefined: function (a) { return typeof a !== 'undefined' }, each: function (ary, func, context) { if (utils.isDefined(ary.length)) { for (var i = 0, len = ary.length; i < len; i++) { if (func.call(context, ary[i], i, ary) === false) { break } } } else { for (var k in ary) { if (func.call(context, ary[k], k, ary) === false) { break } } } }, /** * If option is a function, evaluate it with given params * @param {*} data * @param {...} args arguments of a callback * @returns {*} */ evalOpts: function (data, args) { if (utils.isFunction(data)) { // `arguments` is an object, not array, in FF, so: args = utils.toArray(arguments) data = data.apply(null, args.slice(1)) } return data }, extend: function () { var options var name var src var copy var copyIsArray var clone var target = arguments[0] || {} var i = 1 var length = arguments.length var force = false // 如果第一个参数为布尔,判定是否深拷贝 if (typeof target === 'boolean') { force = target target = arguments[1] || {} i++ } // 确保接受方为一个复杂的数据类型 if (typeof target !== 'object' && !isFunction(target)) { target = {} } // 如果只有一个参数,那么新成员添加于 extend 所在的对象上 if (i === length) { target = this i-- } for (; i < length; i++) { // 只处理非空参数 if ((options = arguments[i]) != null) { for (name in options) { src = target[name] copy = options[name] // 防止环引用 if (target === copy) { continue } if (force && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { if (copyIsArray) { copyIsArray = false clone = src && isArray(src) ? src : [] } else { clone = src && isPlainObject(src) ? src : {} } target[name] = utils.extend(force, clone, copy) } else if (copy !== undefined) { target[name] = copy } } } } return target }, formatSize: function (size) { if (size < 1024) { return size.toFixed(0) + ' bytes' } else if (size < 1024 * 1024) { return (size / 1024.0).toFixed(0) + ' KB' } else if (size < 1024 * 1024 * 1024) { return (size / 1024.0 / 1024.0).toFixed(1) + ' MB' } else { return (size / 1024.0 / 1024.0 / 1024.0).toFixed(1) + ' GB' } }, defineNonEnumerable: function (target, key, value) { Object.defineProperty(target, key, { enumerable: false, configurable: true, writable: true, value: value }) } } module.exports = utils