JQuery源码分析(八)

jQuery的each迭代器

jQuery的each方法从使用上就要分2种情况:

 $.each()函数
$(selector).each()

  

$.each()函数和$(selector).each()是不一样的,后者是专门用来遍历一个jQuery对象的,是为jQuery内部服务的。

$.each()函数可用于迭代任何集合,无论是“名/值”对象(JavaScript对象)或数组。在迭代数组的情况下,回调函数每次传递一个数组索引和相应的数组值作为参数。

(该值也可以通过访问this关键字得到,但是JavaScript始终将this值作为一个Object,即使它是一个简单的字符串或数字值。)该方法返回其第一个参数,这是迭代的对象。

jQuery的实例方法最终也是调用的静态方法。

其中each的实例方法如下:

可见内部是直接调用的静态方法:

each: function(callback, args) {
    return jQuery.each(this, callback, args);
},

  

jQuery.each静态方法:

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;
                }
            }
        }

  

实现原理几乎一致,只是增加了对于参数的判断。对象用for in遍历,数组用for遍历。

jQuery可以是多个合集数组DOM,所以在处理的时候经常就针对每一个DOM都要单独处理,所以一般都需要调用this.each 方法,如下代码:

dequeue: function( type ) {
        return this.each(function() {
            jQuery.dequeue( this, type );
        });
    },

  

迭代器除了单纯的遍历,在jQuery内部的运用最多的就是接口的抽象合并,相同功能的代码功能合并处理:

例如一:

jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

例如二:

jQuery.each({
    mouseenter: "mouseover",
    mouseleave: "mouseout",
    pointerenter: "pointerover",
    pointerleave: "pointerout"
}, function( orig, fix ) {
    //处理的代码
});

  

可以看出上面代码方法,针对相同的功能,节约了大量的代码空间。

实例代码:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://img.mukewang.com/down/540812440001e40e00000000.js" type="text/javascript"></script>
<title></title>
</head>
<body>

<script type="text/javascript">

jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    $(‘body‘).append(name.toLowerCase()+‘</br>‘)
});

</script>
</body>
</html>

  

理解回调函数

函数是第一类对象,这是javascript中的一个重要的概念。意味着函数可以像对象一样按照第一类管理被使用,所以在javaScript中的函数:

能“存储”在变量中

能作为函数的实参被传递

能在函数中被创建

能从函数中返回

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件条件进行响应。

因此从上面可以看出来,回调本质上是一种设计原则,并且jQuery的设计原则遵循了这个模式。

在后端的编程语言中,传统函数以参数形式输入数据,并且使用返回语句返回值。理论上,在函数结尾处有一个return返回语句,结构上就是:一个输入和一个输出。简单的理解函数本质上就是输入和输出之间实现过程的映射

但是,当函数的实现过程非常漫长,你是选择等待函数完成处理,还是使用回调函数进行异步处理呢?这种情况下,使用回调函数变得至关重要,例如:AJAX请求。若是使用回调函数进行处理,代码就可以继续进行其他任务,而无需空等。实际开发中,经常在javascript中使用异步调用。

jQuery中遍地都是回调的设计:

异步回调:

事件句柄回调

$(document).ready(callback);
$(document).on(‘click’,callback)

  

Ajax异步请求成功失败回调

$.ajax({
  url: "aaron.html",
  context: document
}).done(function() {
        //成功执行
}).fail(function() {
        //失败执行
);

  

动画执行完毕回调:

$(‘#clickme‘).click(function() {
    $(‘#book‘).animate({
        opacity: 0.25,
        left: ‘+=50‘,
        height: ‘toggle‘
    }, 5000, function() {
        // Animation complete.
    });
});

  

以上都是jQuery的回调直接运用,运用基本都是将匿名函数作为参数传递给了另一个函数或方法。而且以上都有一个特点,执行的代码都是异步的。

同步回调:

当然回调不仅仅只是处理异步,一般同步(很耗时的任务)的场景下也经常用到回调,比如要求执行某些操作后执行回调函数。

一个同步(阻塞)中使用回调的例子,目的是在test1代码执行完成后执行回调callback

var test1 = function(callback) {
    //执行长时间操作
    callback();
}
test1(function() {
    //执行回调中的方法
});

  

所以理解回调函数最重要的2点:

1、一个回调函数作为参数传递给另一个函数是,我们仅仅传递了函数定义。我们并没有在参数中执行函数。我们并不传递像我们平时执行函数一样带有一对执行小括号()的函数

2、回调函数并不会马上被执行,它会在包含它的函数内的某个特定时间点被“回调”。

实例代码:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://img.mukewang.com/down/540812440001e40e00000000.js" type="text/javascript"></script>
<script src="http://img.mukewang.com/down/541f6ff70001a0a500000000.js" type="text/javascript"></script>

<title></title>
</head>
<body>

<div id="target">
  点击触发事件回调
</div>

<img id="book"  width="100" height="123"
  style="position: relative; left: 10px;background:#ccc" />

<div id="clickme">
  点击动画等待动画结束后回调
</div>

<script type="text/javascript">

//同步回调
function callback(args, fn) {
  var args = args * 2;
  fn(args);
}

callback(2, function(value) {
  show(‘同步回调->‘+ value)
})

//异步事件回调
$("#target").click(function() {
  show("异步事件回调");
});

//异步动画回调
$(‘#clickme‘).click(function() {
  $(‘#book‘).animate({
    opacity: 0.25,
    left: ‘+=50‘,
    height: ‘toggle‘
  }, 1000, function() {
    show(‘异步动画回调‘)
  });
});
</script>
</body>
</html>

  

回调的灵活运用

我们经常会这样使用函数回调:

事件触发通知

资源加载通知

定时器延时

ajax、动画通知等等。

以上都是很单一的事件监听回调的处理方式,但是jQuery把回调函数的用法设计成一个更高的抽像,用于解耦与分离变化。

  

时间: 2024-10-24 21:21:15

JQuery源码分析(八)的相关文章

jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器

jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求,分别是: 1.前置过滤器 jQuery. ajaxPrefilter 2.请求分发器 jQuery. ajaxTransport, 3.类型转换器 ajaxConvert 源码结构: jQuery.extend({ /** * 前置过滤器 * @type {[type]} */ ajaxPrefilter: addToPrefiltersOrTransports(prefilters), /** * 请求分发器 *

Jquery源码分析

1.概述 jQuery是一个非常优秀的Js库,与prototype,YUI,Mootools等众多的Js类库相比,它剑走偏锋,从web开发最实用的角度出发,抛除了一些中看但不实用的东西,为开发者提供一个短小精悍的类库.由于其个短小精悍,使用简单方便,性能相对高效.众多的开发者都选择Jquery来进行辅助的web开发. 在使用jquery时开发,我们也会时常碰到许多的问题,但是jquery的代码很晦涩,难起看懂,当开发时出现了问题,看不懂源码,不知道如何去排错. John Resig,Jquery

jquery源码分析(二)——结构

再来复习下整体架构: jQuery源码分析(基于 jQuery 1.11 版本,共计8829行源码) (21,94)                定义了一些变量和函数jQuery=function(){} (96,280)        给jQuery添加一些方法和属性,jQuery.fn=jQuery.prototype(285,347)        extend:        jQuery的一些继承方法        更容易进行后续的扩展                       

jQuery源码分析-jQuery中的循环技巧

Js代码   作者:nuysoft/JS攻城师/高云 QQ:47214707 EMail:[email protected] 声明:本文为原创文章,如需转载,请注明来源并保留原文链接. 前记:本文收集了jQuery中出现的各种遍历技巧和场景 Js代码   // 简单的for-in(事件) for ( type in events ) { } Js代码   // 缓存length属性,避免每次都去查找length属性,稍微提升遍历速度 // 但是如果遍历HTMLCollection时,性能提升非常

jQuery源码分析系列(38) : 队列操作

Queue队列,如同data数据缓存与Deferred异步模型一样,都是jQuery库的内部实现的基础设施 Queue队列是animate动画依赖的基础设施,整个jQuery中队列仅供给动画使用 Queue队列 队列是一种特殊的线性表,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).队列的特点是先进先出(FIFO-first in first out),即最先插入的元素最先被删除. 为什么要引入队列? 我们知道代码的执行流有异步与同步之分,例如 var a

jQuery源码分析:源码结构与核心函数

jQuery源码分析-03构造jQuery对象-源码结构和核心函数 jQuery.fn和jQuery.prototype区别

jQuery源码分析系列(36) : Ajax - 类型转化器

什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的响应只有 responseText与responseXML 二种 所以现在我要定义dataType为jsonp,那么所得的最终数据是一个json的键值对,所以jQuery内部就会默认帮你完成这个转化工作 jQuery为了处理这种执行后数据的转化,就引入了类型转化器,如果没有指定类型就依据响应头Con

jQuery源码分析系列(34) : Ajax - 预处理jsonp

上一章大概讲了前置过滤器和请求分发器的作用,这一章主要是具体分析每种对应的处理方式 $.ajax()调用不同类型的响应,被传递到成功处理函数之前,会经过不同种类的预处理(prefilters). 预处理的类型取决于由更加接近默认的Content-Type响应,但可以明确使用dataType选项进行设置.如果提供了dataType选项, 响应的Content-Type头信息将被忽略. 有效的数据类型是text, html, xml, json,jsonp,和 script. dataType:预期

jQuery源码分析1

写在开头: 昨天开始,我决定要认真的看看jQuery的源码,选择1.7.2,源于公司用的这个版本.由于源码比较长,这将会是一个比较持久的过程,我将要利用业余时间,和偶尔上班不算忙的时间来进行.其实原本是打算对着源码抄一遍,将对其的理解写成注释,这也算是在强行堆代码量了吧(我想我这是有多懒,必须要反省).不过鉴于自己平时比较懒惰的可耻行径,和太多的东西都写在一起有点庞大,我想我还是有必要写成一个专栏,来记录这个过程.其实最根本的原因是:源码里都是有注释的,而且注释写得那么详尽,翻译过来就是了,但是

jQuery源码分析-each函数

本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuery源码分析-each函数 * jQuery版本:1.4.2 * * ---------------------------------------------------------- * 函数介绍 * * each函数通过jQuery.extend函数附加到jQuery对象中: * jQuery.