(function () {
"use strict";
var getProto = Object.getPrototypeOf,
class2type = {},
toString = class2type.toString,
hasOwn = class2type.hasOwnProperty,
fnToString = hasOwn.toString,
ObjectFunctionString = fnToString.call(Object);
### 专门进行数据类型检测的办法
var toType = function toType(obj) {
if (obj == null) return obj + "";
if (typeof obj !== "object" && typeof obj !== "function") return typeof obj;
var reg = /^\[object ([0-9A-Za-z]+)\]$/,
value = reg.exec(toString.call(obj))[1] || "object";
return value.toLowerCase();
};
// 检测是否为一个函数
var isFunction = function isFunction(obj) {
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
// 检测是否为一个window对象
var isWindow = function isWindow(obj) {
return obj != null && obj === obj.window;
};
// 检测是否为数组或者类数组
var isArrayLike = function isArrayLike(obj) {
var length = !!obj && "length" in obj && obj.length,
type = toType(obj);
if (isFunction(obj) || isWindow(obj)) return false;
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && (length - 1) in obj;
};
### 检测是否为纯粹的对象:直属类是Object 或者 obj.__proto__===Object.prototype(数组/正则等都不是)
var isPlainObject = function isPlainObject(obj) {
var proto, Ctor;
if (!obj || toType(obj) !== "object") return false;
proto = getProto(obj);
if (!proto) return true;
Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
};
// 检测是否为空对象
var isEmptyObject = function isEmptyObject(obj) {
if (obj == null) return false;
var keys = Object.keys(obj);
if (typeof Symbol !== "undefined") {
keys = keys.concat(Object.getOwnPropertySymbols(obj));
}
return keys.length === 0;
};
### 检测是否为数字
var isNumeric = function isNumeric(obj) {
var type = toType(obj);
return (type === "number" || type === "string") && !isNaN(+obj);
};
### 函数防抖
var debounce = function debounce(func, wait, immediate) {
if (typeof func !== "function") throw new TypeError('func must be required and be an function!');
if (typeof wait === "boolean") {
immediate = wait;
wait = 300;
}
if (typeof wait !== "number") wait = 300;
if (typeof immediate !== "boolean") immediate = false;
var timer = null,
result;
return function proxy() {
var runNow = !timer && immediate,
params = [].slice.call(arguments),
self = this;
if (timer) clearTimeout(timer);
timer = setTimeout(function () {
if (timer) {
clearTimeout(timer);
timer = null;
};
!immediate ? result = func.apply(self, params) : null;
}, wait);
runNow ? result = func.apply(self, params) : null;
return result;
};
};
### 函数节流
var throttle = function throttle(func, wait) {
if (typeof func !== "function") throw new TypeError('func must be required and be an function!');
if (typeof wait !== "number") wait = 300;
var timer = null,
previous = 0,
result;
return function proxy() {
var now = +new Date(),
remaining = wait - (now - previous),
self = this,
params = [].slice.call(arguments);
if (remaining <= 0) {
if (timer) {
clearTimeout(timer);
timer = null;
}
result = func.apply(self, params);
previous = +new Date();
} else if (!timer) {
timer = setTimeout(function () {
if (timer) {
clearTimeout(timer);
timer = null;
}
result = func.apply(self, params);
previous = +new Date();
}, remaining);
}
return result;
};
};
// 遍历数组/类数组/对象「支持回调函数返回值处理:返回false则结束循环,这是内置方法forEach/map不具备的」
var each = function each(obj, callback) {
typeof callback !== "function" ? callback = Function.prototype : null;
var length,
i = 0,
keys = [];
if (isArrayLike(obj)) {
// 数组或者类数组
length = obj.length;
for (; i < length; i++) {
var item = obj[i],
result = callback.call(item, item, i);
if (result === false) break;
}
} else {
// 对象
keys = Object.keys(obj);
typeof Symbol !== "undefined" ? keys = keys.concat(Object.getOwnPropertySymbols(obj)) : null;
i = 0;
length = keys.length;
for (; i < length; i++) {
var key = keys[i],
value = obj[key];
if (callback.call(value, value, key) === false) break;
}
}
return obj;
};
### 实现数组和对象深/浅合并
var merge = function merge() {
var options,
target = arguments[0] || {},
i = 1,
length = arguments.length,
treated = arguments[length - 1],
deep = false;
if (typeof target === "boolean") {
deep = target;
target = arguments[i] || {};
i++;
}
if (Array.isArray(treated) && treated.treated) {
// 传递了记录已经处理过的内容的集合
// 后期循环的时候少循环处理一项
length--;
} else {
// 没传递,最后传递的这个值,不是用来存储处理过的内容,而是进行合并比较的
treated = [];
treated.treated = true;
}
if (typeof target !== "object" && !isFunction(target)) target = {};
for (; i < length; i++) {
options = arguments[i];
if (options == null) continue;
### 放置死递归处理的操作
if (treated.indexOf(options) > -1) return options;
treated.push(options);
each(options, function (copy, name) {
var copyIsArray = Array.isArray(copy),
copyIsObject = isPlainObject(copy),
src = target[name],
clone = src;
if (deep && copy && (copyIsArray || copyIsObject)) {
if (copyIsArray && !Array.isArray(src)) clone = [];
if (copyIsObject && !isPlainObject(src)) clone = {};
target[name] = merge(deep, clone, copy, treated);
} else if (copy !== undefined) {
target[name] = copy;
}
});
}
return target;
};
### 实现数组和对象深/浅拷贝
var clone = function clone() {
var target = arguments[0],
deep = false,
type,
isArray,
isObject,
result,
Ctor,
treated = arguments[arguments.length - 1];
!Array.isArray(treated) || !treated.treated ? (treated = [], treated.treated = true) : null;
if (typeof target === "boolean") {
deep = target;
target = arguments[1];
}
// 防止死递归的处理
if (treated.indexOf(target) > -1) return target;
treated.push(target);
// 校验类型
type = toType(target);
isArray = Array.isArray(target);
isObject = isPlainObject(target);
// 特殊值的拷贝
if (target == null) return target;
Ctor = target.constructor;
if (/^(regexp|date)$/i.test(type)) return new Ctor(target);
if (/^(error)$/i.test(type)) return new Ctor(target.message);
if (/^(function|generatorfunction)$/i.test(type)) {
return function proxy() {
var args = Array.from(arguments);
return target.apply(this, args);
};
}
if (!isArray && !isObject) return target;
// 如果是数组/对象,我们依次迭代赋值给新的数组/对象
result = new Ctor();
each(target, function (copy, name) {
if (deep) {
// 深拷贝
result[name] = clone(deep, copy, treated);
return;
}
// 浅拷贝
result[name] = copy;
});
return result;
};
## 获取_URL地址参数并转换为对象
var getQueryParams = function getQueryParams(){
const result = {}
const queryString = window.location.search;
const reg = /[?&][^?&] += [^?&]/g;
const found = queryString.match(reg);
if(found){
found.forEach(item=>{
let temp = item.substring(1).solit("=");
let key = temp[0];
let value = temp[1]
result[key] = value;
})
}
return result;
}
### _storage的存取
const saveItem = function saveItem(key,value){
let storage = window.localStorage.getItem(namespace);
if(!storage){
storage = {}
}else{
storage = JSON.parse(storage)
}
storage[key] = value;
window.localStorage.setItem(namespace,JSON.stringlfy(storage))
}
const loadItem = function loadItem(key,value){
storage = window.localStorage.getItem(namespace);
if(!storage)return def;
storage = JSON.parse(storage)
let result = storage[key];
return result || def;
}
export default {
saveItem,loadItem
}
### 实现洗牌函数
const getRandomNumber = function getRandomNumber(min,max){
// min max之间的一个数字
// [0,1] => [min,max]
return Math.floor(Math.random() * (max - min +1) + min)
}
const shuffle = function shuffle(arr){
let _arr = arr.slice();
for(let i=0; i<_arr.length;i++){
const j = getRandomNumber(0,i);
const temp = _arr[i];
_arr[i] = _arr[j];
_arr[j] = temp
}
return _arr;
}
export default {
shuffle,getRandomNumber
}
### 自定义添加类名
const addClass = function addClass(){
//1.判断添加的类名是否已经存在if(_hasClass(el,className))return
// 2.真正的去添加类名
let newClass = el.className.split('');
newClass.push(className)
el.className = newClass.join('');
}
const hasClass = function hasClass(el,className){
const reg= new RegExp('(^|\\s)' + className + '(\\s|$)');
return reg.test(el.calssName);
}
/* 暴露API */
var utils = {
toType: toType,
isFunction: isFunction,
isWindow: isWindow,
isArrayLike: isArrayLike,
isPlainObject: isPlainObject,
isEmptyObject: isEmptyObject,
isNumeric: isNumeric,
debounce: debounce,
throttle: throttle,
each: each,
merge: merge,
clone: clone,
addClass:addClass,
hasClass:hasClass,
getRandomNumber:getRandomNumber,
shuffle:shuffle,
saveItem:saveItem,
loadItem:loadItem,
};
// 转移_的使用权
var $_ = window._;
utils.noConflict = function noConflict() {
if (window._ === utils) {
window._ = $_;
}
return utils;
};
if (typeof window !== "undefined") {
window._ = window.$utils = utils;
}
if (typeof module === "object" && typeof module.exports === "object") {
module.exports = utils;
}
})();
版权归属:
@小佑前端
许可协议:
本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
评论区