JS框架设计之对象数组化一种子模块

类数组对象是一个很好的存储结构,但是功能太弱了,为了享受纯数组的哪些便捷的方法,使用前可以做下转换,通常可以使用$.slice.call()方法做转换,但是旧版本的IE下的HTMLCollection、NodeList不是Object的子类,如果采用[].slice.call()方法可能会导致异常,下面是各大库是怎么处理的:

1、jQuery的makeArray

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../../common/jquery-1.9.1.min.js"></script>
</head>
<body>
    <script>
        //一般将一个对象转换成数组需要用[].slice.call()方法来转换,但是在旧版本的IE中HTMLCollection、NodeList不是Object的子类,是com对象
        //所以无法使用[].slice.call()方法来把传入的对象数组化,下面是jQuery兼容IE旧版本的对象数组化方法


        //该方法有以下保证
        /*
        1、不管是否传入参数,始终返回一个数组,如果不传参,则返回一个空数组
        2、对传入的参数(不包含length属性、是字符串、是jQuery方法的、是array的setInterval的)将他们的引用存入数组的第一项
        3、如果传入的参数符合数组化的要求,则进行数组化
         */

        //注意:传入的集合必须是具有length属性,然后集合的键值必须是数字,也就是具有数组结构的集合,才能被转换
        var makeArray=function(array)
        {
            var ret=[];
            if(array!=null)
            {
                var l=array.length;
                if(l==null || typeof array==="string" ||jQuery.isFunction(array) || array.setInterval)
                {
                    ret[0]=array;
                }
                else
                {
                    while (l)
                    ret[--l]=array[l];
                }
            }
            return ret;
        }
        alert(makeArray({length:3,0:"a",1:"b",2:"c"})[1]);
    </script>
</body>
</html>

2、dojo的对象数组化方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
        /*
        dojo的对象数组化方法和Ext一样,都是在一开始判断浏览器类型,他的后面也有两个参数,用于操作转化后的数组
        但是dojo后面的两个参数,不是要截取数组的开始索引和结束索引
        dojo的第一个参数是要转换成数组的对象,第二个是偏移量,第三个是已有的数组,返回值是已有的数组和转换后,并截取过的合并数组
         */
        var zc={};
        isIE=true;
        (function(){
            var efficient=function (obj,offest,startWith) {
                return (startWith||[]).concat([].slice.call(obj,offest || 0));
            }
            var slow=function (obj,offest,startWith) {
                 var arr=startWith || [];
                //偏移量不支持负数
                 for(var i=offest || 0;i<obj.length;i++) {
                     arr.push(obj[i]);
                 }
                return arr;
            }
            zc.toArray=isIE?function (obj) {
                return slow.apply(this,arguments);
            }:efficient;
        })();
        alert(zc.toArray({length:3,0:"a",1:"b",2:"c"},0,[1,2,3]));
    </script>
</body>
</html>

3、Ext的对象数组化方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
        /*
        Ext设计的比较巧妙,在框架一加载的同时,就判断浏览器的的类型,然后存到变量中,后面就不需要判断浏览了,
        然后根据浏览器的是不是IE来选择toArray到底引用那个方法体,如果是IE浏览器,则吊用自定义的对象数组化方法,
        如果不是则调用[].slice.call(),并通过slice方法,通过i,j参数对字符串进行截取操作
        */
        /*
        该方法有以下保证
        1、如果在IE浏览器下执行,则则调用自定义的对象数组化方法
        2、如果不再IE下,吊用[].slice.call()来进行对象数组化
        3、可以提供两个参数(start,end),用于截取指定长度的转换后的对象数组
         */
        var toArray=function () {
            var returnisIE;//判断浏览器是否是IE
            return returnisIE?function(a,i,j){
                var length=a.length || 0,result=new Array(length);
                while (length--)
                result[length]=a[length];
                return result.slice(i || 0,j|| a.length);
            }:function(a,i,j){
                return Array.prototype.slice.call(a,i || 0,j || a.length);
            };
        }();
        var res=toArray({length:2,0:"a",1:"2"},1);
        alert(res)
    </script>
</body>
</html>

4、mootools

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    /*
    mootools的对象数组化方法
     */
    /*
    该方法有以下保证
    1、当用户传入的是HTMLCollection集合是,因为老版IE的HTML节点对象是COM对象,不是Js对象的子类,所以无法使用[].slice.call()方法
    使用自定义的对象数组化方法
    2、如果传入的对象不是上面的那种情况,那么吊用[].slice.call()方法来进行对象数组化
     */
    function $A(array)
    {
        if(array.item)
        {
            var length=array.length || 0,result=new Array(length);
            while (length--)
            result[length]=array[length];
            return result;
        }
        return Array.prototype.slice.call(array);
    }
    var res=$A({length:2,0:1,1:2});//输出:1,2
    alert(res)
</script>
</body>
</html>

5、Prototype

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    /*
    Prototype的对象转换成数组的方法
     */

    /*
    该方法有以下保证
    1、如果不传入参数,返回空数组
    2、如果当前浏览器支持toArray()方法,那么调用该对象的toArray()方法
    3、如果上面两种条件都不满足,那么拿到当前对象的length属性(如果没有给0),然后new一个具有length长度的数组,并进行赋值
     */

    //注意:要转换成数组的对象的length不能大于实际元素的长度,也不能小于实际元素的长度
    function $A(array){
        if(!array)return [];
        if(array.toArray)return array.toArray();
        var length=array.length || 0,results=new Array(length);
        while (length--)
        results[length]=array[length];
        return results;
    }
    var result=$A({length:3,0:1,1:2,2:3});
    alert(result);
</script>
</body>
</html>

6、mass

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
/*
下面是mass的对象数组化方法
 */
/*
该方法有以下保证:
1、一开始就对浏览器进行区分
2、如果是IE则调用自定义对戏那个数组化方法,如果不是,则使用[].slice.call
3、提供start和end参数,方便对(传入对象数组化之后的数组)进行截取
4、保证start和end参数的输入不会影响输出结果
 */
isIE=true;
var toArray=window.isIE?function(nodes,start,end)
{
    var ret=[],length=nodes.length;
    if(end===void 0 || typeof  end==="number" && isFinite(end))
    {
        start=parseInt(start,10) || 0;
        end=end==void 0?length:parseInt(end,10);
        if(start<0)
            start+=length;
        if(end>length)
            end=length;
        if(end<0)
            end+=length;
        for(var i=start;i<end;i++)
        {
            ret[i-start]=nodes[i];
        }
    }
    return ret;
}:function (nodes,start,end)
{
    return Array.prototype.slice.call(nodes,start,end);
};
var res=toArray({length:3,0:1,1:"a",2:"b"},0,-1);//输出:1,a
    alert(res);
</script>
</body>
</html>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏coder修行路

go 从入门到精通(二)基本数据类型和操作符

一、文件名&关键字&标识符 所有go源码都是以.go结尾 标识符以字母或下划线开头,大小写敏感 下划线_是特殊标识符,用户忽略结果 保留关键字 导入包时可以设置...

19890
来自专栏技术之路

c++多重继承小结

如果一个类从两个不同的类里继承两个同名的成员,则需要在派生类中使用类限定符来区分他们。 即在从A和B派生出来的c类中使用a::Show()和B::Show()来...

18270
来自专栏前端那些事

RegExp正则匹配模式汇总

 正则表达式提供另一种强大的文本搜索和处理方式,对于正则表达式,不同语言有着不同的实现,JavaScript采用的Perl5的语法。对于极少数匹配模式是简单的全...

22560
来自专栏Java帮帮-微信公众号-技术文章全总结

第二十天 IO-异常file类【悟空教程】

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

14050
来自专栏MasiMaro 的技术博文

结构体和类

在C++中类与结构体并没有太大的区别,只是默认的成员访问权限不同,类默认权限为私有,而结构体为公有,所以在这将它们统一处理,在例子中采用类的方式。

22020
来自专栏海天一树

小朋友学Python(15):函数

函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段。 函数能提高应用的模块性,和代码的重复利用率。 Python提供了许多内建函数,比如print(...

33770
来自专栏Python攻城狮

Python内置函数

mode : mode 决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。

11840
来自专栏mwangblog

python变量、语句

16940
来自专栏Golang语言社区

【Go 语言社区】Go语言类型转换

类型转换是一种可变从一种数据类型转换成另一种数据类型。例如,如果要存储一个long值转成一个简单的整数,那么可以强制类型转换long为int。可以从一种类型使用...

367140
来自专栏Laoqi's Linux运维专列

While 循环语句

42480

扫码关注云+社区

领取腾讯云代金券