Skip to content
This page has been auto-translated and may contain errors.View in English

関数

docs.scrimba.com

ショッピングカートの商品の価格を決めているとしましょう。数値を取って、税金を加え、四捨五入し、通貨記号でフォーマットします。次の商品、その次の商品でもそれを繰り返す必要があります。これらの4つのステップをあちこちにコピーするのは、バグの温床です。丸め処理を1ヶ所で修正しても、他の3つのコピーはまだ間違ったままです。関数を使えば、そのステップのブロックに一度名前を付けて、必要な時はいつでも実行できます。この章では、そのブロックの書き方、入力の与え方、そして値を取り出す方法について説明します。

関数の宣言と呼び出し

**関数**は、いつでも実行できる名前付きのコードブロックです。ステップを一度書いて、名前を付けたら、その名前で何度でも実行できます。

function キーワードで関数を作ります:

js
function greet() {
  console.log("Hi there");
}

これが全体の定義ですが、まだ何も起こっていません。関数を書くことはステップを保存するだけで、実行しません。実際に実行するには、その名前に続けて括弧を書いて関数を呼び出します:

js
greet(); // Hi there
greet(); // Hi there

2行、2つの挨拶、1つのコードブロックから。定義と呼び出しは別のものであり、これを混同するのが最初につまずく点です。

**関数**は、コードブロックを名前の下にまとめるので、必要に応じて実行できます。function キーワードで一度定義すれば、その後は何度でも呼び出せます:

js
function logDivider() {
  console.log("----------");
}

logDivider(); // ----------
logDivider(); // ----------

定義はステップをセットアップしますが、何も実行しません。関数は () で呼び出す時にのみ実行されます。名前だけ、logDivider は関数値であり、括弧がそれを呼び出します。この区別は、関数を受け渡し始めた時点で重要になります。なぜなら logDividerlogDivider() は2つの異なるものだからです。1つは関数で、もう1つはそれを実行した結果です。

関数は、名前に束縛された再利用可能なコードブロックです。ここでの function キーワードは関数宣言を作ります。これはスコープの上部に巻き上げられる名前付き関数なので、それを書いた行の上で呼び出しても機能します。

js
countdown(); // 機能する:宣言は巻き上げられる

function countdown() {
  console.log("Ready");
}

その巻き上げは宣言形式に固有です。この章で後に出てくる他の関数定義方法は同じ巻き上げを共有しません。名前と呼び出しは異なる値です。countdown は関数自体に評価され(保存、渡し、比較できます)、countdown() は関数を実行して生成されるものに評価されます。この2つを混同するのは、「なぜこれは undefined なのか」という混乱の大部分の原因であり、関数が他の関数の引数として渡され始める前に、この2つを分けておく習慣は構築する価値があります。

関数に対して、その機能を説明する明確な動詞的な名前(greetlogDivider)を付けてください。変数の命名の時と同じ注意深さで行います。10ヶ所で呼び出される関数は、その名前と同じくらいの可読性しかありません。

Juno関数の宣言と呼び出し 関数を書くことはステップを保存するだけで、実行しません。それを実行するには、括弧を付けた名前で呼び出します。greet() のように。この分割は最初は混乱していました。定義はレシピで、呼び出しは実際に料理するものです。同じ関数を好きなだけ何度でも呼び出せます。
Juno関数の宣言と呼び出し 関数の定義と呼び出しは2つの別のアクションです。function ブロックはステップをセットアップして、() を追加するまで何も実行しません。頭の中で greetgreet() をきちんと区別してください。1つは関数値で、もう1つはそれを実行した結果です。その違いは、関数をどこかに渡す時点で重要になります。
Juno関数の宣言と呼び出しfunction キーワードは宣言を作り、それは巻き上げられるので、それが置いてある場所より上で呼び出せます。これはこの形式に固有です。式とアロー関数は同じ方法では巻き上げられません。そして countdown は関数で、countdown() はその結果です。関数を値として受け渡し始めると、この区別の重要性は減ります。

パラメータと戻り値

関数は何かを入力できる時により有用です。入力する値は**パラメータ**です。括弧の中に記載される名前で、呼び出す際に渡すもののプレースホルダーになります。

js
function greet(name) {
  console.log("Hi " + name);
}

greet("太郎"); // Hi 太郎
greet("花子"); // Hi 花子

name はパラメータです。greet("太郎") と呼び出すと、テキスト "太郎" がその実行中の name にスロットインします。1つの関数、異なる結果、何を渡すかによって変わります。

これまでのところ、これらの関数は何かを出力します。多くの場合、後で使用できるように関数が値を返すことを望みます。それが return がすることです:

js
function double(number) {
  return number * 2;
}

const result = double(5);
console.log(result); // 10

return は関数から値を送り出します。double(5)10 になり、それを保存、出力、または渡すことができます。出力は画面に値を表示します。戻すことはそれをコードに戻して使い続けることができます。

関数は**パラメータを通じて入力を取ります。括弧の中の名前です。呼び出し時に渡す値は、それらを満たす引数**です。

js
function priceWithTax(price, rate) {
  return price + price * rate;
}

const total = priceWithTax(40, 0.2);
console.log(total); // 48

pricerate はパラメータです。400.2 はこの呼び出しの引数です。return ステートメントは、関数を呼び出したものに値を返すので、priceWithTax(40, 0.2)48 に評価され、それを total に保存できます。

ログ出力と戻すことの違いは、ピン留めする価値があります。console.log を呼び出す関数は何かを表示して undefined に評価されます。return を使う関数は、プログラムが使い続けることができる値を生成します。return はまた関数をすぐに終了させます。それの後の行は実行されません。return を完全に省略した場合、関数は依然として undefined を返すので、値を期待していて何ももらわなかった場合の一般的な驚きです。

パラメータは関数の名前付き入力です。引数は呼び出し時にそれらに束縛された具体的な値です。return ステートメントは関数の出力値を生成して実行をすぐに終了するので、早期終了として二重の役割を果たします:

js
function classify(score) {
  if (score < 0) {
    return "invalid";
  }
  if (score >= 60) {
    return "pass";
  }
  return "fail";
}

console.log(classify(72)); // pass
console.log(classify(-3)); // invalid

return は値を生成して関数を停止するので、一度ブランチが実行されると、その下のものは何も実行されません。その早期終了パターン(最初に検証してベイル、最後にメインケースを処理)は、深くネストされた条件分岐から身を守ります。

実際のコードで重要な区別は、値を返す関数と、副作用のみを生成する関数(コンソールへの書き込み、自分自身の外側の何かの変更)との間です。console.log は副作用を実行して関数は undefined に評価されます。return は呼び出し元が合成できる値を生成します。return がない関数、または何の後ろもない単独の return は、undefined を生成します。ログのみの関数から戻された値に届くのは頻繁なバグで、修正はほぼ常に、値を return して、呼び出しサイトでそれをログするに変わります。

Junoパラメータと戻り値 パラメータは括弧の中の名前で、渡す値のプレースホルダーになるので、1つの関数が異なる結果を与えます。return は、コードがそれを後で使用できるように値を返します。console.log で出力すると画面に表示されます。戻すことはそれをあなたに返します。その違いを感じるのに時間がかかりました。
Junoパラメータと戻り値 パラメータは定義の中の名前で、引数は呼び出しで渡す値です。return は呼び出し元に値を返して、その場で関数を終了します。ログのみの関数は undefined に評価されるので、値を期待していて何ももらえなかった場合は、実際にそれを返したかどうかを確認してください。
Junoパラメータと戻り値return は値を生成して終了するので、検証して早期ベイルは綺麗なパターンです。値を返すことと console.log のような副作用を行うことの分割に注意してください。ログ関数は undefined に評価されます。結果に到達して何ももらえない場合は、ほぼ常にログした場所で戻すはずでした。

アロー関数

関数を書く短い方法があり、**アロー関数**と呼ばれます。変数に保存して、function キーワードの代わりに => の矢印を使用します:

js
const add = (a, b) => {
  return a + b;
};

console.log(add(2, 3)); // 5

関数がこのような単一の式の場合、括弧と return を削除して、矢印に値を返させることができます:

js
const add = (a, b) => a + b;

console.log(add(2, 3)); // 5

どちらも同じことをします。現代的なJavaScriptではアロー関数をいたるところで見かけるので、形を認識するのに役立ちます。名前、=、入力、矢印、本体です。

**アロー関数**は、関数を書くより短い構文で、=> で変数に保存されます:

js
const formatPrice = (amount) => `$${amount.toFixed(2)}`;

console.log(formatPrice(9.5)); // $9.50

本体が単一の式の場合、アロー関数は暗黙的な戻り値を持ちます。括弧がなく、return キーワードもなく、式の値は自動的に返されます。括弧を追加して、それは通常の関数本体のように振る舞い、return を自分で書きます:

js
const formatPrice = (amount) => {
  const rounded = amount.toFixed(2);
  return `$${rounded}`;
};

アロー関数は短くて単一目的の関数に慣用的な選択肢で、特に他の関数に渡す小さい関数です(配列メソッドで会いますね)。トップレベル、再利用可能、名前付けされたルーチンの場合、通常の function 宣言は明確に読め、よく機能します。簡潔さが役に立ち、関数が小さい場合にアロー関数に到達してください。

**アロー関数**は => で書かれた簡潔な関数式です。単一式の本体で暗黙的な戻り値を持ちます(return キーワードなしで式の値が返されます)。括弧で囲まれた本体で明示的に戻され、通常の関数と全く同じです。

js
const applyDiscount = (price, percent) => price * (1 - percent / 100);

console.log(applyDiscount(80, 25)); // 60

3つの関数定義方法が共存し、違いは美的ではなく実用的です:

  • 関数宣言function total() {})は巻き上げられるので、定義より上で呼び出し可能です。
  • 関数式const total = function () {})は同じ方法では巻き上げられません。変数は存在しますが、行が実行されるまで undefined を保有するので、それより前に呼び出すとスローされます。
  • アロー関数const total = () => {})は巻き上げに関して式のように振る舞い、以下の1つの重要なルールを追加します。

アロー関数を除き、1つの重要なルール:それら自身の this を束縛しません。通常の関数は、呼び出され方によって決定される this を取得します。アロー関数は代わりに周囲のコードから this を継承します。この区別は、オブジェクトのメソッドを書き始めるまで重要ではありませんが、その事実を保有して、そこで理由を理解します。

使う価値があるさらに2つのツール。デフォルトパラメータは、引数が欠落している場合にフォールバックを与えるので、関数は予測可能なままです:

js
const greet = (name = "there") => `Hi ${name}`;

console.log(greet("太郎")); // Hi 太郎
console.log(greet()); // Hi there

そして最も報酬を与える習慣:純粋関数を好む、出力が入力にのみ依存し、それ自身の外側で何も変更しない関数(副作用なし)。上記の applyDiscount は純粋です。同じ入力、同じ結果、毎回。純粋関数は分離して試験できるもので、プログラムの残りを追跡することなく推論でき、驚きなしで再利用できます。すべてが純粋になることはできません(何かはログ、フェッチ、状態を変更する必要があります)。しかし、ロジックを純粋関数に押し込んで、副作用をエッジに保つことは、言語における最も高いレバレッジ習慣の1つです。

Junoアロー関数 アロー関数は、関数を書くより短い方法で、function キーワードの代わりに => で変数に保存されます。本体が1つの式の場合、括弧と return を削除して、矢印が値を返します。この形を常に見るので、それを読むのに快適になるのは高速に報酬を与えます。
Junoアロー関数 アロー関数は関数の短形で、単一式の本体は暗黙的な戻りを与えます。括弧がなく、return がありません。括弧を追加して、通常のように return を書きます。小さい単一目的の関数にアロー関数に到達してください。トップレベルの名前付きルーチンの場合、プレーン function 宣言はまだ素晴らしく読めます。
Junoアロー関数 宣言は巻き上げられ、式とアロー関数は巻き上げられず、アロー関数はまた自身の this をスキップします。これはオブジェクトメソッドを書き始めた時点でのみ重要です。デフォルトパラメータで不足している引数に頼り、ロジックを出力が入力にのみ依存する純粋関数に押し込んでください。それらは単独で試験でき、プログラム全体を追跡することなく再利用できるものです。

ここからの関数の進展

関数は、あなたが自分自身を繰り返するのを止める方法です。ステップのブロックに名前を付けて、入力を与え、値を取り出します。これがクリックされたら、書くほとんどのコードは他の関数を呼び出す小さな関数になり、各々は1つの明確な仕事をします。

ここから、関数は至る所に現れます。配列メソッドに渡してデータのリストを変換し、条件分岐からの分岐ロジックを整理する際に使用し、変数で開始した命名規則に頼ります。コードのブロックを次回コピーしているのを見つけた時が、代わりに関数にラップするシグナルです。