|
|
|
# JavaScript の基本: メソッドと関数
|
|
|
|
|
|
|
|
![JavaScript Basics - Functions](/sketchnotes/webdev101-js-functions.png)
|
|
|
|
> Sketchnote by [Tomomi Imura](https://twitter.com/girlie_mac)
|
|
|
|
|
|
|
|
## レッスン前の小テスト
|
|
|
|
[レッスン前の小テスト](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/9?loc=ja)
|
|
|
|
|
|
|
|
コードを書くことを考えるとき、私たちは常にコードが読みやすいようにしたいと考えています。直感的ではないように聞こえるかもしれませんが、コードは書かれた回数よりも何度も読まれます。コードを確実にメンテナンスできるようにするための開発者のツールボックスの中心的なツールの一つが **関数** です。
|
|
|
|
|
|
|
|
[![Methods and Functions](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Methods and Functions")
|
|
|
|
|
|
|
|
## 関数
|
|
|
|
|
|
|
|
コアとなるのは、関数は必要に応じて実行できるコードのブロックです。これは、同じタスクを何度も実行する必要がある場合に最適です。ロジックを複数の場所に複製するのではなく (時間が来たときに更新するのが困難になります)、1つの場所に集中させ、実行する操作が必要なときにいつでも呼び出すことができます - 他の関数から関数を呼び出すこともできます!
|
|
|
|
|
|
|
|
他の関数から関数を呼び出すこともできます!同じくらい重要なのは、関数に名前を付ける機能です。これは些細なことのように思われるかもしれませんが、名前をつけることでコードのセクションを簡単に文書化することができます。これはボタンのラベルのようなものと考えることができます。もし "Cancel timer" と書かれたボタンをクリックすると、それが時計の動作を止めようとしていることがわかります。
|
|
|
|
|
|
|
|
## 関数の作成と呼び出し
|
|
|
|
|
|
|
|
関数の構文は次のようになります:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function nameOfFunction() { // 関数の定義
|
|
|
|
// 関数の定義/中身
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
挨拶を表示する関数を作ろうと思ったら、こんな感じになるかもしれません:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function displayGreeting() {
|
|
|
|
console.log('Hello, world!');
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
関数を直接呼び出したい (または別スレッド、別コンテキストの関数を呼び出したい) ときはいつでも、関数名の後に `()` をつけます。関数を呼び出す前に定義しても後に定義してもよいという事実は注目に値します; JavaScript コンパイラがそれを見つけてくれます。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
// 関数の呼び出し
|
|
|
|
displayGreeting();
|
|
|
|
```
|
|
|
|
|
|
|
|
> **注:** **メソッド** として知られている特殊なタイプの関数がありますが、これはすでに使ったことがあるでしょう!実際、上のデモではこれを見ました。実際、上のデモでは `console.log` を使っています。メソッドが関数と異なるのは、メソッドがオブジェクト (この例では `console`) にアタッチされているのに対し、関数はフリーフローティングです。多くの開発者がこれらの用語を互換性を持って使っているのを耳にするでしょう。
|
|
|
|
|
|
|
|
### 関数のベストプラクティス
|
|
|
|
|
|
|
|
機能を作成する際に留意すべきベストプラクティスがいくつかあります。
|
|
|
|
|
|
|
|
- いつものように、関数が何をするのかがわかるように、記述的な名前を使用します
|
|
|
|
- **キャメルケーシング** を使用して単語を組み合わせます
|
|
|
|
- 関数を特定のタスクに集中させます
|
|
|
|
|
|
|
|
## 関数への情報の受け渡し
|
|
|
|
|
|
|
|
関数をより再利用可能なものにするためには、情報を渡したいことがよくあります。上の `displayGreeting` の例を考えてみると、**Hello, world!** しか表示されません。これでは、作成できる関数の中で最も有用なものとは言えません。挨拶する相手の名前を指定できるようにするなど、もう少し柔軟にしたい場合は、**パラメータ** を追加することができます。パラメータ (**引数** と呼ばれることもあります) は、関数に送られる追加情報です。
|
|
|
|
|
|
|
|
パラメータは定義部分に括弧内に記載されており、以下のようにカンマで区切られています:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function name(param, param2, param3) {
|
|
|
|
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
名前を受け付けてそれを表示するように `displayGreeting` を更新することができます。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function displayGreeting(name) {
|
|
|
|
const message = `Hello, ${name}!`;
|
|
|
|
console.log(message);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
関数を呼び出してパラメータを渡すときは、括弧内で指定します。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
displayGreeting('Christopher');
|
|
|
|
// 実行時に "Hello, Christopher!" と表示される
|
|
|
|
```
|
|
|
|
|
|
|
|
## 初期値
|
|
|
|
|
|
|
|
より多くのパラメータを追加することで、関数をさらに柔軟にすることができます。しかし、すべての値を指定する必要がない場合はどうでしょうか?挨拶の例に倣って、名前は必須のままにしておくこともできますが (誰に挨拶しているのかを知る必要があります)、挨拶自体は必要に応じてカスタマイズできるようにしたいと考えています。誰かがカスタマイズしたくない場合は、代わりにデフォルト値を指定します。パラメータにデフォルト値を設定するには、変数に値を設定するのと同じ方法 - `parameterName = 'defaultValue'` でパラメータを設定します。完全な例を見るには、以下を参照してください。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function displayGreeting(name, salutation='Hello') {
|
|
|
|
console.log(`${salutation}, ${name}`);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
関数を呼び出すときに、`salutation` に値を設定するかどうかを決めることができます。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
displayGreeting('Christopher');
|
|
|
|
// "Hello, Christopher" と表示されます。
|
|
|
|
|
|
|
|
displayGreeting('Christopher', 'Hi');
|
|
|
|
// "Hi, Christopher" と表示されます。
|
|
|
|
```
|
|
|
|
|
|
|
|
## 戻り値
|
|
|
|
|
|
|
|
今までは、私たちが作った関数は常に [console](https://developer.mozilla.org/ja/docs/Web/API/console) に出力されていました。特に他のサービスを呼び出す関数を作成する場合には、これがまさに求めているものになることがあります。しかし、計算を実行するヘルパー関数を作成して値を返し、それを他の場所で使えるようにしたい場合はどうしたらいいでしょうか?
|
|
|
|
|
|
|
|
これを行うには、**戻り値** を使用します。戻り値は関数から返され、文字列や数値などのリテラル値を格納するのと同じように変数に格納することができます。
|
|
|
|
|
|
|
|
関数が何かを返す場合は、キーワード `return` が使用されます。キーワード `return` は、以下のように返されるものの値や参照を期待しています:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
return myVariable;
|
|
|
|
```
|
|
|
|
|
|
|
|
挨拶メッセージを作成して、その値を呼び出し元に返す関数を作成することができます。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function createGreetingMessage(name) {
|
|
|
|
const message = `Hello, ${name}`;
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
この関数を呼び出すときには、変数に値を格納します。これは、(`const name = 'Christopher'` のように) 変数に静的な値を設定するのと同じ方法です。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const greetingMessage = createGreetingMessage('Christopher');
|
|
|
|
```
|
|
|
|
|
|
|
|
## 関数のパラメータとしての関数
|
|
|
|
|
|
|
|
プログラミングのキャリアを積んでいくと、関数をパラメータとして受け入れる関数に出くわすようになります。この巧妙なトリックは、何かがいつ発生するか、または完了するかわからないが、レスポンスとして操作を実行する必要があることがわかっている場合によく使われます。
|
|
|
|
|
|
|
|
例として、タイマーを開始し、タイマーが完了したらコードを実行する [setTimeout](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) を考えてみましょう。どのようなコードを実行したいかを伝える必要があります。関数としては完璧な仕事のように聞こえます。
|
|
|
|
|
|
|
|
以下のコードを実行すると、3秒後に **3秒が経過しました** というメッセージが表示されます。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function displayDone() {
|
|
|
|
console.log('3秒が経過しました');
|
|
|
|
}
|
|
|
|
// タイマーの値はミリ秒単位
|
|
|
|
setTimeout(displayDone, 3000);
|
|
|
|
```
|
|
|
|
|
|
|
|
### 匿名関数
|
|
|
|
|
|
|
|
もう一度、作ったものを見てみましょう。一度だけ使用される名前の関数を作成しています。アプリケーションが複雑になるにつれて、一度しか呼ばれない関数をたくさん作ることになるでしょう。これは理想的ではありません。しかし、常に名前を指定する必要はありません。
|
|
|
|
|
|
|
|
パラメータとして関数を渡すときは、事前に関数を作成する必要はなく、代わりにパラメータの一部として関数を作成することができます。同じ `function` キーワードを使用しますが、代わりにパラメータとしてビルドします。
|
|
|
|
|
|
|
|
上のコードを書き換えて、匿名の関数を使用してみましょう。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
setTimeout(function() {
|
|
|
|
console.log('3秒が経過しました');
|
|
|
|
}, 3000);
|
|
|
|
```
|
|
|
|
|
|
|
|
新しいコードを実行すると、同じ結果が得られることに気づくでしょう。関数を作りましたが、名前をつける必要はありませんでした。
|
|
|
|
|
|
|
|
### ファットアロー関数
|
|
|
|
|
|
|
|
多くのプログラミング言語 (JavaScript を含む) に共通するショートカットは、**アロー** または **ファットアロー** 関数と呼ばれるものを使用することです。これは、矢印のように見える `=>` という特殊なインジケータを使用します。`=>` を使うことで、`function` キーワードを省略することができます。
|
|
|
|
|
|
|
|
ファットアロー関数を使って、もう一度コードを書き換えてみましょう。
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
setTimeout(() => {
|
|
|
|
console.log('3 seconds has elapsed');
|
|
|
|
}, 3000);
|
|
|
|
```
|
|
|
|
|
|
|
|
### それぞれの戦略を使うとき
|
|
|
|
|
|
|
|
関数をパラメータとして渡すには3つの方法があることがわかりましたが、それぞれをいつ使うか迷っているかもしれません。関数を複数回使用することがわかっているのであれば、通常通りに作成してください。1 つの場所だけで使用する場合は、一般的には匿名関数を使用するのがベストです。太いアロー関数を使うか、より伝統的な `function` 構文を使うかはあなた次第ですが、最近の開発者の多くは `=>` を好んでいることに気づくでしょう。
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 🚀 チャレンジ
|
|
|
|
|
|
|
|
関数とメソッドの違いを一文で表現できますか?試してみてください。
|
|
|
|
|
|
|
|
## レッスン後の小テスト
|
|
|
|
[レッスン後の小テスト](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/10?loc=ja)
|
|
|
|
|
|
|
|
## 復習と自己学習
|
|
|
|
|
|
|
|
コードベースで使われることが多くなってきているアロー関数については、[もう少し読み込んでみる](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)価値があると思います。この構文で関数を書いて、それを書き換える練習をしてみましょう。
|
|
|
|
|
|
|
|
## 課題
|
|
|
|
|
|
|
|
[関数で楽しむ](assignment.ja.md)
|