Javascriptを学習する上で、「関数」や「引数」の書き方にバリエーションがある点が分かり難く、きちんと理解しないままでコードを読み進めてもなかなか頭に入らなかったりしています。そこで、Javascriptの関数のさまざまな書き方についてAIに教えてもらうことにしました。
関数宣言(Function Declaration)
function greet(name) {
return `Hello, ${name}!`;
}コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
function greet(name) {
return `Hello, ${name}!`;
}
alert(greet("world"));
</script>
</body>
</html>
特徴:
- 「関数の巻き上げ(hoisting)」がある → 宣言より前に呼び出せる。
- グローバルスコープやブロックスコープ内で定義できる。
関数式(Function Expression)
const greet = function(name) {
return `Hello, ${name}!`;
};コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
const greet = function(name) {
return `Hello, ${name}!`;
};
alert(greet("world"));
</script>
</body>
</html>
特徴:
- 関数が変数に代入されている。
- 巻き上げされない → 宣言より後でしか使えない。
- 無名関数(名前のない関数)が一般的だが、名前付きも可能。
次のような名前付きの記述も可能
const greet = function greetFunc(name) {
return `Hello, ${name}!`;
};コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
const greet = function greetFunc(name) {
return `Hello, ${name}!`;
};
alert(greet("world"));
console.log(typeof greetFunc);
</script>
</body>
</html>
特徴:
- greetFuncは関数の「内部名」です。
- greetは外部(スコープ)で使用される変数名です。
- 関数はgreet経由で呼び出せますが、関数本体の中では greetFuncという名前も使えます(※再帰などに使われる)。
アロー関数(Arrow Function)
const greet = (name) => {
return `Hello, ${name}!`;
};
//または、処理が1行だけなら省略可能
const greet = name => `Hello, ${name}!`;コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
const greet = (name) => {
return `Hello, ${name}!`;
};
alert(greet("world"));
</script>
</body>
</html>
特徴:
thisの束縛がない(親スコープのthisを引き継ぐ)→ コールバック関数などで便利。argumentsオブジェクトが使えない。- コンストラクタとしては使えない(
newできない)。
コールバック関数
function HelloTxt(callback) {
const name = prompt("Helloと言ったら何が続く?");
callback(name);
}
HelloTxt(function(name) {
alert("Hello" + name + "!");
});コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
function HelloTxt(callback) {
const name = prompt("Helloと言ったら何が続く?");
callback(name);
}
HelloTxt(function(name) {
alert("Hello" + name + "!");
});
</script>
</body>
</html>
特徴:
- 他の関数に引数として渡される関数のこと
- ある処理が完了した後に実行される関数として使われることが多い。
- 非同期処理やイベント処理、配列操作などでよく利用される。
再帰関数
function sum(n) {
if (n === 1) return 1;
return n + sum(n - 1);
}
console.log(sum(5)); // 結果:15(1+2+3+4+5)コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
function sum(n) {
if (n === 1) return 1;
return n + sum(n - 1);
}
console.log(sum(5));
</script>
</body>
</html>
特徴:
- 自分自身を呼び出す関数のこと
- 計算しようとしている問題を小さくまとめて自分を呼び出し、その返り値を使って答えを返す。
- 繰り返し処理が必要だがfor文やwhile文が適さない場合などに利用される。終了条件(ベースケース)を必ず設定することが大切。
メソッド定義(オブジェクトのプロパティとして)
const helloTxt = {
name: "World",
greet() {
return `Hello, ${this.name}`;
}
};コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
const helloTxt = {
name: "World",
greet() {
return `Hello, ${this.name}`;
}
};
alert(helloTxt.greet());
</script>
</body>
</html>
特徴:
thisがオブジェクトを指す。- クラスやオブジェクトリテラルでの記述に使われる。
コンストラクタ関数
function helloTxt(name) {
this.name = name;
this.greet = function() {
return `Hello, ${this.name}`;
};
}
const p = new helloTxt("World");コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
function helloTxt(name) {
this.name = name;
this.greet = function() {
return `Hello, ${this.name}`;
};
}
const p = new helloTxt("World");
alert(p.greet());
</script>
</body>
</html>
特徴:
new演算子でインスタンスを生成。thisは生成されたオブジェクトを指す。
Generator関数
function* helloTxt() {
yield 1_Hello!;
yield 2_Hello!;
yield 3_Hello!;
}コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
function* helloTxt() {
yield "1_Hello!";
yield "2_Hello!";
yield "3_Hello!";
}
for (const val of helloTxt()) {
console.log(val);
}
</script>
</body>
</html>
実行結果
※ブラウザの「JavaScriptコンソール」を開いてログを見ると表示されます。
特徴:
function*で定義。yieldで値を順に返す。- 繰り返し処理を制御(
next())で制御可能。
async関数
async function greet() {
return "Hello World!";
}コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<script>
async function greet() {
return "Hello World!";
}
greet().then(msg => console.log(msg));
</script>
</body>
</html>
実行結果
※ブラウザの「JavaScriptコンソール」を開いてログを見ると表示されます。
特徴:
asyncで非同期関数になる。awaitでPromiseの結果を待てる。
まとめ
| 書き方 | 巻き上げ | thisの挙動 | new可能 | 使用場面例 |
|---|
| Function宣言 | 〇 | 通常(呼び出し元) | 〇 | 基本の関数定義 |
| Function式 | × | 通常 | 〇 | 変数に関数を入れたい時 |
| アロー関数 | × | 親のthisを継承 | × | コールバックなど |
| メソッド定義 | × | オブジェクトのthis | × | クラスやオブジェクト |
| コンストラクタ | 〇 | 新しいインスタンス | 〇 | インスタンス生成 |
| Generator関数 | 〇 | 通常 | × | イテレータ処理 |
| async関数 | 〇 | 通常 | × | 非同期処理 |
「メソッド定義」あたりからだんだん複雑になって行って「ついて行けないよ~」という感じがしましたが、こういう例があるのだなとあらかじめ分かっていると、難しい局面に差し掛かった時に何らかの判断のヒントになりそうな気がしました。
わりと古いJavascript初級とか入門という書籍を読んだりしていますが、そこでGenerator関数やasync関数という言葉を目にすることはあまりなかったので、AIの提示する「関数の書き方」は難しいけれど読んでいて楽しめました。
AIを使ってプログラミング学習するのはかなり良さそうな気がする反面、インターネット上にあまり情報がなさそうな分野(例えば、ニッチな生き物の名前や生態、社会的な時事問題など)では、AIは結構いいかげんな回答をしている様子が散見されるので、どこまで信用していいのか…と油断ができません。

Reply