JavaScript 多次元配列の1次元配列への展開

関数を作っていて、こんな機能があったらいいなと思いました。

```function(a, b, c, d, e);```
```function([a, b, c, d, e]);```
```function([a, b], [c, d], e);```
```function([a, [b, c], d], e);```
```function([a, [b, [c], d], e);```

これらの全てで同じように動く機能。

引数、argumentsを、配列に変換する方法は
```Array.prototype.slice.call(arguments)```
このようにすればいいことは以前から知っていますが、
結局のところ、そこから、多次元配列を1次元配列に変更しなければいけないと思ったので、実装してみました。

# 多次元配列から1次元配列への展開
```JavaScript
  var arrayMultiDimensionExpand = function (arrayValue) {
    var result = [];
    var f = function (value) {
      for (var i = 0, l = value.length; i < l; i += 1) {
        var arrayItem = value[i];
        if (Array.isArray(arrayItem)) {
          f(arrayItem);
        } else {
          result.push(arrayItem);
        }
      }
    };
    f(arrayValue);
    return result;
  };
```
内部で再起呼び出しを使って出力しています。

# 動作確認
動作確認は次のとおりです。
[世界最小テストフレームワーク](http://qiita.com/standard-software/items/559d871794bfa38651f4)のcheckを使っています。

```JavaScript
  var check = function (a, b, message) {
    if (a === b) {
      return true;
    }
    if ((typeof message === 'undefined')
    || (message === null)) {
      message = '';
    } else {
      message = 'Test:' + message + '\n';
    }
    message = message +
        'A != B' + '\n' +
        'A = ' + a + '\n' +
        'B = ' + b;
    alert(message);
    return false;
  };

  check('1,2,3,4',          arrayMultiDimensionExpand([1,2,3,4]).join());
  check('1,2,3,4',          arrayMultiDimensionExpand([[1,2],3,4]).join());
  check('1,2,3,4',          arrayMultiDimensionExpand([[1,2],[3,4]]).join());
  check('1,2,3,4,5,6',      arrayMultiDimensionExpand([1,2,3,4,5,6]).join());
  check('1,2,3,4,5,6',      arrayMultiDimensionExpand([[1,2],[3,4], 5, 6]).join());
  check('1,2,3,4,5,6',      arrayMultiDimensionExpand([[1,2,3,4], 5, 6]).join());
  check('1,2,3,4,5,6',      arrayMultiDimensionExpand([[1,[2,3],4], 5, 6]).join());
  check('1,2,3,4,5,6',      arrayMultiDimensionExpand([[[1,[2,3]],4], [5, 6]]).join());
  check('1,2,3,4,5,6',      arrayMultiDimensionExpand([[[[[[1],2],3],4],5],6]).join());
  check('1,2,3,4,5,6,7,8',  arrayMultiDimensionExpand([[1,[2,3],4], [5, [6, 7], 8]]).join());
```

これで、多次元配列で引数を渡されても、対応できる関数を作ることができます。

# 全文

全文です。
web と node.js と windows wsh wsf で動作確認しました。

orValue という、第一引数と、第二引数以降のものを比較する関数を作って、動作確認しました。
orValueは、第一引数に関数を指定すると、第二引数以降が展開されてしまうので、比較できないですね。

```JavaScript:script.js
var alert = alert || function (message) {
	console.log(message);
};

var main = function (testName) {

  //----------------------------------------
  //・assert関数
  //----------------------------------------
  //  ・  value が true でなければ
  //      例外を出力する関数
  //  ・  他言語でよく使う
  //----------------------------------------
  var assert = function (value, message) {

    if ((typeof message === 'undefined')
    || (message === null)) {
      message = '';
    }
    if (typeof value !== 'boolean') {
      throw new Error('Error:' + message);
    }
    if (!value) {
      throw new Error('Error:' + message);
    }
  };

  //----------------------------------------
  //・check関数
  //----------------------------------------
  //  ・  2値が一致するかどうか確認する関数
  //----------------------------------------
  var check = function (a, b, message) {
    if (a === b) {
      return true;
    }
    if ((typeof message === 'undefined')
    || (message === null)) {
      message = '';
    } else {
      message = 'Test:' + message + '\n';
    }
    message = message +
        'A != B' + '\n' +
        'A = ' + a + '\n' +
        'B = ' + b;
    alert(message);
    return false;
  };

  //----------------------------------------
  //・Array.isArray
  //----------------------------------------
  //  ・Array.isArray が存在しない環境(WSHなど)
  //    のために実装
  //  ・参考:書籍:JavaScriptパターン P51
  //----------------------------------------
  Array.isArray = Array.isArray || function (arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };

  var arrayMultiDimensionExpand = function (arrayValue) {
    var result = [];
    var f = function (value) {
      for (var i = 0, l = value.length; i < l; i += 1) {
        var arrayItem = value[i];
        if (Array.isArray(arrayItem)) {
          f(arrayItem);
        } else {
          result.push(arrayItem);
        }
      }
    };
    f(arrayValue);
    return result;
  };

  check('1,2,3,4', arrayMultiDimensionExpand([1,2,3,4]).join(), '01');
  check('1,2,3,4', arrayMultiDimensionExpand([[1,2],3,4]).join(), '02');
  check('1,2,3,4', arrayMultiDimensionExpand([[1,2],[3,4]]).join(), '02');
  check('1,2,3,4,5,6', arrayMultiDimensionExpand([1,2,3,4,5,6]).join(), '02');
  check('1,2,3,4,5,6', arrayMultiDimensionExpand([[1,2],[3,4], 5, 6]).join(), '02');
  check('1,2,3,4,5,6', arrayMultiDimensionExpand([[1,2,3,4], 5, 6]).join(), '02');
  check('1,2,3,4,5,6', arrayMultiDimensionExpand([[1,[2,3],4], 5, 6]).join(), '02');
  check('1,2,3,4,5,6', arrayMultiDimensionExpand([[[1,[2,3]],4], [5, 6]]).join(), '02');
  check('1,2,3,4,5,6', arrayMultiDimensionExpand([[[[[[1],2],3],4],5],6]).join(), '02');
  check('1,2,3,4,5,6,7,8', arrayMultiDimensionExpand([[1,[2,3],4], [5, [6, 7], 8]]).join(), '02');

  var orValue = function (value, compares) {

    assert(2 <= arguments.length);
    var argsArray = arrayMultiDimensionExpand(arguments);

    for (var i = 1, l = argsArray.length; i < l; i += 1) {
      if (value === argsArray[i]) {
        return true;
      }
    }
    return false;
  };

  var a = 1;
  check(true, orValue(a, 1), '01');
  check(true, orValue(a, 1, 2), '02');
  check(true, orValue(a, 1, 2, 3), '03');
  check(false,orValue(a, 2, 3, 4), '04');

  check(true, orValue(101, [101, 102]));
  check(true, orValue(102, [101, 102]));
  check(false,orValue(103, [101, 102]));
  check(true, orValue(103, [101, 102], 103));
  check(false,orValue(104, [101, 102], 103));
  check(true, orValue(104, [101, 102], 103, 104));
  check(true, orValue(104, [101, 102], [103, 104]));

  check(false,orValue(105, [101, 102], [103, 104]));
  check(true, orValue(105, [101, 102], [103, 104], 105));
  check(true, orValue(102, [[[101, [102], 103], 104], 105]));
  check(true, orValue(103, [[[101, [102], 103], 104], 105]));
  check(true, orValue(105, [[[101, [102], 103], 104], 105]));
  check(false,orValue(106, [[[101, [102], 103], 104], 105]));


  alert(testName + ' test finish');
}

if (typeof module !== 'undefined') {
  module.exports = main;
}

```

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title></title>
    <script src="script.js"></script>

<script>

var alert = function (message) {
	console.log(message);
};

window.addEventListener("load",function(eve){
  // main('load');
},false);

</script>

  </head>
<body>

<form name="form01">
<table class="table02">
  <tr>
    <td>
      <input type="button" value="Test01" onclick="main('web')" 
        style="width:150px;">

    </td>
  </tr>

</table>
</form>


</body>
</html>

```

```JavaScript:call_script_node.js
var main = require('./script.js');
main('node.js');
```

```run_node_script.bat
node call_script_node.js
pause
```

```run_wsh_script.wsf
<?xml version="1.0" encoding="shift-jis" ?>
<job>
    <script language="JavaScript" src=".\script.js"></script>
    <script language="JavaScript">
    <![CDATA[

var alert = function (message) {
	WScript.Echo(message);
}

main('WSH_wsf');

    ]]>
    </script>
</job>
```

# ライブラリ

このあたりの仕組みなどを組み込んだ、汎用関数ライブラリを作っています。
既存のJavaScript環境の(たぶん)全てに対応できるように組んでいるので、
ご参考や、ご利用など、どうぞです。

stsLib.js/Source/stsLib.js at master · standard-software/stsLib.js
https://github.com/standard-software/stsLib.js/tree/master/Source/stsLib.js

# 追記
........もしかして......
joinして、splitしたら、同じ処理ができるのではないか？？？

多次元配列に対して、```[1,2,3,[4,5, [6,7]]].join()```
は、かなりいい感じの値を返してくれている。

必要なら調べてみてください。