関数定義
変数名、関数名の大文字小文字は区別される。
使用できる文字は半角英数字、アンダーバー、ドル記号。
function AddNum(a, b){
return a + b;
}
変数に関数を代入
var AddNum = function(a, b){
return a + b;
}
関数を変数に代入出来るため、引数や戻り値として関数を受け渡しすることも出来る。
引数の初期値を設定(ES6)
function sample(name = 'マイケル'){
//処理
}
式や関数なども初期値として書ける。
function sample(a, b = a)
function sample(a = Math.max(10, 20, 30))
function sample(obj = new MyObj())
可変長引数 arguments
関数内では引数は全て arguments オブジェクトで管理されている。
argumentsオブジェクトを使うことで可変長引数が実現できる。
function AddNum(){
var ret = 0;
for(var i = 0; i < arguments.length; i++){
ret += arguments[i];
}
return ret;
}
AddNum(2, 5);
AddNum(10, 8, 50, 20);
可変長引数(ES6)
引数名の前に「...」を付与すると可変長引数となる。
可変長引数はArrayオブジェクトになっている。
function sample(...args){
let total = 0;
for(let a of args){
total += a;
}
return total;
}
sample(10, 20, 30);
引数の数はチェックされない
JavaScriptでは引数の数をチェックされない。
function AddNum(a, b){
return a + b;
}
AddNum(2); //エラーにならない
そのため、必要であればarguments.lengthで渡された引数の数を自分でチェックしてあげる。
function AddNum(a, b){
if(arguments.length != 2){
throw new Error('引数の数が間違っています');
}
return a + b;
}
引数名を指定して関数呼び出し
連想配列を利用して、PHPのような引数名を指定した受け渡しを実現する。
function MemberAppeal(args){
var name = args.name;
var age = args.age;
console.log('私の名前は' + name + '。年齢は' + age + 'です');
}
MemberAppeal( { name:'田中', age:18 } );
ES6ならば、分割代入を利用したオブジェクト引数名指定を使ってもっと簡潔に書ける。
クロージャ
関数内に定義したローカル変数を生かし続ける。
function closure(val){
var count = val;
var closureFunc = function(){
return ++count;
}
return closureFunc;
}
var myClosure = closure(100);
console.log(myClosure()); //101
console.log(myClosure()); //102
console.log(myClosure()); //103
closure関数の戻り値としてclosureFunc関数が返っている。
closureFunc関数ではローカル変数countを参照している。
戻り値として返ったclosureFunc関数の参照をmyClosureグローバル変数に格納している。
ローカル変数countまでの参照が切れていないためガベージコレクションが実行されずcount変数はローカル変数でありながらも開放されない。
当然、クロージャは複数生成すれば、各々は独立している。
var myClosure = closure(100);
var myClosure2 = closure(200);
console.log(myClosure()); //101
console.log(myClosure()); //102
console.log(myClosure2()); //201
console.log(myClosure2()); //202
無名関数
let total = function(a, b){
return a + b;
}
無名関数(アロー関数)(ES6)
アロー関数による表記(ES6)
「(引数) => 本体」
let total = (a, b) => {return a + b};
本体が一文しか無いなら{}は省略可能で、returnも省略できる。
let total = (a, b) => a + b;
引数がひとつの場合は括弧の省略も出来る。
let total = a => a*2;
引数が無い場合は、括弧の省略はできない。
空の括弧を付ける。
let total = () => 10*10;
オブジェクトを戻り値で返す時は()でくくる。
let obj = () => ({name:'マイケル'});
こちらは{}がブロックを、name:がラベル構文と見なされてしまうのでNG。
let obj = () => {name:'マイケル'};
※アロー関数でthisは、アロー関数自身が宣言された場所で固定される。
※そのため、コンストラクタとしては使用できない。