jq源码学习4_jQuery.extend() : 扩展一些工具方法

基于jquery-2.0.3的源码分析

//4.jQuery.extend() : 扩展一些工具方法
/*jQuery.extend({	
	expando  :  生成唯一JQ字符串(内部)
	noConflict()  :  防止冲突
	isReady  :  DOM是否加载完(内部)
	readyWait  :  等待多少文件的计数器(内部)
	holdReady()  :  推迟DOM触发
	ready()  :  准备DOM触发
	isFunction()  :  是否为函数
	isArray()  :  是否为数组
	isWindow()  :  是否为window
	isNumeric()  :  是否为数字 
	type()  :  判断数据类型
	isPlainObject()  :  是否为对象自变量
	isEmptyObject()  :  是否为空的对象
	error()  :  抛出异常
	parseHTML()  :  解析节点
	parseJSON()  :  解析JSON
	parseXML()  :  解析XML
	noop()  :  空函数
	globalEval()  :  全局解析JS
	camelCase()  :  转驼峰(内部)
	nodeName()  :  是否为指定节点名(内部)
	each()  :  遍历集合
	trim()  :  去前后空格
	makeArray()  :  类数组转真数组
	inArray()  :  数组版indexOf
	merge()  :  合并数组
	grep()  :  过滤新数组
	map()  :  映射新数组
	guid  :  唯一标识符(内部)
	proxy()  :  改this指向
	access()  :  多功能值操作(内部)
	now()  :  当前时间
	swap()  :  CSS交换(内部)
	
});
*/
jQuery.extend({
  //生成唯一的jq字符串(内部),作用:用于作为唯一映射关系
  expando:"jQuery" + (core_version + Math.random()).replace(/\D/g, ""),
  //防止冲突,当外界使用 $ 或者 jQuery 时候,jq可以自动方法这两个对外接口,通过调用 noConflict()函数,自定义对外使用接口
  noConflict:function(deep){  
    if(window.$ === jQuery){ //不写参数的时候是对$的放弃写参数的时候是对jQuery的放弃
       window.$ = _$;  //不写参数的时候放弃$
    }
    if(deep && window.jQuery === jQuery){ 
     
         window.jQuery = _jQuery;
    }
    return jQuery;
     /*noConflict()的使用
      
      */
  },
isReady: false, //dom是否加载完成(内部使用)
readyWait:1,//等待多少文件的计数器(内部)
holdReady:function(hold){ //推迟DOM触发
   if(hold){ 
     jQuery.readyWait ++;
   }else{
     jQuery.ready(true);
   }
},
ready:function(wait){ //准备DOM触发,参数和holdReady有关
  //如果readyWait不是0,或者isReady是false,那么什么也不做,继续等待!
  //readyWait为0时就不用hold了,执行后面的操作
   if(await === true ? --jQuery.readyWait : jQuery.isReady){
     return;   
   }
   jQuery.isReady = true;//默认是false
   if(wait !==true && --jQuery.readyWait >0){
     return;
   }
    //如果已经readyWait是0,那么就会执行,也就是触发事件,最终调用Deferred对象的done方法
		 //上下文是document,第二个参数是jQuery对象!这时候外层的done已经执行了,也就说这个ready中的函数可以执行了!
		 //第一个参数是指向context所以ready中第一个参数是document对象,第二个jQuery就是参数也就是给ready函数传递的参数!
   readyList.resolveWith( document, [ jQuery ] );
   if ( jQuery.fn.trigger ) {
    jQuery( document ).trigger("ready").off("ready");
  }
},
isFunction:function(obj){//是否为函数
   return jQuery.type(obj) === "function";//$.type() 函数用于确定JavaScript内置对象的类型,并返回小写形式的类型名称。
},
isArray:Array.isArray,//是否为数组
isWindow:function(obj){  //是否为window
 return obj != null && obj === obj.window;
},
isNumeric:function(obj){ //是否为数字
  //isNaN() 函数用于检查其参数是否是非数字值
  //parseFloat() 函数可解析一个字符串,并返回一个浮点数。
  //该函数指定字符串中的首个字符是否是数字。如果是,则对字符串进行解析,直到到达数字的末端为止,然后以数字返回该数字,而不是作为字符串。
  //isFinite() 函数用于检查其参数是否是无穷大。
  return !isNaN( parseFloat(obj) ) && isFinite(obj);
},
type:function(obj){  // 判断数据类型
  if(obj == null){
    return String(obj);
  }
  return typeof obj === "object" || typeof obj === "function" ?
  class2type[core_toString.call(obj)] || "object" : typeof obj;
},
isPlainObject:function(obj){ //是否为对象自变量
  if(jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj)){
      return false;
  }
  try{
    if(obj.constructor && !core_hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){
          return false;
    }
  }catch(e){
     return false;
  }
},
isEmptyObject:function(obj){ //判断是否为空的对象
  //for-in循环会同时枚举非继承属性和从原型对象继承的属性,如果有,则立即返回false,否则默认返回true。
   var name;
   for(name in obj){ //for...in 语句用于对数组或者对象的属性进行循环操作。
      return false;
   }
   return true;
},
error:function(msg){ //抛出异常
  throw new Error( msg ); 
},
parseHTML:function(data,context,keepScripts){  //解析节点
  if(!data || typeof data !== "string"){
     return null;
  }
  //只有两个参数的时候,第二个就是是否保存script标签,这时候context就没有传进来
  if(typeof context === "boolean"){
     keepScripts = context;
     context = false;
  }
  //如果只有两个参数那么context就是document对象!
  context = context || document;
  //如果不是单个标签那么parsed就是null,所谓的单个标签就是
或者
但是
hello
不满足! var parsed = rsingleTag.exec( data ), //如果keepScripts是false,那么scripts就是 scripts = !keepScripts && []; if ( parsed ) { //如果是单个标签就调用相应的createElement方法,默认上下文是document! return [ context.createElement( parsed[1] ) ]; } //如果不是单个标签就调用buildFragment方法,把html字符串传入,同时上下文也传入,第三个参数就是scripts! //如果paseHTML的第三个参数是false,那么这里的scripts就是一个数组,传递到buildFragment中会把所有的script标签放在里面 parsed = jQuery.buildFragment( [ data ], context, scripts ); if(scripts){ jQuery(scripts).remove(); } //buildFragment返回的是文档碎片,所以要变成数组,调用merge方法 return jQuery.merge( [], parsed.childNodes ); }, parseJSON: JSON.parse,//解析JSON parseXML:function(){ //解析XML var xml, tmp; if ( !data || typeof data !== "string" ) { return null; } // Support: IE9 try { tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } catch ( e ) { xml = undefined; } if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop:function(){}, //空函数 globalEval:function(code){ //全局解析JS // code:待执行的JavaScript语句或表达式 var script, indirect = eval; code = jQuery.trim(code);//去除字符串的前后空格 if(code){ //indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置 //如果在数组中没找到字符串则返回 -1 if(code.indexOf("use strict") === 1 ){ //判断是否是在严格模式下,严格模式不支持eval //createElement() 方法通过指定名称创建一个元素 script = document.createElement("script"); script.text = code; document.head.appendChild( script ).parentNode.removeChild( script ); }else{ indirect(code); } } }, camelCase:function(string){ //转驼峰(内部) return string.replace(rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName:function(elem,name){ //是否为指定节点(内部使用) //用法$.nodeName(document.body,'html') return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); }, each: function( obj, callback, args ) {//遍历集合 var value, i = 0, length = obj.length, isArray = isArraylike( obj ); if ( args ) { if ( isArray ) { for ( ; i < length; i++ ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } } else { for ( i in obj ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isArray ) { for ( ; i < length; i++ ) { value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) { break; } } } else { for ( i in obj ) { value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) { break; } } } } return obj; }, trim:function(text){ //去前后空格 return text == null ? "" : core_trim.call( text ); }, makeArray:function(arr,results){ //类数组转真数组 // makeArray可以将一个类数组转换成真正的数组。如果传入第二个参数resullts(仅在jQuery内部使用), //第一个参数arr中的元素将被合并入第二个参数,最后返回第二个参数,此时返回的不一定是真正的数组。 // arr:待转换对象,可以是任何类型 // results:仅在jQuery内部使用。如果传入参数resultes,则在该参数上添加元素。 // 定义返回值ret。如果传入了参数result则把该参数作为返回值,否则新建一个空数组作为返回值。 var ret = results || []; // 如果传入的参数arr不是null、undefined的情况 if(arr != null){ // 使用isArrayLike判断arr是否是数组或类数组对象。 //如果是数组或类数组对象,调用jQuery.merge()将arr合并到返回值ret中 if(isArraylike(Object(arr))){ //判断是不是类似数组 jQuery.merge(ret, typeof arr === "string" ? [arr] :arr ); } // 否则,因为不确定ret的格式。所以选择push.call()的方式合并而不是ret.push()。 //如果只传入参数array,则返回值ret是真正的数组;如果还传入了第二个参数result,则返回值ret的类型取决于该参数的类型 else{ core_push.call(ret,arr); } } // 返回ret return ret; }, //jQuery.inArray()函数用于在数组中搜索指定的值,并返回其索引值。如果数组中不存在该值,则返回 -1。 inArray:function(elem,arr,i){ // 数组版 indexOf return arr == null ? -1 : core_indexOf.call(arr,elem,i); }, merge:function(first,second){ //合并数组 // 用于合并两个数组的元素到第一个数组中,第一个参数可以是数组或类数组对象,即必须含有整数(或可以转换成整些)属性length; //第二个参数可以数组,类数组对象或任何含有连续属性的对象。注意:方法jQuery.merge()的合并具有破坏性, //将第二个参数合并到第一个参数时,会改变第一个参数。如果不希望改变第一个参数,可以在调用jQuery.merge()方法前对第一个参数进行备份。 // 初始化变量,将second.length转换成数字, //并将first.length赋值给i,循环添加second的属性到first中,因为不确定first是否是数组,所以用i来修正first.length。最后返回first。 var l = second.length, i = first.length, j = 0; if(typeof l ==="number"){ //判断第二个参数是数组 for(;j

 

你可能感兴趣的:(JQuery源码学习)