戻り値
- 関数の値は
return
を使って呼び出し元に戻します。- 関数から
return
で戻らない場合や値が指定されないreturn
で戻る場合、関数が戻す値はundefined
となる。 - 関数は任意の型を返すことができる。
- 関数から
呼び出しと参照
JavaScript
で関数はオブジェクトです。- 関数を関数の引数として渡すことができる。
- 関数を変数に代入することができる。
種類 | 記述方法 | 詳細 |
---|---|---|
呼び出し | 関数名に()をつける | 関数の本体が実行される |
参照 | 関数名のみ | 実行されない |
function getGreeting() { return "Hello World!"; } //呼び出し console.log(getGreeting()); // "Hello World!" //参照 console.log(getGreeting); /* ƒ getGreeting() { return "Hello World!"; } */ // 関数を変数に代入する(関数の名前を変更する) const f = getGreeting; console.log(f()); // "Hello World!" // 関数をオブジェクトのプロパティに代入する const o = {}; o.f = getGreeting; console.log(o.f()); // "Hello World!" // 配列の要素として関数を代入する const arr = [1,2,3]; arr[1] = getGreeting; console.log(arr[1]()); // "Hello World!"
関数の引数
- 仮引数がプリミティブ型の変数の場合、仮引数に対し関数内で変更を加えても呼び出し元の値には変化が起こらない。
function f(x){ console.log(`関数内1:${x}`); x = 5; console.log(`関数内2:${x}`); } const x =10; console.log(`関数外1:${x}`); f(x); console.log(`関数外2:${x}`); /* // 表示内容 関数外1:10 関数内1:10 関数内2:5 関数外2:10 */
- 仮引数がオブジェクト型の変数の場合、関数内部で別オブジェクトを参照する記述を実行するまでは元のオブジェクトを参照する。
- 仮引数で受け取ったオブジェクトの既存キーの値を変更する:呼び出し元と同一のオブジェクトを参照
- 仮引数で受け取ったオブジェクトにキーを追加:別の新しいオブジェクトを参照
function f1(o){ console.log(` f1-1:${o.message}`); o.message = "f1内で書き換え"; console.log(` f1-2:${o.message}`); } function f2(o){ console.log(` f2-1:${o.message}`); o ={ message:"f2内で同名オブジェクト追加", }; console.log(` f2-2:${o.message}`); } function f3(o){ console.log(` f3-1:${o.message}`); o.message = "f3内で別名オブジェクト追加"; o.message2 = "f3内で別名オブジェクト追加"; console.log(` f3-2:${o.message}`); } function f4(o){ console.log(` f4-1:${o.message}`); o.message = "f4内で別名オブジェクト削除"; delete o.message2; console.log(` f4-2:${o.message}`); } let o ={ message:"初期値", }; console.log(`呼び出し元1:${o.message}`); f1(o); console.log(`呼び出し元2:${o.message}`); f2(o); console.log(`呼び出し元3:${o.message}`); f3(o); console.log(`呼び出し元4:${o.message}`); f4(o); console.log(`呼び出し元5:${o.message}`); /* 呼び出し元1:初期値 f1-1:初期値 f1-2:f1内で書き換え 呼び出し元2:f1内で書き換え f2-1:f1内で書き換え f2-2:f2内で同名オブジェクト追加 呼び出し元3:f1内で書き換え f3-1:f1内で書き換え f3-2:f3内で別名オブジェクト追加 呼び出し元4:f3内で別名オブジェクト追加 f4-1:f3内で別名オブジェクト追加 f4-2:f4内で別名オブジェクト削除 呼び出し元5:f4内で別名オブジェクト削除 */
引数と関数
- JavaScriptでは、関数は名称のみで区別される(引数の数によらない)
- すべての関数は任意個の引数を指定して呼び出すことができる。
- 引数へ値をセットする際に分割代入が可能
- 呼び出し側で関数定義側が用意している引数が指定されなかった場合、
undefined
が指定されたものとして扱われる。
- 関数定義側は呼び出し側で引数がセットされなかった時のためのデフォルト引数を要しすることができる。
function f(a,b="default",c=3){ return `${a} - ${b} - ${c}`; } let o ={ message:"初期値", }; console.log(f(5,6,7)); // 5 - 6 - 7 console.log(f(5,6)); // 5 - 6 - 3 console.log(f(5)); // 5 - default - 3 console.log(f()); // undefined - default - 3
オブジェクトのメソッド
- オブジェクトのプロパティとして指定される関数のことをメソッドという。
const o = { name: "Takeshi", message: function(){return "Hello!";}, } console.log(o.name); // Takeshi console.log(o.message()); // Hello! // 上記を省略記法(ショートハンド)で表現する const o2 = { name: "Takeshi", message(){return "Hello!";}, } console.log(o2.name); // Takeshi console.log(o2.message()); // Hello!
this
- 「オブジェクト」と「オブジェクトのプロパティである関数(メソッド)」を束縛する。
const o = { name: "Takeshi", message(){return `Hello! My name is ${this.name}`;}, } const message = o.message; console.log(message === o.message); // true console.log(o.message()); // "Hello! My name is Takashi" console.log(message); // ƒ message(){return `Hello! My name is ${this.name}`;}
関数式と無名関数
関数式
とは関数宣言に対し、関数名を省略する記法のコト関数式
は値をとして関数を返す関数式
は変数
などに代入することが可能関数式
はすぐに呼び出すことも可能
関数式
と関数宣言
の違いは実質的にはない- 周囲の文脈を把握する必要がある
const f = function(){ // ... }
アロー演算子
- 無名関数の一種
- 無名関数を引数に渡す場合によく利用される
特徴
function
という単語を省略できる。- 引数が一つならば
(
と)
を省略できる。 - 関数本体が一つの式となる場合、
{
と}
、それにreturn
を省略できる。
通常の関数とは異なる点
this
が他の変数と同様に、語彙的に束縛される- オブジェクトのコンストラクタとして使えない
arguments
が使えない
const f1_1 = function(){ return "Hello!";} const f1_2 = () => "Hello!"; console.log(f1_1()); // Hello! console.log(f1_2()); // Hello! const f2_1 = function(name){ return `My name id ${name}`;} const f2_2 = name => `My name id ${name}`; console.log(f2_1("Takeshi")); // My name id Takeshi console.log(f2_2("Takeshi")); // My name id Takeshi const f3_1 = function(a,b){ return a + b;} const f3_2 = (a,b) => a+b; console.log(f3_1(3,5)); // 8 console.log(f3_2(3,5)); // 8
call、apply、bind
call
- すべての関数に対して利用できるメソッド
this
を特定の値に指定したうえで、関数を呼び出すcall
の第一引数にはthis
を束縛したい値を指定する- 残りの引数には呼び出す関数の引数を入れる
const taro = {name :"Taro"}; const hanako = {name :"Hanako"}; // 通常はthisは使用できない function greet(){ return `My name is ${this.name}`; } console.log(greet.call(taro)); // My name is Taro console.log(greet.call(hanako)); // My name is Hanako console.log(greet()); // error
apply
- 引数を配列として受け取る(
call
は引数を直接受け取る)- 既に、関数が用意されていて、その値を関数の引数として使いたい場合
const arr = [2,3,-5,15,7]; console.log(Math.min.apply(null,arr)); // -5 console.log(Math.max.apply(null,arr)) // 15; // スプレッド演算子を利用した場合 console.log(Math.min.apply(...arr)); // -5 console.log(Math.max.apply(...arr)) // 15;
- 以下の
apply
はスプレッド演算子を使用してcall
に置き換えることが可能
const taro = {name :"Taro"}; const taro2 = {name :"Taro"}; const arr = [2004,"student"]; function update(birthyear,occupation){ this.birthyear = birthyear; this.occupation = occupation; }; // applyの場合 update.apply(taro,arr); console.log(taro); // {name: "Taro", birthyear: 2004, occupation: "Student"} update.call(taro2,...arr); console.log(taro2); // {name: "Taro", birthyear: 2004, occupation: "Student"}
bind
this
の値をある関数と永続的に結びつけることができる。- 一度
bind
でセットされた値は、call
・apply
・別のbind
とも結びつく
- 一度