どらちゃんのポッケ

R・統計・技術メモなど勉強ログ置き場

JavaScriptはじめました(基本的言語仕様 その2)

今回はこんな感じ。

  1. ブロックスコープはJavaScriptには存在しない。
  2. argumentsオブジェクト
  3. 引数のデフォルト値を設定する
  4. 可変長の引き数を扱う関数
  5. 名前付き引数
  6. 高階関数
  7. クロージャ

 

  • ブロックスコープはJavaScriptには存在しない。

java

    if (1 == 1) {
        var n = 123;
    }
    document.write(n); //エラーになる

javascript

    if (1 == 1) {
        var n = 123;
    }
    document.write(n); //123
  • argumentsオブジェクト

JavaScriptでは関数の引数が多くても、エラーにはならず、argumentsオブジェクトに格納される。
argumentsオブジェクトは、関数呼び出しのタイミングで生成され、引数の値をすべて保持する。

下の例では・・・
showMessage(123); ⇒123
showMessage(123,456);⇒123と456
がargumentオブジェクトに格納される。

    function showMessage(txt) {
        document.writeln(txt);
    }

    showMessage();           //undefined
    showMessage(123);        //123
    showMessage(123, 456);   //123 
                                                //456もargumentオブジェクトに格納される

引数のチェックをかけるためには、arguments.lengthを使う。

    function showMessage(txt) {
        if (arguments.length != 1) {
            throw Error(’引数の数が違います’+arguments.length);
        }
        document.writeln(txt);
    }

    try {
        showMessage();                //エラー
        showMessage(123);        //OK
        showMessage(123, 456);   //エラー
    } catch (e) {
    window.alert(e.message);
    }
  • 引数のデフォルト値を設定する

Javascriptでは、引数の指定をしなくてもよいため、引数の指定が行われなかった場合のデフォルト値を設定しておくことが一つの手段としてある。

    function triangle(base, height) {
        if (base == undefined) {
            base = 1;
        }
        if (height == undefined) {
            height = 1;
        }
        return base * height / 2;
    }
    document.writeln(triangle(5)); //2.5 heightが省略されていると見なされる
    document.writeln(triangle()); //0.5
  • 可変長の引き数を扱う関数

arguments.lengthをうまく使う。

    function sum() {
        var result = 0;
        for (var i=0; i < arguments.length; i++) {
            var temp = arguments[i];
            if (isNaN(temp)) {
                throw new Error('the value is not number!!' + temp);
                }
            result += temp;
        }
        return result;
    }

    try {
        document.writeln(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));   //55
        document.writeln(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 'u')); //the value is not number!!u
    } catch (e) {
        window.alert(e.message);
    }
  • 再帰的な使い方

arguments.calleeを使う。

    function factorial(n) {
        if (n != 0) {
            return n * arguments.callee(n - 1);
        }
        return 1; //ここを忘れがち
    }

    document.writeln(factorial(5)); //120 
  • 名前付き引数

名前付き引数は、関数呼び出し時に、名前を明示的に指定できる引数のこと。
1)省略可能な引数が多い
2)引数の数が多いと言う場合には有効。

    function triangle(args) {
        if (args.base == undefined) {
            args.base = 1;
        }
        if (args.height == undefined) {
            args.height = 1;
        }
        return args.base * args.height / 2;
    }

    document.writeln(triangle({ base: 5 }, { height: 4 }));  //2.5
    document.writeln(triangle({ height: 2 }, { base: 4 }));  //1 順序の入れ替え
    document.writeln(triangle({ height: 2 }));          //baseを省略   

関数の引数が関数になるもの。オブジェクト指向に向く。

   function showElement(key, vale) {
        document.writeln(key + ':' + vale);
    }

    var result = 0;
    function addAll(key, value) {
        result += value;
    }

//関数を引数にしている関数(階層が一番上)    
function arrayWalk(data, useFunction) {
        for (var key in data) {
            useFunction(key, data[key]);
                }
    }

    var ary = [1, 2, 3, 4, 5];
    arrayWalk(ary, showElement);     //0:1 1:2 2:3 3:4 4:5
    arrayWalk(ary, addAll);               //15
    document.writeln(result);
  • クロージャ

クロージャの概念はもやもやとして上手く理解できない・・・・。

 function closure(init) {
        var counter = init;

        return function () {
            return ++counter;
        }
    }

    var myClosure = closure(1);     //myClosure にclosure関数を代入。
                                                          //変数counterはスコープを超えて保持されるようになる。
    document.writeln(myClosure());  //2
    document.writeln(myClosure());  //3
    document.writeln(myClosure());  //4

JavaScript奥深いだろ!