JavaScript常用工具类库封装
- 在我们自己去封装JavaScript组件时,难免会用到一些判断的逻辑处理,比如判断一个值是否是空对象,是否是一个纯对象,是否是一个类数组等等,每次判断都要写一堆逻辑,用起来很麻烦。下面就将常用的判断逻辑和一些常用的方法进行封装成一个公共类库,以后再使用时就可以直接拿来用了。
- 本次封装参考jquery3.5.1版本源码
- 该类库主包括如下方法的封装:
- 数据类型检测 toType
- 函数检测 isFunction
- window对象检测 isWindow
- 类数组检测 isArrayLike
- 纯对象检测 isPlainObject
- 空对象检测 isEmptyObject
- 数字类型检测 isNumeric
- 数组或对象遍历方法封装 each
- 深克隆方法封装 deepClone
- 浅克隆方法封装 shallowClone
- 深合并方法封装 deepMerge
- 浅合并方法封装 shallowMerge
最后将这些方法暴露到全局对象上,话不多说,直接上代码了
//公共方法封装
(function(){
//创建一个空对象
var class2type = {
};
//用来检测数据类型
var toString = class2type.toString;//Object.prototype.toString
//用来检测是否是私有属性
var hasOwn = class2type.hasOwnProperty;//Object.prototype.hasOwnProperty
//Object.prototype.hasOwnProperty是一个函数,那么hasOwn肯定也是一个函数,每个函数都是Function的实例
//所以hasOwn.toString 就是Function.prototype.toString
//用来把函数转换为字符串
var fnToString = hasOwn.toString;//Function.prototype.toString
//相当于Function.prototype.toString.call(Object) => 将toString中的this改为Object
//相当于Object.toString(); 注意这里不是Object.prototype.toString()
//把Object变成字符串
var ObjectFunctionString = fnToString.call(Object);"function Object(){...}"
//获取当前对象的原型链__proto__
var getProto = Object.getPrototypeOf;
//在jQuery源码中有这样一段代码:现将字符串切割为数组,然后遍历这个数组给class2type添加以object+数组中的项为名的属性,属性值则是数组中的每一项的小写形式
/*
jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function(_i, name){
class2type["[object "+name+"]"] = name.toLowerCase();
});
*/
//上面代码我们可以转换为:
//建立数据类型检测映射表
var mapType = ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error", "Symbol"];
mapType.forEach(function(name){
class2type["[object "+name+"]"] = name.toLowerCase();
});
//最后class2type将变为如下所示:
/*
class2type={
"[object Boolean]":"boolean",
"[object Number]":"number",
"[object String]":"string"
}
*/
//封装万能的数据类型检测方法
function toType(obj){
//如果obj是null或undefined(undefined == null)
//则返回字符串null或字符串undefined
if(obj == null) {
return obj + "";//obj和字符串相加结果转换为字符串
};
//基于字面量方式创建的基本数据类型,直接基于typeof检测即可(性能稍高一些)
//剩余的则基于Object.prototype.toString.call的方式来检测,把获取的值拿到映射表中进行匹配,
//得到的值是字符串对应的数据类型
return typeof obj === "object" || typeof obj === "function" ?
class2type[toString.call(obj)] || "object" : typeof obj;
}
//检测是否为函数
var isFunction = function isFunction(obj){
//元素节点[DOM对象]具备nodeType(元素、文本、注释、document 对应1、3、8、9)
//typeof obj.nodeType !== "number":防止在部分浏览器中,检测<object>元素对象结果也是"function"
return typeof obj === "function" && typeof obj.nodeType !== "number";
}
//检测是否是window对象