jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的。

jQuery.extend({

  ......    

  each: function( obj, callback, args ) {   //$.each(arr , function(i,value){}),第三个参数用于内部调用。此方法就是来遍历数组的,然后取数组中的值进行显示。不能改变原数组arr,跟map一样,但是map返回新数组,而each返回原数组。这里跟原生的forEach和map的回调方法参数不一样,原生的回调方法中,第三个参数是原数组,可以在回调方法中改变原数组的值。但jQuery的回调方法,不会传第三个参数。
    var value,
      i = 0,
      length = obj.length,
      isArray = isArraylike( obj );   //是否是类数组或数组,json(不包括jQuery这种对象形式)返回false

    if ( args ) {    //jQuery内部使用
      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;
          }
        }
      }

    }

    else {       //我们在外面调用时,执行的代码
      if ( isArray ) {   //如果是类数组
        for ( ; i < length; i++ ) {
          value = callback.call( obj[ i ], i, obj[ i ] );  //回调方法返回false就停止循环

          if ( value === false ) {
            break;
          }
        }
      }

      else {
        for ( i in obj ) {  //如果是json对象
          value = callback.call( obj[ i ], i, obj[ i ] );

          if ( value === false ) {
            break;
          }
        }
      }
    }

    return obj;
  }, 

  trim: function( text ) {   //core_trim是字符串的trim方法
    return text == null ? "" : core_trim.call( text );
  }, 

  makeArray: function( arr, results ) {  //把所有东西转换成数组,$.makeArray(json) -> [],第二个参数是给内部用的
    var ret = results || [];

    if ( arr != null ) {
      if ( isArraylike( Object(arr) ) ) {

      //如果arr为数字123,这里会返回false,因为number不是类数组。但是如果是字符串"hello",Object会把它转成具有length的json对象,所以就返回true。字符串是有length属性的。
        jQuery.merge( ret,
          typeof arr === "string" ?
            [ arr ] : arr
        );
      }

      else {    //如果传入123,就执行这里,把123push到数组中。假设有第二个参数,$.makeArray(123,{length:0}) ,那么就会出现[].push.call({length:0},123),这里我做了测试,是没有任何问题的,会变成{length:1,0:123}

        core_push.call( ret, arr );   
      }
    }

    return ret;
  },

  inArray: function( elem, arr, i ) {  //元素是否在arr数组中,从i位置开始找。core_indexOf=[].indexOf
    return arr == null ? -1 : core_indexOf.call( arr, elem, i );
  }, 

  merge: function( first, second ) {    //合并数组
    var l = second.length,
      i = first.length,
      j = 0;

    if ( typeof l === "number" ) {    //第二个参数,可能不是数组或类数组,特殊json。第一个参数必须是。
      for ( ; j < l; j++ ) {
        first[ i++ ] = second[ j ];
      }
    }

    else {
      while ( second[j] !== undefined ) {   //普通json的情况,{0:"0",1:"1"},但必须是0,1,2...这种
        first[ i++ ] = second[ j++ ];
      }
    }

    first.length = i;    //当第一个参数,不是数组时,比如是{0:"0",1:"1",length:2},length就需要手动改变

    return first;
  },   

  grep: function( elems, callback, inv ) {

  //过滤得到一个新数组,$.grep(arr,function(value,index){ return value>2}),arr数组中大于2的,才会返回生成数组。也就是返回true时,才会返回此值生成数组,第三个参数,true,就代表相反的(小于等于2)返回生成数组

    var retVal,
      ret = [],
      i = 0,
      length = elems.length;
    inv = !!inv;    //转换成true or false,不传的时候是undefined,就会变成fase.

    for ( ; i < length; i++ ) {
      retVal = !!callback( elems[ i ], i );    //转换成true or false
      if ( inv !== retVal ) {
        ret.push( elems[ i ] );
      }
    }

    return ret;
  },

  map: function( elems, callback, arg ) {  //支持普通json,数组,类数组,特殊json(jQuery对象形式)

  //$.map(arr,function(value,index){ return }),通过回调,把返回的值组成一个全新的数组,返回全新的数组。第三个参数内部调用
    var value,
      i = 0,
      length = elems.length,
      isArray = isArraylike( elems ),    //数组和类数组都可以,jQuery对象形式也可以
      ret = [];

    if ( isArray ) {
        for ( ; i < length; i++ ) {
          value = callback( elems[ i ], i, arg );

          if ( value != null ) {   //回调返回的值不是null或者undefined,就存入新数组中
            ret[ ret.length ] = value;
          }
        }

    }

    else {      //普通json就执行这里,比如:{name:"chaojidan",age:25}
        for ( i in elems ) {
          value = callback( elems[ i ], i, arg );//callback("chaojidan",name)

          if ( value != null ) {
            ret[ ret.length ] = value;
          }
        }
    }

    return core_concat.apply( [], ret );

    //core_concat=[].concat,以防回调方法返回的是数组形式,那么就会出现复合数组,比如:ret = [[1],[2],[3]],通过concat([1],[2],[3]),合并,返回[1,2,3]
  },

  ......

})

加油!

jquery源码解析:each,makeArray,merge,grep,map详解的更多相关文章

  1. jQuery 源码解析(三十) 动画模块 $.animate()详解

    jQuery的动画模块提供了包括隐藏显示动画.渐显渐隐动画.滑入划出动画,同时还支持构造复杂自定义动画,动画模块用到了之前讲解过的很多其它很多模块,例如队列.事件等等, $.animate()的用法如 ...

  2. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  3. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

  4. jQuery源码分析(九) 异步队列模块 Deferred 详解

    deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...

  5. JQuery源码解析(一)

    写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...

  6. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  7. jquery源码解析:代码结构分析

    本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function() ...

  8. jquery 源码解析

    静态与实力方法共享设计 遍历方法 $(".a").each() //作为实例方法存在 $.each() //作为静态方法存在 Jquery源码 jQuery.prototype = ...

  9. jQuery源码解析资源便签

    最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...

  10. 三.jQuery源码解析之jQuery的框架图

    这张图片是对jQuery源码截图,一点一点拼出来的. 现在根据这张图片来对jQuery框架做一些说明. 一.16~9404行可以发现,最外层是一个自调用函数.当jQuery初始化时,这个自调用函数包含 ...

随机推荐

  1. JsSIP 注册,拨打填坑

    吐个槽: http://tryit.jssip.net/  这个毛东西,默认是要使用视频的,而且没得设置不使用,至少我没看到有设置的!!!(其实就是写死了,翻了他的js代码的-_-||) 设置连接到自 ...

  2. siebel简介

    定义公司架构.描述S应用架构.安装应用.配置S.自动化的业务规则.数据整合.不同环境如何整合. 一.介绍CRM 销售.Callcenter等 允许管理客户和联系人. 二.Using the web c ...

  3. Spring学习笔记(四)--MVC概述

    一. 飞机 最近马来西亚航空370号班机事故闹得沸沸扬扬,情节整的扑朔迷离,连我在钻研springMVC平和的心情都间接的受到了影响.正当我在想这个MVC的处理过程可以怎样得到更好的理解呢?灰机,灰机 ...

  4. Java-CSV文件读取

    import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import ja ...

  5. 洛谷 P2850 [USACO06DEC]虫洞Wormholes 判负环

    虫洞(wormhole) FJ 在农场上闲逛时,发现他的农场里有很多虫洞.虫洞是一条特殊的有向路径,当 FJ 从它的一头走到另一头后,他将被传送到过去的某个时刻.FJ 的每个农场包括 N(1<= ...

  6. linux sed命令详解-乾颐堂CCIE

    简介 sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的 ...

  7. Django学习笔记:为Model添加Action

    |- Django版本:1.8 |- Python版本:3.4 models.py 1 class Story(models.Model): #编辑Story状态 STATUS_CHOICES = ( ...

  8. Perl 学习笔记-文件测试

    1.文件测试操作符 针对文件和目录的测试操作符: -r/-w/-x/-o: 文件或目录, 对有效的(负责运行这个程序的)用户或组来说是可读/写/执行/拥有 的; 这些测试位会查看文件的权限位, 以此判 ...

  9. C# 静态类的使用

    静态类与非静态类基本相同,但存在一个区别:静态类不能实例化.也就是说,不能使用 new 关键字创建静态类类型的变量.因为没有实例变量,所以要使用类名本身访问静态类的成员. static class C ...

  10. java中jar打包的方法

    jar 应用 先打开命令提示符(win2000或在运行筐里执行cmd命令,win98为DOS提示符),输入jar -help,然后回车(如果你盘上已经有了jdk1.1或以上版本),看到什么:用法:ja ...