jQuery 源码分析5: jQuery 基本静态方法(一)

jQuery在初始化过程中会为自己扩展一些基本的静态方法和属性,以下是jQuery 1.11.3版本 239 ~ 564行间所扩展的静态属性和方法

 
  1 jQuery.extend({
  2 
  3 // 为每个jQuery拷贝建立一个唯一的编号
  4 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
  5  
  6 // 假设jQuery脱离模块支持,已经准备好
  7 isReady: true,
  8 
  9 // 空转函数
 10 noop: function() {},
 11 
 12 /******************* 基本类型判断方法 *****************************/
 13 
 14 isFunction: function( obj ) {
 15      return jQuery.type(obj) === "function";
 16 },
 17 isArray: Array.isArray || function( obj ) {
 18      return jQuery.type(obj) === "array";
 19 },
 20 isWindow: function( obj ) { /* jshint eqeqeq: false */
 21      return obj != null && obj == obj.window;
 22 },
 23 
 24 isNumeric: function( obj ) {
 25 // 首先抛弃数组, 利用parseFloat返回一个浮点数
 26 // 如果obj是一个合法数字(包括字符串数字),与parseFloat返回值的差是0,因此相减后等0,于是加1
 27 // 如果obj是"0x10",返回值则是0,而obj - 0则会得到16,因此判断"0x10"也是数值
 28 // 如果obj是"abc"等非法数字,会得到NaN - NaN,最终也会得到非数值的判断
 29 
 30      return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
 31 },
 32  // 保证obj不包含任何属性
 33 isEmptyObject: function( obj ) {
 34      var name;
 35      for ( name in obj ) {
 36 
 37           return false;
 38      }
 39      return true;
 40 },
 41 // 最常使用的判断之一,纯对象判断
 42 // 纯对象是有 new 或 {} 创建的对象
 43 // 意味着纯对象不能从其他对象原型中继承而来,只能从Object原型中继承
 44 isPlainObject: function( obj ) {
 45      var key;
 46      // 首先必须是一个object
 47      // 针对IE,需要检查对象的constructor属性
 48      // 把DOM节点和window对象都过滤掉
 49      if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
 50           return false;
 51      }
 52       try {
 53           // Not own constructor property must be Object
 54           if ( obj.constructor &&                      // 不包含构造器
 55                !hasOwn.call(obj, "constructor") &&
 56                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
 57                return false;
 58           }
 59 
 60      } catch ( e ) {
 61           // IE8或9在某些主机上会抛出异常
 62           return false;
 63      }
 64       // 支持: IE<9
 65      // 先处理继承的属性,之后才会处理自身属性
 66      if ( support.ownLast ) {
 67           for ( key in obj ) {
 68                return hasOwn.call( obj, key );
 69           }
 70      }
 71      // 一般浏览器是先遍历自己的属性,因此利用空变量来略过之前的自身属性,直接跳到最后一个属性
 72      // 如果最后一个属性是自身的,那么证明了所有属性都是自身的
 73      for ( key in obj ) {}
 74      return key === undefined || hasOwn.call( obj, key );
 75 },
 76 
 77  
 78 
 79 /********************** 基本工具 **********************/
 80 
 81 type: function( obj ) {
 82      if ( obj == null ) {
 83           return obj + "";          // 返回一个字符串 'null'
 84      }
 85 
 86      // //jQuery初始化过程中会产生一个"class到type"的表
 87      // jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
 88      //      class2type[ "[object " + name + "]" ] = name.toLowerCase();
 89      // });
 90      // // 实际上class2type是这样的
 91      // var class2type = {
 92      //      "[object Array]": "array",
 93      //      "[object Boolean]": "boolean",
 94      //      "[object Date]": "date",
 95      //      "[object Function]": "function",
 96      //      "[object Number]": "number",
 97      //      "[object Object]": "object",
 98      //      "[object RegExp]": "regexp",
 99      //      "[object String]": "string",
100      //      "[object Error]" : "error",
101      // };
102      // toString(123) 实际上会返回一个字符串"[object Number]",此时就可以通过class2type表来返回"number"
103      // type(123) 返回的就是"number"
104      // 这样做的原因是,对于很多对象,typeof返回的只是object,无法区分具体是什么对象
105      // 通过object.prototype.toString.call(obj),虽然可以判断出什么对象,但是返回值却不够简练,因此使用了class2type进行映射
106    return typeof obj === "object" || typeof obj === "function" ?
107             class2type[ toString.call(obj) ] || "object" :     // 通过class2type来返回object类型
108             typeof obj;
109 },
110  // Evaluates a script in a global context
111 // 在全局上下文上执行一个脚本
112 globalEval: function( data ) {
113      if ( data && jQuery.trim( data ) ) {
114           // IE上使用execScript
115           // 使用一个匿名函数,从而使上下文在firefox中变成window而非jQuery
116           ( window.execScript || function( data ) {
117                window[ "eval" ].call( window, data );
118           } )( data );
119      }
120 },
121 // 转换 dashed to camelCase; CSS和数据模块才使用这个方法
122 // 首先要去除'-ms-'中的第一个'-'
123 // 然后删除'-'并将'-'后紧接着的字母转换成大写
124 // rmsPrefix = /^-ms-/
125 // rdashAlpha = /-([\da-z])/gi
126 // fcamelCase = function( all, letter ) {
127 //          return letter.toUpperCase();
128 // };
129 camelCase: function( string ) {
130      return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
131 },
132 // 判断elem节点的名字是否为name
133 // 在后面对节点的操作经常会用到
134 nodeName: function( elem, name ) {
135      return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
136 },
137 });

 

总结
  • 基本判断方法里,jQuery.isNumeric的实现过程比较简练,要判断"0x10"这样的十六进制数字,又要判断"1.23"这样的浮点数.该方法里面只使用到了parseFloat,并根据其返回值的特点("字符串前部的合法数字"),只使用一次函数就可判别出数字,实现得非常精明;
  • 纯对象的判断jQuery.isPlainObject也是用得较多的工具,其中针对浏览器的兼容性实现和优化都值得学习;
  • jQuery.type的实现方案更加精彩,因此不同平台上typeof不一定能够准确返回对象的类型,因此需要使用到Object.ptototype.toString方法,然而这个方法会返回不需要的字符,建立一个映射表便可解决这一个问题;
posted @ 2015-07-24 12:08 elcarim 阅读(...) 评论(...) 编辑 收藏