Function (関数)
JavaScript において関数を定義するには function ステートメントまたは Function コンストラクターを使用します。function ステートメントによって Function オブジェクトが生成されます。
Function オブジェクトはリテラル値で、変数に代入したり、引数として関数に渡したりすることができます。また、オブジェクトのメンバにすることもでき、その場合はメソッドとも呼ばれています。
function example_(){
...
}
let example_ = function(){
...
}
アロー演算子を使って関数式として定義することもできます。
let example_ = ()=>{
...
}
関数とは、複数の処理をひとつの手続きにしたものです。関数を利用することで似たような処理を何度も描く必要がなくなります。
関数には、引数という関数内で処理するための値を渡すことができます。
引数をパラメーターともいいます。そのために関数にパラメータを渡す、関数がパラメータを受取るといったりします。
引数を調べるためには、arguments オブジェクトを利用します。引数の数とその値を取得することができます。
以降では以下の項目について説明しています。
サブルーチン、プロシージャ
JavaScript において Functionはサブルーチンやプロシージャが作成できます。JavaScript ではどちらかというハッキリとした区別はないのですがコンピューター用語に習って解説しています。
値を返すものをサブルーチン
といいます。値を返さないものはプロシージャ
と呼びます。JavaScriptでは、サブルーチン
やプロシージャ
はreturnステートメントがあるか/ないかによります。
// サブルーチンの例
function example_() {
...
return( foo ) // returnがある
}
// プロシージャの例
function example_() {
... // returnがない
}
引数
引数とは関数にデータを渡す方法で、パラメーターと呼ばれます。
function example_(a, b) {
...
return( a + b );
}
let answer_ = example_( 1, 1 ); // 2 が返ってくる
引数の扱いで気を付けなければならないことがあります。以下の例を見てください。
function example_(a) {
console.log( "代入前 : ${a}" );
a = 100;
console.log( "代入後 : a" );
}
let a = 0;
console.log( "呼び出し前 : ${a}" );
example_( a );
console.log( "呼び出し後 : ${a}" );
例を実行すると以下のように表示されます。
呼び出し前 : 0 代入前 : 0 代入後 : 100 呼び出し後 : 0
関数の中で a の値を変更しましたが、関数の呼び出し後も a の値に変更はありません。
これは、関数の中での変数と呼び出し元で宣言された変数は別のものとして扱われるためです。変数の参照範囲であるスコープの違いによるものです。
関数の中で同じ変数名があったとしても関数の中で宣言されたら、別の変数として扱われます。それは引数に関しても同じで別の変数として扱われます。これを仮引数
とも呼ばれます。
引数とオブジェクト
引数にオブジェクトを渡すこともできます。この場合、オブジェクトのメンバの値を関数内で変更することができます。
const animal = {
name: cat;
old: 3;
}
const change_old_animal = function( object_animal, new_old ){
object_animal.old = new_old
}
console.log( animal.old );
change_old_animal( animal, 10 );
console.log( animal.old );
結果は以下のようになります。
> 3 > 10
関数の引数としてオブジェクトを指定することができ、そのメンバの値を変更することができます。
引数として渡されたオブジェクトはその本体の参照が渡されるため、そのメンバやメンバの値を関数内で変更することができます。
引数の数
JavaScript では引数の数が違っても同じ名称の関数なら同じと扱われます。
C 言語では以下の関数は別の関数としてみなされます。
void example_(); void example_( int a, int b ); void example_( char c );
JavaScript ではこのような区別はなく、同じ名称の関数なら同じ関数とみなします。
引数の数に関しても柔軟性があり、定義された引数の数より少なく渡されたら undefined で補完します。
例えば以下のような example_() 関数において、定義された引数より少ない数で関数を呼び出します。
function example_(a, b, c) {
console.log( c ); // c は undefined になる
...
}
...
let answer_ = example_( 1, 2 );
渡された引数が足らない分は undefined になります。
引数の有無判別
関数の引数が渡されているか/否かは undefined リテラルによって判別できます。値とデータタイプが等しいかを比較する比較演算子"==="を使います。
function example_(a, b) {
if (b === undefined) {
alert("2番目のパラメータがありません");
}
...
}
...
let answer_ = example_(1);
undefined は初期値がないという意味です。値が無いという意味では null もあります。引数の値が null である場合もあります。
値がない場合という意味では null を使ってもよいかもしれません。
関数式
関数は変数に代入する形で定義することもできます。この場合は、関数式といいます。
function example( a, b, c ){
...
}
上記の関数の定義を関数式で宣言します。
const example_ = function( a, b, c ){
...
}
右辺では無名の関数を宣言しています。この無名の関数を左辺に代入しています。
右辺のような無名の関数を無名関数
といい、関数リテラルとして扱います。この宣言から無名関数
が作成できることが分かりますが、ここでは詳しく解説しません。
以下のようにアロー関数で関数式を定義することもできます。
アロー関数で宣言
今度は、アロー関数で宣言してみます。
const example_ = ( a, b, c ) => {
...
}
アロー関数の宣言いろいろ
{ }内のコードが1行のときは{ }カッコを付ける必要がありません。
const example_ = (prm001) => ...;
引数が1つのときは( )カッコを付けなくてもいいです。
const example_ = prm001 => {
...
}
引数がない場合は( )カッコだけを付けます。
const example_ = () => {
...
}
アロー関数には以下の特徴があります。
- コンストラクターには使えない
- this が使える
- arguments といった展開演算子が使えない
変数への代入
関数は変数に代入することができます。ただし、関数を代入する場合は変数名だけを指定します。カッコ ( )
は要りません。
function example_(a, b) {
return( a + b );
}
cpy_example = example_; // cpy_example( a, b ) として利用できる
これは関数の参照と呼ばれます。もしもカッコ ( )
を付けて代入すると関数による答えが代入されます。
let answer_example = example( a, b ); // answer_example には a + b の値が代入される。
関数を代入する場合は関数の参照
を代入します。
this ステートメント
this ステートメントは、JavaScriptの実行時に現在参照しているオブジェクトを返します。
関数内で this によって呼び出されるオブジェクトはその関数が参照しているオブジェクトになります。
const _obj = {
obj_this: this, // デフォルトのグローバルオブジェクト、windowオブジェクトを参照
_function: function() {
return this; // この _obj 自体を参照
}
}
console.log( _obj.obj_this );
console.log( _obj._function() );
this の場所によってその値は変化することが分かります。this の使用には注意が必要です。
call、apply、bind による this の指定
call、apply、bind によって this を任意に指定することができます。
ただし、チームといった複数で開発を行う場合は call、apply、bind の使用は事前に計画をしておいた方がよいかもしれません。
詳しくはここでは割愛します。
関数はリテラル値
関数はリテラル値としての性質をもっています。
定義した関数の返り値を取得する方法には、代入に利用、引数に使用する、配列のデータとして、オブジェクトのプロパティとして利用できます。
さらに、関数自体を代入、引数として渡す(コールバック)、配列のデータとして、オブジェクトのプロパティにすることができます。
function example_() {
...
return( foo ) // returnがある
}
let a = example_();
let a = other_function( 1, 'a', example_() );
let list = [ 1, 2, 3, example_() ];
let object = {
name : 'a',
example_ : function(){
...
}
};
// object.example_( ) として利用
関数自体をリテラル値として利用することもできます。その場合は()
を付けません。
function example_() {
...
return( foo ) // returnがある
}
let a = example_; // a() という関数になる
let a = other_function( 1, 'a', example_ ); // 引数として関数が渡される // other_function() 内で 第3引数( ) として利用できる
let list = [ example_ ]; // list[0]( ) という使い方ができる
let object = {
name : 'a',
a : example_
};
// object.a( ) として利用できる
他にもクラスのメソッドとして利用できます。
コールバック関数
コールバック関数とは、引数として関数を渡す方法です。
引数として関数を渡す方法では、処理すべき関数を指定することができます。
繰り返しや現在の状態を監視しながら処理をする場合にコールバック関数が利用されています。
コールバック関数は、引数に関数名を指定します。コードの編集方法は以下のようになります。
function other_func(){
...
}
function example( callback ) {
...
// 引数で指定した関数が実行される
// この場合は other_func() になる
callback();
}
...
example( other_func ); // 関数名で指定
のように、関数名にカッコexample( other_func() );()
を付けて渡すと実行結果が引数になります。
Ajax などサーバーとの通信などにおいて処理の遅滞による不具合を解消することにコールバックは利用されます。
ブラウザはネットワークを介したサーバーと通信をしながら処理を行うために待ち時間が生じます。通信処理を待たないで次のコードを実行すると不具合が生じる場合があります。
通信処理を待たないでコードが続行されることで不具合が生じるのを防ぐために、コールバック関数を使います。
再帰関数
再帰関数とは関数から自身の関数を呼び出すものです。
再帰関数は自身の関数を呼び出すため無限ループします。上記の例では条件によってループを抜けるようにしています。この条件を終了条件
といいます。
再帰関数では必ず終了条件で抜け出せるようにします。
IIFE 即時関数
IIFE ( Immediately Invoided Function Expression ) は定義されたら実行される関数のことです。
構文は以下のようにカッコ () で囲んだ関数 functionステートメント になります。
const example_IIFE = ( function(){
...
})();
このように定義すると、関数が宣言されたところで1度目の実行が行われます。
以下で IIFE の実行例です。以下の確認
ボタンをクリックしてください。
Example
IIFE は、非同期コードとして使用することができます。
function(関数)のEventからの呼び出し
HTMLエレメント(DOM)のEventから呼び出すことができます。
<button onclick="example_()">...<button>
詳しくは、Event インターフェイスを参照してください。
Functionとクラス定義
Functionは、クラス定義もできます。
現在は class ステートメントを使用するのが一般的です。ちなみに、以下は過去の作成例です。
const example_ = function ( prm01, prm02,... ){
this.prm01 = prm01;
this.prm02 = prm02;
...
}
example_.prototype =
{
get_ExamplePrm : function(){
...
},
...
}
クラスについて詳しくはクラス
ページを参照してください。
