js配列の内部実装、サブジェネレータ、ジェネレータ、および内部パケット

35916 ワード

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ではInt 32 ArayやInt 8 Arayなどのカスタム強化機能を追加する必要があるという意見もあります.
配列スタイルのオブジェクトをArayクラスに呼び出す方法
 
<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関数の呼び出しによって、オブジェクトのインスタンスを生成することができます.このとき、列挙したい対象物をその最初のパラメータに渡す必要があります.その第1のパラメータは、サブエージェントオブジェクトに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>
内部からイテレーションジェネレータはローズマリーであるため、for inサイクルに隠れている内部js_をnextメソッドで呼び出すことができます.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の下でテストできます.