• js数组的内部实现,迭代器,生成器和内包


    js内部实现

    在js以外的很多语言中,数组将会隐式占用一段连续的内存空间。
    这种隐式的内部实现,使得高效的内存使用及高速的元素方法称为可能,而

    在javascript中,数组实体是一个对象,所以通常的实现方式
    并不是占用一段连续的内存空间
    比较下面2段代码

    <script>
    //代码1
    var arr=[];
     for(var i=0;i<1e7;i++){
         arr[i]='';
     }
    //代码2
     var arr={};
     for(var i=0;i<1e7;i++){
         arr[i]='';
     }
    </script>

    根据实现方式的不同,代码1和代码2的执行速度会有所差异,这其实是数组是否使用连续的内存空间的一种体现。
    然而如果数组内部总是使用连续的内存空间,下面代码就应该占用多达GB量级的连续内存,不过在一般的实现中,这样的情况不糊发生

    <script>
    var arr=[];
    arr[1e9]='';
    </script>

    在流行的jsvascript实现中,小型的数组(下标值较小的部分)会占用连续的内存空间,而下标值较大的部分,

    则一般会以类似于对象的形式进行处理
    此外在js中 也有人提出需要增加Int32Array或Int8Array这类自定义增强功能

    数组风格的对象调用Array类的方法

    <script>
    var fake_arr={0:'zero',1:'one',2:'two',length:3}
    fake_arr.join(',');//Uncaught TypeError: undefined is not a function
    p(Array.join(fake_arr,','));//zero,one,two     firefox可以运行  其它浏览器可能报错
    Array.push(fake_arr,'three');
    p(fake_arr.length);//4
    p(Array.join(fake_arr,'_'));//zero_one_two_three
    //另外一种
    p(Array.prototype.join.call(fake_arr,'-'));  // zero-one-two-three 更多浏览器支持了
    </script>

    迭代器
    一种专门为循环操作设计的对象
    在javascript中有Iterator类这样一个自定义增强功能。
    可以通过构造函数调用或Iterator函数的调用来生成一个对象实例,这时需要将想要枚举的目标对象传递个它的第一个参数
    在迭代器对象中含有一个next方法,可以从对象或元素的集合中返回下一个所需的元素
    下面代码在firefox下正常运行,在其他浏览器中可能出问题

    <script>
    var arr=['zero','one','two'];
    var it=new Iterator(arr,true);
    p(it.next());//0  单个元素
    p(it.next());//1
    p(it.next());//2
    p(it.next());//uncaught exception: [object StopIteration]
    //如果第二个参数为false
    var it=new Iterator(arr,false);
    p(it.next());//[0 ,zero ]  数组
    p(it.next());//1 one
    p(it.next());//2 two
    p(it.next());//uncaught exception: [object StopIteration]
    </script>

    对Iterator使用for in

    <script>
    var arr=['zero','one','two'];
    var it=new Iterator(arr,false);
    for(var item in it){
        for(var k in item){
            p(k+":"+item[k]);
        }
        p("--------------------------------------")
    }
    /*输出
    0:0
    1:zero
    --------------------------------------
    0:1
    1:one
    --------------------------------------
    0:2
    1:two
    --------------------------------------
    */
    </script>

    对于已经存在的对象或数组来说,使用Iterator没有太大作用
    for in等语句已经足够
    使用场景:自定义迭代器
    代码如下(测试时在firefox下好使)

    <script>
    //迭代器的目标对象
    function Factorial(max){
        this.max=max;
    }
    //自定义迭代器
    function FactorialIterator(factorial){
        this.max=factorial.max;
        this.count=this.current1=1;
    }
    //迭代器的实现
    FactorialIterator.prototype.next=function(){
        if(this.count>this.max){
            throw StopIteration;
        }else{
            return this.current1*=this.count++;
        }
    }
    //将Factorial与FactorialIterator相关联
    //__iterator__属性是一种特殊属性
    Factorial.prototype.__iterator__=function(){
        return new FactorialIterator(this);
    }
    
    var obj=new Factorial(5);
    for(var n in obj){
        p(n)
    }
    /*
    结果
    1
    2
    6
    24
    120
    */
    </script>

     生成器

    和迭代器一样,生成器(Generator)也是javascript自定义的增强功能,其作用是帮助执行循环处理

    从表面上看,生成器就像一个普通的函数.生成器与普通函数的不同之处在于是否在内存进行yield调用。

    一个函数如果在内部进行yield调用,它就是一个隐式的生成器
    输出阶层的函数

    <script type="application/javascript;version=1.7">
    function jc_prnt(max){
        var cur=1;
        for(var n=1;n<=max;n++){
            cur*=n;
            p('curl='+cur);
        }
    }
    jc_prnt(5);
    /*输出
    curl=1
    curl=2
    curl=6
    curl=24
    curl=120
    */
    </script>

    如果在js_print函数里的p(打印)函数之前调用yield
    就变成了如下代码

    <script type="application/javascript;version=1.7">
    function jc_prnt(max){
        var cur=1;
        for(var n=1;n<=max;n++){
            cur*=n;
            yield(cur);
            p('curl='+cur);
        }
    }
    var g=jc_prnt(5);
    p(g.next());//1
    p(g.next());//curl=1    2
    p(g.next());//curl=2    6
    p(g.next());//curl=6    24
    p(g.next());//curl=24    120
    p(g.next());//curl=120   报错
    </script>

    由于从内部看迭代生成器是一个迭代器,所以可以将next方法调用隐藏在for in循环的内部
    js_print函数同上

    <script  type="application/javascript;version=1.7">
    var g=jc_prnt(5);
    for(var n in g){
        p(n,'------------');
    }
    /*
    1
    ------------
    curl=1
    2
    ------------
    curl=2
    6
    ------------
    curl=6
    24
    ------------
    curl=24
    120
    ------------
    curl=120
    */
    </script>

    可将生成器理解为一种由于yield而处于停滞状态的函数。
    在调用next时,生成器的循环将执行一次,更确切的说,这一执行过程与循环没有关系,只是执行生成器的代码直至下一次调用yield

    数组的内包
    数组的内包是一种在通过生成器生成数组时的功能

    <script type="application/javascript;version=1.7">
    function jc_prnt(max){
        var cur=1;
        for(var n=1;n<=max;n++){
            cur*=n;
            yield(n);
        }
    }
    var arr=[i for each (i in jc_prnt(5))];
    p(arr);//数组  1,2,3,4,5
    //也可过滤
    var arr=[ i for each (i in jc_prnt(5)) if (i>3)];
    p(arr);//4,5   数组
    </script>

    注意,上面所有的代码 由于是javascript里的自定义增强功能有的浏览器还不支持,在firefox下运行良好,可以在firefox下测试

  • 相关阅读:
    矩阵快速幂
    BITSET
    不再以讹传讹,GET和POST的真正区别(转)
    Anaconda 镜像
    Anaconda常用命令大全
    如何使用抓包工具fiddler对app进行接口分析
    windows10搭建django1.10.3+Apache2.4
    如何用jenkins实现自动化构建新版本和二维码下载
    解决从jenkins打开robot framework报告会提示‘Opening Robot Framework log failed ’的问题
    Macaca开源--阿里的移动自动化测试框架
  • 原文地址:https://www.cnblogs.com/HKUI/p/4287025.html
Copyright © 2020-2023  润新知