12関数とスコープ
12-1 関数の定義
上記のことを意識して使い分けることを推奨します。
function 関数名(){
// ここに処理を書く
}上のように関数を作成することができます。
関数名を考えるときは以下のことを意識しましょう。
- 関数に中身が想像できる名前を付ける
- 日本語はできるだけつけない
- 命名規則に沿った名前を付ける
命名規則については、以下の3つのルールがあります。
- キャメルケースcamelCaseのように単語の先頭だけ大文字にする
- スネークケースsnake_caseのように単語間を_でつなげる
- ケバブケースkebab-caseのように単語間を-でつなげる
この3つのうちどれかを使用します。このレッスンではキャメルケースを用いますが、今後チーム開発が始まった場合は周りのコードを見てどのケースにするかを考えましょう。周りのコードはキャメルケースなのに自分だけスネークケースを使うなどということはやめましょう。
また2の日本語についてはどうしても日本語じゃないと伝わらないときは日本語にしましょう。
たとえば支払調書などの名前を組み込みたいとき英語にするとPayment Recordと一目で支払調書とはわからない英文になってしまいます。
12-2 関数の呼び出し
先ほど3-1で関数の作成方法を学びましたが関数を書いただけでは実行はされません。
たとえば
main.js
function helloAlert(){
alert('hello');
}上にhelloAlert()というダイアログを表示するだけの自作関数を作成しました。
これをブラウザで読み込んでみるとなにも起こらないはずです。なぜなら関数を作成しただけで関数を呼び出せていないからです。
関数を呼び出すにはhelloAlert();という1文を追加しないといけません。
追加するとコードは以下のようになります。
main.js
function helloAlert(){
alert('hello');
}
helloAlert();この状態でファイルを実行してみてください。
無事にダイアログに’hello’が表示されているはずです。
また、関数を2回呼び出したいときはfunctionを2回書く必要はなく、helloAlert()を2回書くだけで2回実行されます。余裕があればやってみてください。
12-2-1 関数に引数を設定する
これまでの関数には引数がありませんでしたが、場合によっては関数に引数が設定される場合があります。
たとえば足し算する関数を用意しました。
main.js
function addNumber(num1, num2){
let result = num1 + num2;
return result;
}
console.log(addNumber(1, 5));
// >6
console.log(addNumber(17, 23));
// >40今回は足し算する値は関数外から取得するので引数にnum1とnum2を設定します。
もしもnum1とnum2が関数内で設定されている場合は以下となります。
function addNumber(){
let num1 = 5;
let num2 = 10;
let result = num1 + num2;
return result;
}
console.log(addNumber());
// >15しかしこれでは5 + 10しかできない関数になってしまうので意味ないですよね。
足し算に必要な値は必ず外部から取得し計算に用いられる値も異なるはずです。
よって外部の値が必要な時は必要な数だけ引数に変数を指定するようにしましょう。
また、作成した関数に返り値を求める場合必ずreturnを設定します。
今回は足し算の結果であるresultの値が欲しかったのでreturn result;としました。
たとえば、DBに保存するだけで終わり、などの関数は見返りを求めないのでreturnの設定はいりません。しかし、電話番号のハイフンを除く関数であればハイフンが除かれた後の電話番号が見返りとしてほしいはずです。
そのような場合はreturnを必ず使用します。
JavaScriptにおける関数
JavaScriptには大きく2つの関数が存在します。
- 自作関数自ら作成したhelloAlert()のような関数のこと
- デフォルト関数これはalert()やconfirm()などのもともとJavaScriptに備わっている関数
コラム: 無名関数
無名関数は名前の通りfunctionの後に関数名を指定しなくてもよい関数です。
たとえば先ほどのhelloAlert関数を無名関数に直すと下のようになります。
const helloAlert = function(){
alert('hello');
}
helloAlert();変数を利用することで無名関数を作成することができます。
無名関数を呼び出すときは関数名ではなく変数名を利用して呼び出します。
自作関数を無名関数の大きな違いは関数の呼び出す場所が異なる点です。
自作関数ではどこで呼び出しても関数が実行されましたが無名関数では定義後でないと呼びだすことはできません。
実際に確認してみましょう。
main.js
helloAlert();
function helloAlert(){
alert('hello');
}
helloAlert();
// 2回helloAlertが呼び出される
helloAlert();
const helloAlert = function(){
alert('hello');
}
helloAlert();
// Uncaught ReferenceError: helloAlert is not defined無名関数のほうでは関数定義前に関数を呼び出してしまうと上のようなUncaught ReferenceError: helloAlert is not definedというエラーが出て実行されません。
よって無名関数の時は関数宣言後に関数を呼び出すようにしましょう。
main.js これが正解となります。
const helloAlert = function(){
alert('hello');
}
helloAlert();12-3 クロージャ
クロージャはJavaScriptにおける重要な概念で、関数が自身が作成された時の環境(レキシカルスコープ)へのアクセスを保持する能力を指します。
つまり、関数が定義されたスコープ内の変数に、その関数がどこで実行されてもアクセスできる状態のことです。
これにより、関数外部からはアクセスできないプライベートな変数を作成することが可能になります。クロージャを使う主な理由は、データのカプセル化や状態の保持などです。
クロージャの理解を深めるために、より具体的な例を見てみましょう。ここでは、特定のメッセージを記憶する挨拶関数を生成する関数を考えます。
例:
function createGreeting(greeting) {
return function(name) {
console.log(greeting + ', ' + name);
};
}
const greetHello = createGreeting("Hello");
greetHello("John"); // 出力: Hello, John
const greetHola = createGreeting("Hola");
greetHola("Pedro"); // 出力: Hola, Pedro説明
1.関数の生成
createGreeting関数が異なる挨拶メッセージ(”Hello”や”Hola”)で呼び出されます。この関数は、引数greetingに基づいた挨拶を行う新しい関数を返します。
2.クロージャの作成
createGreeting関数は、引数として受け取ったgreetingメッセージを含む匿名関数(無名関数)を返します。この匿名関数は、createGreeting関数のgr
3.関数の実行
greetHelloやgreetHolaといった変数に代入された関数を呼び出すと、それぞれの関数はcreateGreetingによって「記憶」された挨拶メッセージを使用して出力します。この時、各関数は自身が作成された環境(createGreetingが呼び出された時のgreetingの値)にアクセスできます。greeting変数への参照を保持しています。これがクロージャです。
この例からわかるように、クロージャは関数が定義された時のスコープに存在する変数へのアクセスを可能にします。これにより、関数がそのスコープ外で実行された場合でも、その変数へアクセスできるようになります。クロージャはプログラミングにおいて強力なツールであり、データを隠蔽し、プライベート変数を作成するために役立ちます。
初学者に取っては難しい概念になるので、クロージャは関数が自分が作られた環境を記憶して、その環境外からでも変数にアクセスできるJavaScriptの機能ということを頭に入れておいてください!
12-4 スコープの概念
スコープとは、変数や関数がアクセス可能な範囲のことを指します。主に、グローバルスコープ、ローカルスコープ(関数スコープ)、ブロックスコープの3種類があります。
12-4-1 グローバルスコープ
グローバルスコープにある変数は、スクリプトのどこからでもアクセス可能です。
var message = "こんにちは、世界!"; // グローバル変数
function showMessage() {
console.log(message); // "こんにちは、世界!" を出力
}
showMessage();
console.log(message); // "こんにちは、世界!" を出力12-4-2 ローカルスコープ(関数スコープ)
関数内で宣言された変数は、その関数内でのみアクセス可能です(ローカルスコープまたは関数スコープ)。
varキーワードで宣言された変数はこの関数スコープのルールに従いますが、letやconstで宣言された変数も、同様に関数内でのみアクセス可能となります。
function greet() {
var greeting = "こんにちは、世界!"; // ローカル変数
console.log(greeting); // "こんにちは、世界!" を出力
}
greet();
// console.log(greeting);
// エラー: greeting は関数の外からはアクセスできない12-4-3 ブロックスコープ
ブロックスコープとは、変数がその定義されたブロック({}で囲まれた範囲)内でのみアクセス可能であるというスコープ(変数の有効範囲)のことです。
letやconstで宣言された変数はこのブロックスコープのルールに従い、宣言されたブロック内でのみアクセス可能となります。
一方で、varで宣言された変数はブロックスコープを形成せず、関数スコープまたはグローバルスコープに従います。
if (true) {
let blockScopeVariable = "ブロックスコープの変数です";
console.log(blockScopeVariable); // "ブロックスコープの変数です"
}
// console.log(blockScopeVariable);
// エラー: blockScopeVariable はブロックの外からはアクセスできないJavaScriptのスコープを理解することは、変数がどこで有効であるかを把握し、予期しない値の変更やエラーを防ぐ上で重要です。
コメントを残す