/*
* @Author: zhangyujie
* @Date: 2016-05-11 14:48:57
* @Last Modified by: wxq
* @Last Modified time: 2017-09-28 15:21:01
* @Email: zhangyujie3344521@163.com
* @File Path: F:\work\hyMap\src\util\baseUtil.js
* @File Name: baseUtil.js
* @Descript: 提供最基本的数据类型判断、、、可以使用underscore lodash 、、、、
* @module baseUtil
*/
var hat = require('hat');
'use strict';
/**
* baseUtil
* @private
* @module baseUtil
*/
// 用于处理merge时无法遍历Date等对象的问题
var BUILTIN_OBJECT = {
'[object Function]': 1,
'[object RegExp]': 1,
'[object Date]': 1,
'[object Error]': 1
};
var objToString = Object.prototype.toString;
var arrayProto = Array.prototype;
var nativeForEach = arrayProto.forEach;
var nativeFilter = arrayProto.filter;
var nativeSlice = arrayProto.slice;
var nativeMap = arrayProto.map;
var nativeReduce = arrayProto.reduce;
/**
* @param {object} source
* @return {object} 拷贝后的新对象
*/
function clone(source) {
if (typeof source == 'object' && source !== null) {
var result = source;
if (source instanceof Array) {
result = [];
for (var i = 0, len = source.length; i < len; i++) {
result[i] = clone(source[i]);
}
} else if (!isDom(source)) {
result = {};
for (var key in source) {
if (source.hasOwnProperty(key)) {
result[key] = clone(source[key]);
}
}
}
return result;
}
return source;
}
/**
* @param {*} target
* @param {*} source
* @param {boolean} [overwrite=false]
*/
function merge(target, source, overwrite) {
// We should escapse that source is string
// and enter for ... in ...
if (!isObject(source) || !isObject(target)) {
return overwrite ? clone(source) : target;
}
for (var key in source) {
if (source.hasOwnProperty(key)) {
var targetProp = target[key];
var sourceProp = source[key];
if (isObject(sourceProp) && isObject(targetProp) && !isArray(sourceProp) && !isArray(targetProp) && !isDom(sourceProp) && !isDom(targetProp)) {
// 如果需要递归覆盖,就递归调用merge
merge(targetProp, sourceProp, overwrite);
} else if (overwrite || !(key in target)) {
// 否则只处理overwrite为true,或者在目标对象中没有此属性的情况
// NOTE,在 target[key] 不存在的时候也是直接覆盖
target[key] = clone(source[key], true);
}
}
}
return target;
}
/**
* @param {Array} targetAndSources The first item is target, and the rests are source.
* @param {boolean} [overwrite=false]
* @return {*} target
*/
function mergeAll(targetAndSources, overwrite) {
var result = targetAndSources[0];
for (var i = 1, len = targetAndSources.length; i < len; i++) {
result = merge(result, targetAndSources[i], overwrite);
}
return result;
}
/**
* @param {*} target
* @param {*} source
*/
function extend(target, source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
return target;
}
/**
* @param {*} target
* @param {*} source
* @param {boolen} [overlay=false]
*/
function defaults(target, source, overlay) {
for (var key in source) {
if (source.hasOwnProperty(key) && (overlay ? source[key] != null : target[key] == null)) {
target[key] = source[key];
}
}
return target;
}
function createCanvas() {
return document.createElement('canvas');
}
// FIXME
var _ctx;
function getContext() {
if (!_ctx) {
// Use util.createCanvas instead of createCanvas
// because createCanvas may be overwritten in different environment
_ctx = util.createCanvas().getContext('2d');
}
return _ctx;
}
/**
* 查询数组中元素的index
*/
function indexOf(array, value) {
if (array) {
if (array.indexOf) {
return array.indexOf(value);
}
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return i;
}
}
}
return -1;
}
/**
* 构造类继承关系
*
* @param {Function} clazz 源类
* @param {Function} baseClazz 基类
*/
function inherits(clazz, baseClazz) {
var clazzPrototype = clazz.prototype;
function F() {
}
F.prototype = baseClazz.prototype;
clazz.prototype = new F();
for (var prop in clazzPrototype) {
clazz.prototype[prop] = clazzPrototype[prop];
}
clazz.prototype.constructor = clazz;
clazz.superClass = baseClazz;
}
/**
* @param {Object|Function} target
* @param {Object|Function} sorce
* @param {boolean} overlay
*/
function mixin(target, source, overlay) {
target = 'prototype' in target ? target.prototype : target;
source = 'prototype' in source ? source.prototype : source;
defaults(target, source, overlay);
}
/**
* @param {Array|TypedArray} data
*/
function isArrayLike(data) {
if (!data) {
return;
}
if (typeof data == 'string') {
return false;
}
return typeof data.length == 'number';
}
/**
* 数组或对象遍历
* @memberOf module:zrender/tool/util
* @param {Object|Array} obj
* @param {Function} cb
* @param {*} [context]
*/
function each(obj, cb, context) {
if (!(obj && cb)) {
return;
}
if (obj.forEach && obj.forEach === nativeForEach) {
obj.forEach(cb, context);
} else if (obj.length === +obj.length) {
for (var i = 0, len = obj.length; i < len; i++) {
cb.call(context, obj[i], i, obj);
}
} else {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
cb.call(context, obj[key], key, obj);
}
}
}
}
/**
* 数组映射
* @memberOf module:zrender/tool/util
* @param {Array} obj
* @param {Function} cb
* @param {*} [context]
* @return {Array}
*/
function map(obj, cb, context) {
if (!(obj && cb)) {
return;
}
if (obj.map && obj.map === nativeMap) {
return obj.map(cb, context);
} else {
var result = [];
for (var i = 0, len = obj.length; i < len; i++) {
result.push(cb.call(context, obj[i], i, obj));
}
return result;
}
}
/**
* @memberOf module:zrender/tool/util
* @param {Array} obj
* @param {Function} cb
* @param {Object} [memo]
* @param {*} [context]
* @return {Array}
*/
function reduce(obj, cb, memo, context) {
if (!(obj && cb)) {
return;
}
if (obj.reduce && obj.reduce === nativeReduce) {
return obj.reduce(cb, memo, context);
} else {
for (var i = 0, len = obj.length; i < len; i++) {
memo = cb.call(context, memo, obj[i], i, obj);
}
return memo;
}
}
/**
* 数组过滤
* @memberOf module:zrender/tool/util
* @param {Array} obj
* @param {Function} cb
* @param {*} [context]
* @return {Array}
*/
function filter(obj, cb, context) {
if (!(obj && cb)) {
return;
}
if (obj.filter && obj.filter === nativeFilter) {
return obj.filter(cb, context);
} else {
var result = [];
for (var i = 0, len = obj.length; i < len; i++) {
if (cb.call(context, obj[i], i, obj)) {
result.push(obj[i]);
}
}
return result;
}
}
/**
* 数组项查找
* @memberOf module:zrender/tool/util
* @param {Array} obj
* @param {Function} cb
* @param {*} [context]
* @return {Array}
*/
function find(obj, cb, context) {
if (!(obj && cb)) {
return;
}
for (var i = 0, len = obj.length; i < len; i++) {
if (cb.call(context, obj[i], i, obj)) {
return obj[i];
}
}
}
/**
* @memberOf module:zrender/tool/util
* @param {Function} func
* @param {*} context
* @return {Function}
*/
function bind(func, context) {
var args = nativeSlice.call(arguments, 2);
return function () {
return func.apply(context, args.concat(nativeSlice.call(arguments)));
};
}
/**
* @memberOf module:zrender/tool/util
* @param {Function} func
* @return {Function}
*/
function curry(func) {
var args = nativeSlice.call(arguments, 1);
return function () {
return func.apply(this, args.concat(nativeSlice.call(arguments)));
};
}
/**
* @memberOf module:zrender/tool/util
* @param {*} value
* @return {boolean}
*/
function isArray(value) {
return objToString.call(value) === '[object Array]';
}
/**
* @memberOf module:zrender/tool/util
* @param {*} value
* @return {boolean}
*/
function isFunction(value) {
return typeof value === 'function';
}
/**
* @memberOf module:zrender/tool/util
* @param {*} value
* @return {boolean}
*/
function isString(value) {
return objToString.call(value) === '[object String]';
}
/**
* @memberOf module:zrender/tool/util
* @param {*} value
* @return {boolean}
*/
function isObject(value) {
// Avoid a V8 JIT bug in Chrome 19-20.
// See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
var type = typeof value;
return type === 'function' || (!!value && type == 'object');
}
/**
* @memberOf module:zrender/tool/util
* @param {*} value
* @return {boolean}
*/
function isDom(value) {
return value && value.nodeType === 1 && typeof(value.nodeName) == 'string';
}
/**
* If value1 is not null, then return value1, otherwise judget rest of values.
* @param {...*} values
* @return {*} Final value
*/
function retrieve(values) {
for (var i = 0, len = arguments.length; i < len; i++) {
if (arguments[i] != null) {
return arguments[i];
}
}
}
/**
* @memberOf module:zrender/tool/util
* @param {Array} arr
* @param {number} startIndex
* @param {number} endIndex
* @return {Array}
*/
function slice() {
return Function.call.apply(nativeSlice, arguments);
}
/**
* @param {boolean} condition
* @param {string} message
*/
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
function transObject(arr) {
if (typeof arr === 'object' && !(arr instanceof Array)) {
var hasProp = false;
for (var prop in arr) {
hasProp = true;
break;
}
if (hasProp) {
return [arr];
} else {
console.info('arr is empty object');
return false;
}
}
}
function isEmpty(value) {
return (Array.isArray(value) && value.length === 0)
|| (Object.prototype.isPrototypeOf(value) && Object.keys(value).length === 0);
}
function guid(){
return hat();
}
const baseUtil = {
inherits: inherits,
mixin: mixin,
clone: clone,
merge: merge,
mergeAll: mergeAll,
extend: extend,
defaults: defaults,
getContext: getContext,
createCanvas: createCanvas,
indexOf: indexOf,
slice: slice,
find: find,
isArrayLike: isArrayLike,
each: each,
map: map,
reduce: reduce,
filter: filter,
bind: bind,
curry: curry,
isArray: isArray,
isString: isString,
isObject: isObject,
isFunction: isFunction,
isDom: isDom,
retrieve: retrieve,
assert: assert,
transObject: transObject,
isEmpty:isEmpty,
guid:guid
};
export default baseUtil;