JQuery源码分析
Posted 石
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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把回调函数的用法设计成一个更高的抽像,用于解耦与分离变化。
以上是关于JQuery源码分析的主要内容,如果未能解决你的问题,请参考以下文章
Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段