不用意に(いわゆる)クロージャーを量産してはならない。

  • 一度覚えだすと、使いたくなるクロージャーだが今後の為に覚書
var createCountDown = function ( n ) {
  var count = n;
  var func  = function ( ) {
    return count--;
  };

  return func;
};

var count0 = createCountDown ( 10 );
var count1 = createCountDown ( 20 );

count0(); //--> 10
count0(); //--> 9
count1(); //--> 20
count0(); //--> 8

この関数 createCountDown の中の関数 func からは、変数 count と、n が参照できる。

しかも、関数 createCountDown を呼び出すたびに、新しい count と n が作り出される。

慣れてくると非常に便利。

  • 正規表現で置き換えするときに、関数で処理する

(要素のstyleを、"background-color" から "backgroundColor" に変換する)

var hoge = function ( str /*String*/ ) {
  var fuga = function( a, b ) {
    return b.toUpperCase();
  };
  var result = str.replace( /-[a-z]/g, fuga );

  return result;

  //一行なら
  return str.replace(/-[a-z]/g,function(a,b){return b.toUpperCase()})
};

この関数 fuga からも、外側の関数の変数 str は、参照できる。なのでこれもいわゆるクロージャー。
ところで、参照させないためにはどうするか?

  • それは簡単なこと。関数 fuga を、外側で定義すればよい。
var fuga = function( a, b ) {
  return b.toUpperCase();
};

var hoge = function ( str /*String*/ ) {
  var result = str.replace( /-[a-z]/g, fuga );

  return result;

  //一行なら
  return str.replace(/-[a-z]/g,function(a,b){return b.toUpperCase()})
};

しかし、関数 fuga は、関数 hoge のためだけにあるような関数。他の関数から使われないように
するにはどうするか?
もしくは、関数 fuga を定義してしまったために、fuga という名前を使えなくなってしまった。
それをどうするか?

  • こんな形に変形できる
var hoge = (function ( fuga ) {
  return function ( str ) {
    return str.replace( /-[a-z]/g, fuga );
  };
})(function( a, b ) {
     return b.toUpperCase();
   });
  • なんと version=1.8 では、関数の { } と return を省略できる。
<script type="application/javascript;version=1.8">
var hoge =
  (function ( fuga )
    function ( str )
      str.replace( /-[a-z]/g, fuga ))
        (function( a, b )
          b.toUpperCase());
</script>

う〜〜ん。自分でも一発でこれを書けません。

  • これを発展させて、配列の文字列を、変換するのに逆にも対応させると
<script type="application/javascript;version=1.8">

function hoge ( ary, flag )
 ary.map(
  flag ?
   function ( a )
    a.replace( /-([a-z])/g,
     function ( a, b )
      b.toUpperCase() )://←この位置から見ると
   function ( a )
    a.replace(/[A-Z]/g,
     function ( a )
      '-' + a.toLowerCase() )
 );



alert( [hoge( [ 'aB', 'bC' ], false ), hoge( [ 'a-b', 'b-c' ], true ) ] );
</script>

この場合だと、関数 function ( a, b ) のところからは、その外側、さらにその外側と参照できる環境が出来てしまっている。これでは大量にメモリーを消費する。(反省)

<script type="application/javascript;version=1.8">

var hoge =
  (function ( toUpper, toLower )
     function( ary, flag )
       ary.map( flag ? toUpper: toLower ))(
         (function ( up )
           function( a )
             a.replace( /-([a-z])/g, up ))(
               function ( a, b )
                 b.toUpperCase()),
         (function ( low )
           function ( a )
             a.replace(/[A-Z]/g, low ))(
               function ( a )
                 '-' + a.toLowerCase()));

alert( [hoge( [ 'aB', 'bC' ], false ), hoge( [ 'a-b', 'b-c' ], true ) ] );

</script>

とにかく、「アホな書き方をすると大量にメモリーを消費してしまう」ということで。