• 分析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最后返回了要循环的对象。

  • 相关阅读:
    如何使用PL/SQL工具批量导出表、存储过程、序列
    oracle如何导出和导入数据库/表
    linux安装nginx
    Linux下nginx反向代理服务器安装与配置实操
    StringTokenizer
    mapreduce join
    mapreduce计数器
    hadoop分布式系统架构详解
    进程与线程
    hadoop第一个例子
  • 原文地址:https://www.cnblogs.com/qiaotaojin/p/4054894.html
Copyright © 2020-2023  润新知