分析jQuery中的each方法

在看jQuery源码是怎么实现each方法之前,我们看一下js的原生实现。

ECMAScript 5为数组定义了一个forEach方法,该方法接受两个参数:第一个参数是要在每一个数组项上运行的函数,第二个参数是运行该函数的作用域对象。第二个参数为非必填。作为第一个参数的运行函数接受三个参数,分别是:数组项的值、该项在数组中的位置、数组本身。示例代码如下:

var aa = [1,2,3]
aa.forEach(function(item, index, array){
    console.log("item:"+item)
    console.log("index:"+index)
    console.log(array)
})

原生的方法,效率应该没问题。但是我们仔细一想,这个原生方法可能不太适合用在我们的实际开发中。因为实际开发中我们经常会遇到满足某个条件跳出循环的情况。不能够break,这是原生方法的硬伤。怎么办?我们结合ECMAScript 5的定义自己写一个试试,并且让它也适应于对象。我写的大体代码如下:

function forEach( object, callback, context ) {
    if ( typeof object.length ==="number" ){
        for ( var name in object ) {
            if (object.hasOwnProperty(name) && false === callback.call( context, object[name], name, object ) ) break;
        }
    } else {
        for ( var i = 0, len = object.length; i < len; i++ ) {
            if (false === callback.call( context, object[i], i, object ) ) break;
        }
    }
}

函数的第一个参数是要循环的数组或对象,第二个参数是每项要执行的函数,第三项为非必填,为函数运行的作用域对象。这里主要的变化就是当运行函数返回false时,即跳出循环。

还有就是在循环对象的时候加了一个object.hasOwnProperty的判断,以保证是实例中的属性而不是原型中的。

现在我们再看下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;
                    }
                }
            }
        } 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;
    }

我们看到jQuery实现的each方法的第一个参数也是要循环的数组或对象,第二个参数也是每项要执行的函数。不同的是:

a、这里的第三个参数并不是运行该函数的作用域对象。从代码中看这里的args,是传给运行函数的参数。这种用法不常用,调用时一般用不到args。

b、循环数组或对象的每一项的值作为了运行函数的作用域对象,即运行函数里的this指向了obj[i]。

c、运行函数参数的顺序有所不同,变成了先是”该项在数组中的位置“,再是”项的值“了。我觉得还是先有value 再有 index(或key)会好一些。

d、在循环对象时没有进行hasOwnProperty的判断,这个到底有没有必要那?请高手指点一下!3Q。

e、还有就是jQuery最后返回了要循环的对象。

时间: 2024-12-06 23:59:02

分析jQuery中的each方法的相关文章

jQuery中的$.grep()方法的使用

jQuery中的$.grep()方法的使用 转载▼ grep()方法用于数组元素过滤筛选 grep(array,callback,invert) array:待过滤数组; callback:处理数组中的每个元素,并过滤元素,该函数中包含两个参数,第一个是当前数组元素的值,一个是当前数组元素的下标,即元素索引值.此函数应返回一个布尔值.另外,此函数可设置为一个字符串,当设置为字符串时,将视为“lambda-form”(缩写形式?),其中 a 代表数组元素,i 代表元素索引值.如“a > 0”代表“

重新认识Jquery中的html()方法

今天测试给我提了一个bug:在页面上我需要借助"</td>"来获取表格中某行内的某列以后的单元格,也就是说里面有这样一行代码:"tr = tr.substring(tr.indexOf("</td>"));",这个JavaScript脚本在谷歌等浏览器中均可以达到预期效果,可是在IE8中就不行了,弄了一个多小时最后终于发现了问题,先看如下代码: <html> <head> <title>

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

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

jQuery 中的 unbind() 方法

jQuery 中的 unbind() 方法是 bind() 方法的反向操作,从每一个匹配的元素中删除绑定的事件. 语法结构: [javascript] view plain copy unbind([type][, data]); type是事件类型,data为将要移除的事件.具体说明如下: 1.如果没有参数,则删除所有的绑定事件: 2.如果提供了事件类型(type)作为参数,则只删除该类型的绑定事件: 3.如果把在绑定时传递的处理函数作为第2个参数,则只有这个特定的事件处理函数被删除.

jQuery中的join方法

和JS 中的JOIN 方法一样,将一数组按照JOIN的参数连接起来.比如: var arr = [ "a", "b", "c", "d", "e" ]; document.write(arr.join("-")); 结果:a-b-c-d-e. var members=["John","Steve","Ben","Dam

$.ajax()方法详解 jquery中的ajax方法

jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持. 3.timeout: 要求为Number类型的参数,设置请求超时时间(毫秒).此设置将覆盖$.ajaxSetup()方法的全局设置. 4.async: 要求为Boolean类型的参数,默

jquery中的$.post()方法无法给变全局变量的问题

今天遇到一个问题,在使用jquery的$.post()方法时,没有办法返回布尔值. function check_exist() { var email = $('#email').val().Trim(); url = "/Account/Exist"; $.post(url, { email: email }, function (result) { if (result == "1") { $('#email_error').html("该邮箱已经被

jQuery中animate()的方法以及$(&quot;body&quot;).animate({&quot;scrollTop&quot;:top})不被Firefox支持问题的解决

jQuery中animate()的方法可以去w3school查看,这里主要说一下: $("body").animate({"scrollTop":top}) 不被Firefox支持问题的解决. 其实是使用body的: $("body").animate({"scrollTop":top}) 只被chrome支持,而不被Firefox支持. 而使用html的: $("html").animate({"

解决关于jquery中$.get()方法总是报“HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy”错的方法

解决关于jquery中$.get()方法总是报“HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy”错的方法 今天在看<jquery基础教程(第三版)>第十章的时候,运行随书下载的源码时总是不成功.起初以为书中自带的JS文件有错呢,但是测来测去也没发现哪里有问题.现在把源码附下: 1.这是书中带的HTML文件,其余的忽略不计,关键的就是下面这个a. <a id=&qu