目次
関数とは何か
一言でいうと「ある処理に名前をつけて、何度でも呼び出せるようにしたもの」です。
関数を使わない書き方
console.log("Hello, Taro!");
console.log("Hello, Hanako!");
console.log("Hello, Jiro!");同じパターンを何度も書いていて、変更に弱い です。
関数でまとめる
function sayHello(name) {
console.log(`Hello, ${name}!`);
}
sayHello("Taro");
sayHello("Hanako");
sayHello("Jiro");function… 関数を定義するキーワードsayHello… 関数名name… 引数(パラメータ){ ... }の中 … 実際の処理(関数本体)
メリット:
- 「挨拶の処理を変えたい」ときは、
sayHelloの中だけ直せばOK - 何度でも再利用できる
関数宣言(function declaration)
基本形
function add(a, b) {
const result = a + b;
return result;
}
const sum = add(3, 5);
console.log(sum); // 8ポイント:
a,bは 仮引数(パラメータ)add(3, 5)の3,5は 実引数(引数)returnは「関数の結果」を呼び出し元に返す戻り値
→returnに到達した時点で関数の実行はそこで終わる
return が無いとき
function mul(a, b) {
console.log(a * b);
}
const result = mul(2, 3);
console.log("result:", result);出力イメージ:
6
result: undefinedmulにはreturnが無いので、戻り値はundefinedになる- コンソールに表示するのと、値として返すのは別物という意識が重要
関数式(function expression)
無名関数を変数に代入
const add = function (a, b) {
return a + b;
};
console.log(add(2, 3)); // 5- これは 「関数という値を add に代入している」 と考えます。
addは「関数型の変数」というイメージ。
関数宣言との違い(Hoisting)
関数宣言:
console.log(add(2, 3)); // 5(ここで呼んでも動く)
function add(a, b) {
return a + b;
}関数式:
// console.log(add(2, 3)); // ReferenceError or TypeError
const add = function (a, b) {
return a + b;
};
console.log(add(2, 3)); // 5- 関数宣言は スコープの先頭に巻き上げられる(Hoisting)
→ 宣言より前でも呼べる(strict mode でも動作は同じ) - 関数式は単なる「代入」です
→const add = ...より前では使えない(TDZ)
実務的には:
- 「後から読む人に分かりやすいか」で選ぶ
- 最近は「
const 関数名 = function/ アロー関数」のスタイルが好まれがちです
(再代入されないので安全)
デフォルト引数
引数が渡されなかったとき
function greet(name) {
console.log(`こんにちは、${name}さん`);
}
greet("Taro"); // こんにちは、Taroさん
greet(); // こんにちは、undefinedさん2回目は name に何も渡していないので undefined になります。
デフォルト値をつける
function greet(name = "ゲスト") {
console.log(`こんにちは、${name}さん`);
}
greet("Taro"); // こんにちは、Taroさん
greet(); // こんにちは、ゲストさんname = "ゲスト"が デフォルト引数- 引数が
undefinedのときにデフォルト値が使われる
複数引数の例:
function createUser(name = "名無し", age = 18) {
return { name, age };
}
console.log(createUser("Hanako", 25)); // { name: "Hanako", age: 25 }
console.log(createUser()); // { name: "名無し", age: 18 }残余引数 …args と arguments
可変長引数を受け取りたい
「引数が何個くるか分からない」関数を書きたいときがあります。
例:全部足す sum 関数
function sum(...numbers) {
// numbers は配列
let total = 0;
for (const n of numbers) {
total += n;
}
return total;
}
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4, 5)); // 15...numbersが 残余引数(rest parameters)- 「残りの引数をすべて配列にまとめる」という意味
残余引数の位置
残余引数は 最後の引数にしか置けません。
function sample(a, b, ...rest) {
// OK
}
function bad(...rest, a) {
// 構文エラー
}arguments オブジェクト(古いスタイル)
昔からある方法として、arguments オブジェクト があります。
function oldSum() {
console.log(arguments); // 配列っぽいオブジェクト
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(oldSum(1, 2, 3)); // 6特徴:
- 関数の中で暗黙に使える「配列風オブジェクト」
lengthとインデックスアクセスはできるが、
本物の配列ではない(mapなどは直接使えない)
対して、...args は最初から本物の配列になります。
arguments とアロー関数
アロー関数には 独自の arguments がありません。
const arrow = () => {
console.log(arguments); // ここで arguments を使うと外側のを参照してしまう
};そのため、「可変長引数を扱うアロー関数」は基本的に ...args を使います。
const sumArrow = (...nums) => {
return nums.reduce((acc, v) => acc + v, 0);
};実務的には:
- 新しく書くコードでは
argumentsではなく...argsを使う argumentsは「既存コードを読むために知っておく」くらいの立ち位置
関数は「値」として扱える
関数は「値」なので、変数に入れたり、他の関数に渡したり、関数から返したりできます。
変数に入れる
const greet = function (name) {
console.log(`Hi, ${name}`);
};
greet("Taro");引数として渡す(コールバック)
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
function logIndex(i) {
console.log("index:", i);
}
repeat(3, logIndex);
// index: 0
// index: 1
// index: 2repeatは「回数nと、実行する処理action」を受け取るactionに「関数」を渡すことで、処理をカスタマイズできる
アロー関数と組み合わせると:
repeat(3, (i) => {
console.log(`i=${i}`);
});この形は、配列の forEach / map / filter などで多用されます。
関数を返す関数
function createAdder(base) {
return function (x) {
return base + x;
};
}
const add10 = createAdder(10);
console.log(add10(5)); // 15
const add100 = createAdder(100);
console.log(add100(5)); // 105- 「関数が関数を返す」という構造
→ 後の クロージャ の章で深掘りします
ここでは、「JavaScript では関数も「普通の値」と同じように扱える」という感覚だけ持っておけばOKです。
コメント