jq框架封装学习笔记2-选择模块

select选择器引擎初步封装

    /**
     * Created by Jepson on 2016/11/20.
     */

    var select = (function () {
        // 基本函数, support 对象, 验证 qsa 与 byclass
        var support = {};
        var rnative = /\{\s*\[native/; // 浏览器能力检测,对方法的定义进行检测

        support.qsa = rnative.test( document.querySelectorAll + '' );
        support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' );

        // 基本方法
        function getByClassName( className, node, i ) {
            node = node || document;
            var list, res = [], i;
            if ( support.getElementsByClassName ) {
                return node.getElementsByClassName( className );
            } else {
                list = document.getElementsByTagName( '*' );
                for(  i = 0; i < list.length; i++ ) {
                    if( ( " " + list[ i ].className + " " ).indexOf( " " + className + " " ) > -1 ) {
                        res.push( list[ i ] );
                    }
                }
                return res;
            }
        }
        // 捕获 1 是 id, 2 是 类, 3 是 通配符 4 是 标签  选择器
        var rbaseselector = /^(?:\#([\w\-]+)|\.([\w\-]+)|(\*)|(\w+))$/;

        function select ( selector, results ) {
            results = results || [];
            var m, temp;
            if ( typeof selector != 'string' ) return results;

            // 判断是否支持 qsa 方法,支持直接用
            if ( support.qsa ) {
                results.push.apply( results, document.querySelectorAll( selector ) )
                return results;

            }
            m = rbaseselector.exec( selector );
            if ( m ) {
                // 捕获到数据了
                if ( m[ 1 ] &&
                    ( temp = document.getElementById( m[ 1 ] ) ) ) {
                    results.push( temp );
                } else if ( m[ 2 ] ) {
                    results.push.apply( results, getByClassName( m[ 2 ] ) );
                } else if ( m[ 3 ] ) {
                    results.push.apply( results, document.getElementsByTagName( m[ 3 ] ) ); // selector
                } else if ( m[ 4 ] ) {
                    results.push.apply( results, document.getElementsByTagName( m[ 4 ] ) ); // selector
                }
                // 注意: 3 和 4 是可以合并
            }
            return results;
        }
        return select;
    })();

trim 的检测与自己实现

    var rtrim = /^\s+|\s+$/g;
    var support = {};
    support.trim = rnative.test(String.prototype.trim + '');    // 方法能力检测,定义
    // 自定义实现 trim 方法
    var myTrim = function (str) {
        // 表示两端去空格, 然后返回去除空格的结果
        if (support.trim) {
            return str.trim();
        } else {
            // 自定义实现
            return str.replace(rtrim, '');
        }
    }

带逗号的选择器功能实现

    var select = ( function() {
        // 正则表达式
        var rnative = /\{\s*\[native/;  // 利用方法定义进行能力检测
        var rtrim = /^\s+|s+$/g;    // trim 方法没有,我们就自己搞
        var rbaseselector = /^(?:\#([\w\-]+)|\.([\w\-]+)|(\*)|(\w+))$/;

        var support = {};
        support.qsa = rnative.test( document.querySelectorAll + '' );
        support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' );
        support.trim = rnative.test( String.prototype.trim + '' );

        // 基本方法
        function getByClassName( className, node ) {
            node = node || document;
            var allElem, res = [], i;

            if ( support.getElementsByClassName ) {
                node = node || document;
                var allElem, res = [], i;

                if ( support.getElementsByClassName ) {
                    return node.getElementsByClassName( className );
                } else {
                    allElem = node.getElementsByClassName( '*' );
                    for( i = 0; i < allElem.length; i++ ) {
                        if ( (" " + allElem[ i ].className + " ").indexOf( " " + className + " ") > -1 ) {
                            allElem.push( list[ i ] );
                        }
                    }
                    return res;
                }
            }
        }

        // 自定义实现 trim 方法
        var myTrim = function( str ) {
            // 两端去掉空格,然后返回去除空格的结果
            if ( support.trim ) {
                return str.trim();
            } else {
                return str.replace( rtrim, '' );
            }
        }

        function select( selector, results ) {
            results = results || [];
            var m, temp, selectors, i, subselector;
            if ( typeof selector != 'string' ) return results;
            // 处理分割的问题
            selectors = selector.splits( ',' );

            for( i = 0; i < selectors.length; i++ ) {
                // selector[ i ] 选择器
                subselector = myTrim( selectors[ i ] );
                // 判断
                if ( support.qsa ) {
                    results.push.apply( results, document.querySelectorAll( subselector ) );
                } else if ( m = rbaseselector.exec( subselector ) ) {
                    // 捕获到数据了
                    if ( m[ 1 ] && ( temp = document.getElementById( m[ 1 ] ) ) ) {
                        results.push( temp );
                    } else if ( m[ 2 ] ) {
                        results.push.apply( results, getByClassName( m[ 2 ] ) );
                    } else if ( m[ 3 ] ) {
                        results.push.apply( results, document.getElementsByTagName( m[ 3 ] ) ); // selector
                    } else if ( m[ 4 ] ) {
                        results.push.apply( results, document.getElementsByTagName( m[ 4 ] ) ); // selector
                    }
                    // 注意: 3 和 4 是可以合并
                }
            }
        }
        return select;  // 返回函数引用
    })();

元素去重

可以得到 select 返回的就是一个数组.* ‘.p, div’很可能匹配到相同元素标签,都在数组中,那就有重复,消耗了性能*。所以可以抽象一下. 我们就是要在数组中去除重复元素

var arr = [ 1, 2, 3, 1, 3, 2, 4 ]; // =>  [ 1, 2, 3, 4 ]
var tempArr = [];
循环将 arr 中的 元素 一个一个 的加到 tempArr 中, 并且需要判断
如果 tempArr 中不包含该元素才会加进去

最简单的方法

    var arr = [ 1, 2, 3, 2, 4, 3, 1, 5 ];
    var tempArr = [];
    for( var i = 0; i < arr.length; i++ ) {
        if ( tempArr.indexOf( arr[ i ] ) === -1  ) {
            tempArr.push( arr[ i ] );
        }
    }
    console.log( tempArr );

但是 indexOf 早期浏览器又不支持,我们要自己封装, 能力检测 - 方法定义检测

    var rnative = /\{\s*\[native/;
    var support = {};
    support.indexOf = rnative.test(Array.prototype.indexOf + "");
    console.log( support.indexOf );

兼容性 indexOf 封装

    var rnative = /\{\s*\[native/;
    var support = {};
    support.indexOf = rnative.test(Array.prototype.indexOf + "");

    var myIndexOf = function (array, search, startIndex) {
        startIndex = startIndex || 0;
        if (support.indexOf) {
            return array.indexOf(search, startIndex);
        } else {
            for (var i = startIndex; i < array.length; i++) {
                if (array[i] === search) {
                    return i;
                }
            }
            return -1;
        }
    }

    var arr = [ 1, 2, 3, 2, 4, 3, 1, 5 ];
    var tempArr = [];
    for ( var i = 0; i < arr.length; i++ ) {
        if ( myIndexOf( tempArr, arr[ i ] ) == -1 ) {
            tempArr.push( arr[ i ] );
        }
    }

    console.log( tempArr ); // 12345

所以元素去重方法就有了

    var rnative = /\{\s*\[native/;
    var support = {};
    support.indexOf = rnative.test(Array.prototype.indexOf + "");
    var myIndexOf = function (array, search, startIndex) {
        startIndex = startIndex || 0;
        if (support.indexOf) {
            return array.indexOf(search, startIndex);
        } else {
            for (var i = startIndex; i < array.length; i++) {
                if (array[i] === search) {
                    return i;
                }
            }
            return -1;
        }
    }
    // 兼容性元素去重方法
    var unique = function ( array ) {
        var resArray = [], i = 0;
        for (; i < array.length; i++) {
            if (myIndexOf(resArray, array[i]) == -1) {
                resArray.push(array[i]);
            }
        }
        return resArray;
    }

添加后代元素元素选择器的封装

jquery的后代元素选择器

    <body>
        <div>div1
            <div>div2
                <div>div3
                    <div>div4</div>
                </div>
            </div>
        </div>
    </body>
    <script>
        $( 'div div' ).each( function () {
            this.style.border = '1px solid red';
            this.style.margin = '5px';
        });
        var length = $( 'div div' ).length;
    </script>

利用空格 实现 后代元素 选择器

现在需要一个函数,函数的参数与结构类似于 select, 该函数专门处理带有 空格的 后代元素

    // 假设 selector 选择器是字符串, 而且不是基本选择器
    // 肯定是 : selector1 selector2 selector3 形式
    // 还有可能: selector1 > selector2:first 形式
    function select2 ( selector, results ) {
        // 如果是空格形式的, 很简单, 将其 split 一下, 然后遍历数组,
        // 利用数组中的选择器来获得元素.
        // 比如 selecotr 是 'div div'
        // split 后: [ 'div', 'div' ]
        // 获得 div: document.getElementsByTagName( 'div' )
        // 得到的是一个维数组 list
        // 再次遍历 list, 在 list 下再次查找 div 元素
        // list[ i ].getElementsByTagName( 'div' );

        // 再比如: 'div .c'
        // 1> 先找 div -> list
        // 2> list[ i ].getElementsByClassName( 'c' )

        // 再看一个例子: 'div p .c'
        // 1> 找 'div' -> list
        // 2> list[ i ] 中找 p -> 重新得到一个集合 list
        // 3> 在 list[ i ] 再找 .c

        // 首先将元素 split, 得到一个选择器数组
        // 遍历数组, 获得元素, 得到元素数组
        // 在遍历元素数组, 再来获得元素

        var selectors = selector.split( ' ' );

        // 假定 'div p .c'
        var arr = document.getElementsByTagName( selectors[ i ].trim() );

        var tempArr = [];
        for ( var i = 0; i < arr.length; i++ ) {
            tempArr.push.apply( tempArr, arr[ i ].getElementsByTagName( 'p' ));
        }

        // 在 tempArr 的基础上再次过滤 .c
        var tempArr2 = [];
        for ( var i = 0; i > tempArr.length; i++ ) {
            tempArr2.push.apply( tempArr2, tempArr[ i ].getElementsByClassName( 'c' ) );
        }
    }

我们思考怎么提取,伪代码:

    // 假设 selector 选择器是字符串, 而且不是基本选择器
    // 肯定是 : selector1 selector2 selector3 形式
    // 还有可能: selector1 > selector2:first 形式
    function basicSelect ( selector, node ) {}
    function select2 ( selector, results ) {
        var selectors = selector.split( ' ' );
        // 假定 'div p .c'
        var arr = [], node = [ document ];
        for ( var i = 0; i < node.length; i++ ) {
            arr.push.apply( arr, basicSelect( selectors[ 0 ], node[ i ] ));
        }
        var tempArr = [];
        for ( var i = 0; i < arr.length; i++ ) {
            tempArr.push.apply( tempArr, basicSelect( selectors[ 1 ], arr[ i ] ));
        }
        // 在 tempArr 的基础上再次过滤 .c
        var tempArr2 = [];
        for ( var i = 0; i > tempArr.length; i++ ) {
            tempArr2.push.apply( tempArr2, basicSelect( selectors[ 2 ], tempArr[ i ] ));
        }
    }

这里 arr,tempArr, tempArr2都是临时的,用完一次就没用了,所以可以考虑全用 arr (伪代码):

    function basicSelect ( selector, node ) {}
    function select2 ( selector, results ) {
        var selectors = selector.split( ' ' );
        // 假定 'div p .c'
        var arr = [], node = [ document ];

        for ( var i = 0; i < node.length; i++ ) {
            arr.push.apply( arr, basicSelect( selectors[ 0 ], node[ i ] ));
        }
        node = arr;
        arr = [];

        for ( var i = 0; i < node.length; i++ ) {
            arr.push.apply( arr, basicSelect( selectors[ 1 ], node[ i ] ));
        }
        node = arr;
        arr = [];

        for ( var i = 0; i > node.length; i++ ) {
            arr.push.apply( arr, basicSelect( selectors[ 2 ], node[ i ] ));
        }
        node = arr;
        arr = [];
        // 最终结果存储到 node 里面去了
    }

这样我们就可以考虑把整个过程用一个循环来做

    function basicSelect ( selector, node ) {}
    function select2 ( selector, results ) {
        results = results || [];
        var selectors = selector.split( ' ' );
        var arr = [], node = [ document ];
        for ( var j = 0; j < selectors.length; j++ ) {
            for ( var i = 0; i < node.length; i++ ) {
                arr.push.apply( arr, basicSelect( selectors[ j ], node[ i ] ));
            }
            node = arr;
            arr = [];
        }
        results.push.apply( results, node );
        return results;
    }

好了我们最后完成一下basicSelect的代码

    <div>
        <p class='c'>p1
            <span class="c">span</span>
        </p>
        <div>
            <p class='c'>p3</p>
            <div>
                <p>p4</p>
            </div>
        </div>
    </div>
    <div>
        <p>p2</p>
    </div>
    <script>
        var rbaseselector = /^(?:\#([\w\-]+)|\.([\w\-]+)|(\*)|(\w+))$/;
        function basicSelect ( selector, node ) {
            node = node || document;
            var m, res;
            if ( m = rbaseselector.exec( selector ) ) {
                if ( m[ 1 ] ) { // id
                    res = document.getElementById( m[ 1 ] );
                    if ( res ) {
                        return [ res ];
                    } else {
                        return [];
                    }
                } else if ( m[ 2 ] ) {  // class
                    return node.getElementsByClassName( m[ 2 ] );
                } else if ( m[ 3 ] ) {
                    return node.getElementsByTagName( m[ 3 ] );
                } else if ( m[ 4 ] ) {
                    return node.getElementsByTagName( m[ 4 ] );
                }
            }
            return [];
        }

        function select2 ( selector, results ) {
            results = results || [];
            var selectors = selector.split( ' ' );
            // 假定 'div p .c'
            var arr = [], node = [ document ];
            for ( var j = 0; j < selectors.length; j++ ) {
                for ( var i = 0; i < node.length; i++ ) {
                    arr.push.apply( arr, basicSelect( selectors[ j ], node[ i ] ));
                }
                node = arr;
                arr = [];
            }

            results.push.apply( results, node );
            return results;
        }
        // 测试代码
        var list = select2( 'div p .c' );
        console.log( list );
    </script>

加入后代选择器的封装

    var select = (function() {
        // 正则表达式
        var rnative = /\{\s*\[native/;
        var rtrim = /^\s+|\s+$/g;

        var rbaseselector = /^(?:\#([\w\-]+)|\.([\w\-]+))|(\*)|([\w\-]+)$/;

        var support = {};
        // 分别判断方法是否支持
        support.qsa = rnative.test( document.querySelectorAll + "" );
        support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' );
        support.trim = rnative.test( String.prototype.trim + '' );
        support.indexOf = rnative.test( Array.prototype.indexOf + '' );

        // 基本方法
        // 兼容性方法 getByClassName
        function getByClassName( className, node ) {
            node = node || document;
            var allElem, res = [], i;
            // 支持就用,不支持,我们就自己实现
            if ( support.getElementsByClassName ) {
                return node.getElementsByClassName( className );
            } else {
                allElem = node.getElementsByClassName( '*' ); // 获取所有的元素
                for (i = 0; i < allElem.length; i++) { // 进行筛选
                    if ((' ' + allElem[i].className + '').indexOf(' ' + className + ' ') > -1) {
                        res.push(allElem[i]);
                    }
                }
                return res;
            }
        }
        // 兼容性方法 myTrim
        var myTrim = function( str ) {
            // 两端去掉空格, 然后返回去掉空格的结果
            if ( support.trim ) {
                return str.trim();
            } else {
                // 这时候系统没有,自定义的实现
                return str.replace( rtrim, '' );
            }
        };
        // 兼容性方法 myIndexOf
        var myIndexOf = function ( array, search, startIndex ) {
            startIndex = startIndex || 0;
            // 如果有么,就用系统的
            if ( support.indexOf ) {
                return array.indexOf( search, startIndex );
            } else { // 如果没有么,那就自己实现好了挖
                for ( var i = startIndex; i < array.length; i++ ) {
                    if ( array[ i ] === search ) {
                        return i;   // 返回索引
                    }
                }
                return -1;
            }
        };
        // 兼容性方法 数组去重
        var unique = function( array ) {
            var resArray = [], i = 0;
            for (; i < array.length; i++ ) {
                if ( myIndexOf( resArray, array[ i ] ) == -1 ) {
                    resArray.push( array[ i ] );
                }
            }
            return resArray;
        };

        // 基本选择器封装,能够实现 id 类 通配符 标签选择器
        function basicSelect( selector, node ) {
            node = node || document;
            var m, res;
            if ( m = rbaseselector.exec( selector ) ) {
                if ( m[ 1 ] ) { // id
                    res = document.getElementById( m[ 1 ] );
                    // id 选择器比较特殊,没找到会返回 null, 但是应该要返回[] 所以这里要做一个特殊处理
                    if ( res ){
                        return [ res ];
                    } else {
                        return [];
                    }
                } else if ( m[ 2 ] ) { // class
                    return getByClassName( m[ 2 ], node );
                } else if ( m[ 3 ] ) { // *
                    return node.getElementsByTagName( m[ 3 ] );
                } else if ( m[ 4 ] ) { // tag
                    return node.getElementsByTagName( m[ 4 ] );
                }
             }
            return [];
        }

        // 基于 basicSelect 的 层级选择器封装
        function select2( selector, results ) {
            results = results || [];
            var selectors = selector.split( ' ' ); // 将selector 根据 空格进行分割
            var arr = [], node = [ document ];

            for ( var j = 0; j < selectors.length; j++ ) {
                for ( var i = 0; i < node.length; i++ ) {
                    // 遍历 selectors 分割出来的 子元素, 进行选择
                    arr.push.apply( arr, basicSelect( selectors[ j ], node[ i ] ) );
                }
                node = arr;
                arr = [];
            }
            // 最后的结果全都在 results 中
            results.push.apply( results, node );
            return results;
        }

        //  核心暴露函数
        function select( selector, results ) {
            results = results || [];
            var m, temp, selectors, i, subselector;
            // 你首先传给我个 东西, 那必须是字符串吧
            if ( typeof selector != 'string' ) return results;
            // 参数没有问题,那就开搞
            // 先看看 牛逼的 qsa 能不能用,能用就直接用
            if ( support.qsa ) {
                results.push.apply( results, document.querySelectorAll( selector ) );
            } else {
                // 不存在我们自己来搞一搞, 字符串分割
                selectors = selector.split( ',' );
                // 循环
                for( i = 0; i < selectors.length; i++ ) {
                    subselector = myTrim( selectors[ i ] ); // 去掉不该有的空格
                    // 接下来就是 处理 subselector
                    if ( rbaseselector.test( subselector ) ) {
                        // 基本选择器
                        results.push.apply( results, basicSelect( subselector ) );
                    } else {
                        // select2 函数
                        select2( subselector, results );
                    }
                }
            }
            // return 之前过滤一波
            return unique( results );
        }

        return select;
    })();

解决 IE 8 中伪数组无法使用 push 的方法 - 完善封装

    var list = document.getElementsByTagName( 'div' );
    var arr = [];

    arr.push.apply( arr, list );
    console.log( arr );

在 IE 8 是无法实现这个 push 效果的,伪数组无法使用 push,我们需要考虑自己重新实现 push 的 apply 方法,并加入封装之中

    var select = (function() {
        var push = [].push;

        // 如果出现了错误那么就需要重写 push
        try {
            var div = document.createElement('div');
            div.innerHTML = '<p></p>';
            var arr = [];
            push.apply(arr, div.getElementsByTagName('p'));
        } catch (e) {

            push = {
                apply: function (array1, array2) {
                    for (var i = 0; i < array2.length; i++) {
                        array1[array1.length++] = array2[i];
                    }
                }
            };
        }


        // 正则表达式
        var rnative = /\{\s*\[native/;
        var rtrim = /^\s+|\s+$/g;

        var rbaseselector = /^(?:\#([\w\-]+)|\.([\w\-]+))|(\*)|([\w\-]+)$/;

        var support = {};
        // 分别判断方法是否支持
        support.qsa = rnative.test( document.querySelectorAll + "" );
        support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' );
        support.trim = rnative.test( String.prototype.trim + '' );
        support.indexOf = rnative.test( Array.prototype.indexOf + '' );

        // 基本方法
        // 兼容性方法 getByClassName
        function getByClassName( className, node ) {
            node = node || document;
            var allElem, res = [], i;
            // 支持就用,不支持,我们就自己实现
            if ( support.getElementsByClassName ) {
                return node.getElementsByClassName( className );
            } else {
                allElem = node.getElementsByClassName( '*' ); // 获取所有的元素
                for (i = 0; i < allElem.length; i++) { // 进行筛选
                    if ((' ' + allElem[i].className + '').indexOf(' ' + className + ' ') > -1) {
                        res.push(allElem[i]);
                    }
                }
                return res;
            }
        }
        // 兼容性方法 myTrim
        var myTrim = function( str ) {
            // 两端去掉空格, 然后返回去掉空格的结果
            if ( support.trim ) {
                return str.trim();
            } else {
                // 这时候系统没有,自定义的实现
                return str.replace( rtrim, '' );
            }
        };
        // 兼容性方法 myIndexOf
        var myIndexOf = function ( array, search, startIndex ) {
            startIndex = startIndex || 0;
            // 如果有么,就用系统的
            if ( support.indexOf ) {
                return array.indexOf( search, startIndex );
            } else { // 如果没有么,那就自己实现好了挖
                for ( var i = startIndex; i < array.length; i++ ) {
                    if ( array[ i ] === search ) {
                        return i;   // 返回索引
                    }
                }
                return -1;
            }
        };
        // 兼容性方法 数组去重
        var unique = function( array ) {
            var resArray = [], i = 0;
            for (; i < array.length; i++ ) {
                if ( myIndexOf( resArray, array[ i ] ) == -1 ) {
                    resArray.push( array[ i ] );
                }
            }
            return resArray;
        };

        // 基本选择器封装,能够实现 id 类 通配符 标签选择器
        function basicSelect( selector, node ) {
            node = node || document;
            var m, res;
            if ( m = rbaseselector.exec( selector ) ) {
                if ( m[ 1 ] ) { // id
                    res = document.getElementById( m[ 1 ] );
                    // id 选择器比较特殊,没找到会返回 null, 但是应该要返回[] 所以这里要做一个特殊处理
                    if ( res ){
                        return [ res ];
                    } else {
                        return [];
                    }
                } else if ( m[ 2 ] ) { // class
                    return getByClassName( m[ 2 ], node );
                } else if ( m[ 3 ] ) { // *
                    return node.getElementsByTagName( m[ 3 ] );
                } else if ( m[ 4 ] ) { // tag
                    return node.getElementsByTagName( m[ 4 ] );
                }
            }
            return [];
        }

        // 基于 basicSelect 的 层级选择器封装
        function select2( selector, results ) {
            results = results || [];
            var selectors = selector.split( ' ' ); // 将selector 根据 空格进行分割
            var arr = [], node = [ document ];

            for ( var j = 0; j < selectors.length; j++ ) {
                for ( var i = 0; i < node.length; i++ ) {
                    // 遍历 selectors 分割出来的 子元素, 进行选择
                    push.apply( arr, basicSelect( selectors[ j ], node[ i ] ) );
                }
                node = arr;
                arr = [];
            }
            // 最后的结果全都在 results 中
            push.apply( results, node );
            return results;
        }

        //  核心暴露函数
        function select( selector, results ) {
            results = results || [];
            var m, temp, selectors, i, subselector;
            // 你首先传给我个 东西, 那必须是字符串吧
            if ( typeof selector != 'string' ) return results;
            // 参数没有问题,那就开搞
            // 先看看 牛逼的 qsa 能不能用,能用就直接用
            if ( support.qsa ) {
                push.apply( results, document.querySelectorAll( selector ) );
            } else {
                // 不存在我们自己来搞一搞, 字符串分割
                selectors = selector.split( ',' );
                // 循环
                for( i = 0; i < selectors.length; i++ ) {
                    subselector = myTrim( selectors[ i ] ); // 去掉不该有的空格
                    // 接下来就是 处理 subselector
                    if ( rbaseselector.test( subselector ) ) {
                        // 基本选择器
                        push.apply( results, basicSelect( subselector ) );
                    } else {
                        // select2 函数
                        select2( subselector, results );
                    }
                }
            }
            // return 之前过滤一波
            return unique( results );
        }

        return select;
    })();

each 函数函数封装

    function each ( arr, func ) {
        var i;
        // 在 js 中(面向对象的编程语言中) 有一个规则:鸭式变型
        // 在 ES5 中还引入了 Array.isArray 的方法专门来判断数组
        if ( arr instanceof Array || arr.length >= 0) {
            for ( i = 0; i < arr.length; i++ ) {
                func.call( arr[ i ], i, arr[ i ] );
            }
        } else {
            for ( i in arr ) {
                func.call( arr[ i ], i, arr[ i ] );
            }
        }
        return arr;
    }

map 函数的封装

    function map(arr, func) {
        var i, res = [], tmp;
        // 鸭式变型
        if (arr instanceof Array || arr.length >= 0) {
            for (i = 0; i < arr.length; i++) {
                tmp = func(arr[i], i);
                if (tmp != null) {
                    res.push(tmp);
                }
            }
        } else {
            for (i in arr) {
                tmp = func(arr[i], i);
                if (tmp != null) {
                    res.push(tmp);
                }
            }
        }
        return res;
    }
    var list = map([1, 2, 3, 4, 5], function (v, i) {
        return 'a';
    });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值