jQuery源码刨析
var class2type = {};
var toString = class2type.toString; //=>Object.prototype.toString
var hasOwn = class2type.hasOwnProperty; //=>Object.prototype.hasOwnProperty
var fnToString = hasOwn.toString; //=>Function.prototype.toString
var ObjectFunctionString = fnToString.call(Object); //=>Object.toString() =>"function Object() { [native code] }"
"Boolean Number String Function Array Date RegExp Object Error Symbol".split(" ").forEach(function anonymous(item) {
class2type["[object " + item + "]"] = item.toLowerCase();
});
console.log(class2type);
// 学习参考封装
function toType(obj) {
//=>obj may be null / undefined
//=>return "null"/"undefined"
if (obj == null) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" :
typeof obj;
}
// jQuery.type = toType;
//=>是否为函数
var isFunction = function isFunction(obj) {
return typeof obj === "function" && typeof obj.nodeType !== "number";
// typeof obj.nodeType 是为了考虑老版本浏览器
};
//=>检测是否为window对象
// window.window===window
var isWindow = function isWindow(obj) {
return obj != null && obj === obj.window;
//window.window 还是返回window
};
//=>是否为纯粹的对象{}(数组和正则等都不是纯粹的对象)
var isPlainObject = function isPlainObject(obj) {
var proto, Ctor;
if (!obj || toString.call(obj) !== "[object Object]") {
return false;
}
//=>getPrototypeOf获取当前对象的原型
proto = Object.getPrototypeOf(obj);
// Objects with no prototype (`Object.create( null )`)
// 如果非null
if (!proto) {
return true;
}
// Objects with prototype are plain iff they were constructed by a global Object function
// 判断原型上是否有constructor,如果有就获取constructor,没有就返回false;并且 proto.constructor指向类本身
Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
// 判断是否既是function,也是object
return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
};
//=>是否为空对象
// 看他是否能够for in循环,for in 跳过空元素
var isEmptyObject = function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
};
//=>是否为数组或者类数组
var isArrayLike = function isArrayLike(obj) {
// !obj 代表是否传东西了,先转化为boolean,有为true,取反为false, 再取反为true
var length = !!obj && "length" in obj && obj.length,
type = toType(obj);
// window.length===0
if (isFunction(obj) || isWindow(obj)) {
return false;
}
// 运算符优先级,先算逻辑与&&,再算逻辑或||
// 其中,length-1, 代表最大的索引
return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
};
知识点强调
运算符优先级,先算逻辑与&&,再算逻辑或||
其中,length-1, 代表最大的索引
! !obj 代表是否传东西了,先转化为boolean,有为true,取反为false, 再取反为true
··老是忘记··
const prototype1={‘name’:‘OBJ’}
const object1 = Object.create(prototype1)
Object.create 创建一个空对象,他的__proto__指向prototype1
getPrototypeOf()获取当前对象的原型,这里的原型就是 prototype1
话术:
检测数据类型的常规就四种,typeof,instanceof,constructor,Object.prototype.toString.call()
我之前看过jq源码,它的原理是
对常见的数据类型大字符串用split以空格拆分,生成新的数组,然后循环数组中的每一项, 在class2type对象存放[‘Object Array’]=array 等字面量对象,然后检测是否为空,输出null或者undefined,再进行判断 是引用类型还是基本类型,如果是引用类型则进行calss2type对象比对,输出对应的属性值,否则就用typeof 检测。
之后,在项目上哪怕不用jq,我也会参考jq源码自己封装totype 方法。 -->