関数を定義する
JavaScriptでは、関数は次のように定義される。
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
上記のabs()
関数の定義は次のとおりです。
- functionは関数を定義することを示す。
- absは関数の名前です。
- (x)のxは関数のパラメーターであり、複数のパラメーターは[,]で区切られている。
- {...}の間のコードは関数本体であり、複数のコードを含める。
要注意:関数本体内のステートメントが実行される時、return
が実行されると、関数が実行完了、結果が返される。 したがって、条件付きの判断とループにより、関数内に非常に複雑なロジックが実装できる。
return
ステートメントがない場合、関数は実行後に結果も返しますが、結果はundefined
です。
JavaScript関数もオブジェクトであるため、上記で定義したabs()
関数は関数オブジェクトであり、関数名abs
は関数を指す変数と見られる。
したがって、関数を定義する2番目の方法は次のとおりです。
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
};
このように、function(x){...}
は無名関数であり、関数名はありません。 ただし、この無名関数は変数abs
に割り当てられているため、変数abs
を介して関数を呼び出すことができる。
上記の2つの定義は完全に同じです。
関数を呼び出す
関数を呼び出す時に、パラメーターを順序で渡す。
abs(10); // 10を返す
abs(-8); // 8を返す
定義されているよりも少ないパラメータを渡しても問題はありません。
abs(); // NaNを返す
この時点、abs(x)
関数のパラメーターx
はundefined
受信され、結果はNaN
です。
変数のスコープ
JavaScriptでは、var
宣言された変数はスコープされる。
変数が関数本体の内部で宣言されている場合、変数のスコープは関数本体全体であり、変数を関数の外部で参照することはできません。
function foo() {
var x = 1;
x = x + 1;
}
x = x + 2; // ReferenceError! 関数の外部で変数xを参照できません。
2つの異なる関数が同じ変数を宣言する場合、その変数はそれぞれの関数の本体内でのみ機能する。つまり、異なる関数内の同じ名前の変数は互いに独立しており、互いに影響を与えません。
function foo() {
var x = 1;
x = x + 1;
}
function bar() {
var x = 'A';
x = x + 'B';
}
JavaScript関数はネスト(関数内関数)できるため、この時点で、内部関数は外部関数に定義された変数にアクセスできますが、その逆はできません。
function foo() {
var x = 1;
function bar() {
var y = x + 1; // barはfooの変数xにアクセスできる
}
var z = y + 1; // ReferenceError! fooはbarの変数yにアクセスできません
}
内部関数と外部関数の変数名が同じ名前の場合はどうなりますか?それをテストしてみましょう:
function foo() {
var x = 1;
function bar() {
var x = 'A';
console.log('x in bar() = ' + x); // 'A'
}
console.log('x in foo() = ' + x); // 1
bar();
}
foo();
// 結果:
// x in foo() = 1
// x in bar() = A
これは、JavaScript関数が変数を探すときに独自の関数の定義から始まり、「内部」から「外部」まで検索することを示している。内部関数が外部関数と同じ名前の変数を定義している場合、内部関数の変数は外部関数の変数をシールドする。