関数オブジェクト
JavaScriptは以下のように関数も変数に代入できたりしますが、関数自体もオブジェクトになります。
1 2 3 |
function add (a,b) { return a+ b; } |
こうするとaddという変数に対して関数オブジェクトが代入されるという挙動になります。
typeof演算子
ただ、これを使うと「function」と出力されます。
オブジェクトから関数を定義できるのか?
では、逆に言えば関数はオブジェクトということなので、オブジェクトから関数を生成できるかなといえばこれはできません。
なぜなら、JavaScriptエンジンが関数用のプロパティを内部的に自動生成しているからです。これは一般の開発者が操作できるものではないので必ず関数を定義する必要があります。
以下のように丸括弧を変数名の後に指定して実行できるようになるのはその関数特有の特殊なプロパティのおかげなのです。
1 |
add(); |
なお、この仕様についてはECMAScriptの仕様書に載っていたりします。
関数式
以下のように書いた場合は「関数オブジェクト」ではなく「関数式」という扱いになります。式なので変数に代入しないと使えません。
名前付き関数式
1 2 3 |
const aaa = function add (a,b) { return a+ b; }; |
無名関数と比べてデバッグするときにいい感じで表示してくれます。デバッグトレースでどこでエラーが発生したか関数名までコンソールに出力してくれます。
無名関数(匿名関数とも呼ばれることもある)
正直、関数式は名前が不要なので以下のようにも記述できます。
1 2 3 |
const aaa = function (a,b) { return a+ b; }; |
なお、無名関数はアロー関数に書き換えることが可能です。(というか今はこれが主流です。)
関数オブジェクトと関数式はどちらを使えば良いのか?
どちらにもメリットはあるのでプロジェクトでできるだけ統一するようにすると良いでしょう。現状は関数式の方が主流のような気がします。
二つの違い
巻き上げられるか巻き上げられないか。
関数オブジェクトは巻き上げられますし、関数式は巻き上げられません。
例えば、関数オブジェクトは関数宣言の前に実行することができます。(JavaScriptエンジンによって巻き上げられて先頭に持っていくからです。)
1 2 3 4 |
add(); // OK function add (a,b) { return a+ b; } |
逆に、関数式は以下のように記述しないといけません。
1 2 3 4 5 |
aaa(); // NG const aaa = function (a,b) { return a+ b; }; aaa(); // OK |
関数オブジェクトのメリット
関数が一つの文として独立しているので、可読性が高い。
関数式のメリット
- 必ず上を見れば関数が書いてある。
- constを使えて再代入を防げる。
JavaScriptで同じようなオブジェクトをたくさん定義しようとしたら冗長になってしまいます。それを解決するためにさまざまな構文が用意されています。
ファクトリ関数
1 2 3 4 5 6 |
const PersonFactory = (name, age) => { return { name, age, }; }; |
使う
1 2 |
const person1 = PersonFactory("太郎",32); const person2 = PersonFactory("次郎",32); |
コンストラクタ関数
JavaScriptではファクトリ関数のような書き方を非常によく使うので一般的にはコンストラクタ関数をよく使います。
1 2 3 4 5 6 |
const PersonConstructor = function (name, age) { // this = {}; が省略されている。 this.name = name; this.age = age; // return thisが省略される。 }; |
JavaScriptが内部的にthisという空オブジェクトを生成して返してくれます。注意点としてはアロー関数は使えないことです。
呼び出し方
1 2 |
const person1 = new PersonConstructor("太郎", 32); const person2 = new PersonConstructor("次郎", 33); |
アロー関数とは?
ECMAScript2015にて、追加された機能で、「関数リテラル」をよりシンプルに記述することができます。
関数リテラルに関しては、下記の記事でも解説しています。
アロー関数の記述方法
1 |
(引数1,引数2) => {…処理内容…}; |
アロー関数では、functionというキーワードを使用しません。
また、関数本体が1文の場合は、下記のようにブロック「{}」を外して、さらにシンプルに記述することができます。
1 |
(引数1,引数2) => …処理内容…; |
さらに、引数が1つの場合は、下記のように引数をくくる括弧すらも省略することができます。なお、最後の評価は暗黙的にreturnとして戻り値が返さるのと同様の動作になります。
1 |
引数 => …処理内容…; |
※注意点として、引数がない場合は()を省略できません。「() =>」のように記述します。
アロー関数のデメリット
アロー関数ではargmentオブジェクトを使用する事ができません。argmentオブジェクトに関しては下記の記事で解説しておりますのでご参照ください。
http://www.code-magagine.com/?p=5432
thisについて
アロー関数では、thisはアロー関数自身が宣言された場所によって決まります。
なので、イベントリスナー等では、本来はthisは、イベントの発生元を変数として使いますが、イベントリスナー内でも、this(インスタンスそのもの)として定義することができます。
これをアロー関数の「thisの固定化」の機能と呼びます。
thisキーワードについては、下記の記事で解説しています。
この記事へのコメントはありません。