関数

Tag:

関数を利用する上で押さえておきたいと思う基礎知識です。

定義方法

// function命令
function aaa(x, y) {
    return x + y;
}

// 関数リテラル
var aaa= function(x, y) {
    return x + y;
};

// Functionコンストラクタ(非推奨)
var aaa = new Function('x', 'y', 'return x + y;');

Functionコンストラクタによる定義も可能だが非推奨。Functionコンストラクタ内ではグローバル変数を参照するため、意図しない動作が起こる可能性がある。

定義する位置に注意

funtion命令で定義された関数
同一scriptタグ内であればどこからでも呼べる。
異なるscriptタグの場合、関数呼出しのscriptタグよりも、関数定義のscriptタグを先に記述しないといけない。

関数リテラルで定義された関数
同一scriptタグ内であっても、呼び出しもとより前に定義しないとエラーとなる。

アロー関数(ES6)

// 関数リテラルを書きやすく ⇒ アロー関数
var aaa = (x, y) => {
    return x + y;
}

// 引数が一つであれば()を省略可能
var aaa = x => {
    return x + 2;
};

// 一文であれば、{}とreturnも省略可能
var aaa = x => x + 2;

アロー関数を利用するとthisのスコープは周囲と同じになるため、退避させる必要がなくなります。

// 退避させる必要あり
var counter = {
  count: 0,
  start: function() {
    var self = this;
    setTimeout(function() {
      console.log(self.count++);
    }, 1000);
  }
};

// 退避させなくても良い
var counter = {
  count: 0,
  start: function() {
    setTimeout(() => {
      console.log(this.count++);
    }, 1000);
  }
};

スコープチェーン

変数の解決順です。

var name1 = 'aaa';
var name2 = 'aaa';
var name3 = 'aaa';

function bbb() {
  var name2 = 'bbb';
  var name3 = 'bbb'
  function ccc() {
    var name3 = 'ccc';
    console.log(name1); // aaa
    console.log(name2); // bbb
    console.log(name3); // ccc
  }
  ccc();
}

bbb();

引数

仮引数に基本型のデータを渡すと値渡しになり、参照型のデータ(配列や関数など)を渡すと参照渡しになります。

可変長引数

引数の数はチェックされません。引数情報はargumentsオブジェクトで管理されます。

function aaa(x, y) {
  console.log(arguments);
}

aaa(1, 2)     // {0: 1, 1: 2, callee: <書き込みできません。>, caller: <書き込みできません。>, length: 2}
aaa(1, 2, 3); // {0: 1, 1: 2, 2: 3, callee: <書き込みできません。>, caller: <書き込みできません。>, length: 3}

ES6では可変長引数を配列として受け取れます。

function addNumbers(...numbers) {
  console.log(numbers);  // [1, 2, 3, 4, 5, 6, 7]

  return numbers.reduce((sum, number) => {
    return sum + number;
  } , 0);
}
console.log(addNumbers(1,2,3,4,5,6,7));  // 28

デフォルト値

ES5では以下のようにデフォルト値を設定していました。

function xxx(url, method) {
    if (!method) {
        method = 'GET';
    }

}
xxx('dn-web64.com');
xxx('dn-web64.com', 'POST');

ES6では以下のようにできます。

function xxx(url, method = 'GET') {

}
xxx('dn-web64.com');
xxx('dn-web64.com', 'POST');

引数に関数を渡す

function aaa(x, y, func) {
  var sum = x + y;
  func(sum);
}

// 第3引数に無名関数を指定
aaa(
  1, 
  2,
  function (val) {
    console.log(val);
  }
);

コンソールに「3」と表示されます。

クロージャー

関数内のローカル変数は、関数の処理終了後に破棄されます。これを維持するための仕組みがクロージャーです。

function clousure() {
  var x = 1;
  return function () {
    return x++;
  }
}
var f = clousure();
console.log(f());  // 1
console.log(f());  // 2
console.log(f());  // 3

「ローカル変数を参照している関数」を返す関数を定義してますが、これがクロージャになります。

「clousure関数のローカル変数を参照している無名関数」が「f関数」に格納され続けているため「f関数」がローカル変数を維持し続けています。

クロージャーの仕組みは、プライベート変数を作るのに利用されます。

スポンサーリンク