jQuery源码分析(二)之数据类型检测

源码分析:

//开启严格模式
"use strict";	
	//定义空对象
    var class2type = {
    
    };
    //获取Object的原型
    var getProto = Object.getPrototypeOf;
    //获取Object原型上的toString方法,所有对象中的toString方法都是转换字符串的,
    //只有Object原型上的toString方法是用来做数据类型检测的(可以看我数据类型检测那篇文章)
    var toString = class2type.toString; //->Object.prototype.toString
    //获取Object原型上的hasOwnProperty方法,检测某个属性或方法是不是某个对象私有的
    var hasOwn = class2type.hasOwnProperty; //->Object.prototype.hasOwnProperty
    //将Object原型上的hasOwnProperty方法转化为字符串
    //获取到的是Function.prototype.toString方法,hasOwn也是一个方法
    var fnToString = hasOwn.toString; //->Function.prototype.toString
    //改变Function.prototype.toString中的this指向为Object
    var ObjectFunctionString = fnToString.call(Object); //->Object.toString()  //->"function Object() { [native code] }"
  • isFunction检测是否为函数
var isFunction = function isFunction(obj) {
    
    
	 // In some browsers, typeof returns "function" for HTML <object> elements
        // (i.e., `typeof document.createElement( "object" ) === "function"`).
     //在某些浏览器中,typeof HTML<object>元素返回的“function”  不常用的情况
    return typeof obj === "function" && typeof obj.nodeType !== "number";
  };
  • isWindow检测是否为window对象
	//利用window对象中有个属性window=window来检测
	//window.window == window 返回结果为true
  var isWindow = function isWindow(obj) {
    
    
    return obj != null && obj === obj.window;
  };
  • 建立数据类型检测引用表

好处:以后的方法不需要修改, 如果想增加或删除某种数据类型检测只需要维护引用表即可。

	//$.each( object, callback ) jQuery中each的用法
	//"Boolean Number String Function Array Date RegExp Object Error Symbol".split(" ")返回一个数组;_i:索引;name:值
	//class2type["[object " + Number+ "]"] = Number.toLowerCase(); class2type["[object Number]"]:number。
	//name.toLowerCase(); 将name转换为小写
 jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),
      function (_i, name) {
    
    
        class2type["[object " + name + "]"] = name.toLowerCase();
      });

在这里插入图片描述

  • toType数据类型检测
var toType = function toType(obj) {
    
    
	//obj == null/undefined 直接返回“null”/"undefined"
	//1.首先排除null 和 undefined类型
    if (obj == null) {
    
    
      return obj + "";
    }
	//2.判断obj为原始值类型直接走typeof obj简单方便
	//3.obj 为object 或 function类型时走class2type.toString.call(obj) 检测数据类型,
	//使用Object.prototype.toString.call(obj)检测数据类型时返回值都是“[object ?]”
	//4.把[object Number]当做属性值去classtype中出对应的值返回 “number”,找不到则返回“object”
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[toString.call(obj)] || "object" :
        typeof obj;
  }
  • isArrayLike检测是否为数组或类数组
 var isArrayLike = function isArrayLike(obj) {
    
    
 	//1.判断obj不为null/undefined/0/"";2.判断obj对象中存在length属性;3.返回obj.length;
        var length = !!obj && "length" in obj && obj.length,
        //检测obj的数据类型
            type = toType(obj);
            //判断如果obj是function或window对象直接返回,它肯定不是数组或类数组
        if (isFunction(obj) || isWindow(obj)) return false;
        //1.判断obj的数据类型为array;2.判断数组中的length属性为0;3.判断length为number类型 且 length>0 且 数组的最大索引(length -1)存在则返回true;
        return type === "array" || length === 0 ||
            typeof length === "number" && length > 0 && (length - 1) in obj;
    };
  • isPlainObject检测是否为纯粹的对象obj.proto===Object.prototype
var isPlainObject = function isPlainObject(obj) {
    
    
        var proto, Ctor;
        //检测obj不存在 toString.call(obj) 返回数据类型不等于"[object Object]" 直接返回false;
        if (!obj || toString.call(obj) !== "[object Object]") return false;
        //获取obj的原型对象
        proto = getProto(obj);
        //dir({}) 如果obj没有原型对象说明它是一个纯粹对象
        if (!proto) return true; // Object.create(null)
        //class2type.hasOwnProperty.call(proto,"constructor")获取构造函数,判断Ctor的数据类型为function且构造函数tostring =Object.toString
        Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
        return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
    };
  • isEmptyObject检测当前对象是否为空对象
var isEmptyObject = function isEmptyObject(obj) {
    
    
		//排除null/undefined
        if (obj == null) return false;
        //获取object的所有普通属性
        var keys = Object.keys(obj);
        //如果Symobl属性不等于undefined,将object的普通属性和Symbol属性组合成一个数组,判断数组的length长度为0返回true
        if (typeof Symbol !== "undefined") keys = keys.concat(Object.getOwnPropertySymbols(obj));
        return keys.length === 0;
    };
  • isNumeric检测是否为有效数字
var isNumeric = function isNumeric(obj) {
    
    
		//获取obj的数据类型
        var type = toType(obj);
        //1.判断obj的数据类型为number 或 string类型;2:判断obj不是一个非法数字;支持 isNumeric(1)返回true,isNumeric("1")返回true,isNumeric("1px")返回false
        return (type === "number" || type === "string") && !isNaN(obj);
    };

猜你喜欢

转载自blog.csdn.net/Lele___/article/details/111588761