関数
TypeScript,JavaScript 初学者が関数について勉強したのでメモを残す。
JavaScript の関数
JavaScript において関数は式もしくは文で定義できる。
-
式(Expression)
- 評価した結果を変数に代入できるもの。
- 変数、関数呼び出し、リテラル、式と演算子の組み合わせも全部式。
- 式を評価すると結果の値を得ることができる。(評価値)
-
文(Statement)
-
if文
やfor文
は文。 - なんらかの手続きを処理系に命令するもの。
- 文の末尾にセミコロンを置くことで文を区切る。
-
if 文と三項演算子(条件演算子)
if 文は文なので変数に代入できないが、同じように条件を扱う三項演算子は変数に代入できる。
// if文は文のため変数に代入はできない
const judge = if(isEven) 'even' else 'odd'; // NG
// 三項演算子(条件演算子)は式のため変数に代入可
const judge = isEven ? 'even' | 'odd'; // OK
関数宣言文と関数式
関数宣言文の定義
function double(n) {
return n * 2;
}
関数式の定義
const twice = function (n) {
return n * 2;
};
※JavaScript では{}
のブロックで終わる場合はセミコロン;
をつけない例外規則が存在する。関数式では関数を変数に代入しているためセミコロンが必要。
- 宣言文は再代入ができてしまうため、基本的には
const
で再代入不可の関数式を宣言して使うことが安全。
第 1 級オブジェクト(First-Class Object)
> const func = function () {};
undefined
> func.__proto__.constructor.name
'Function'
> func.__proto__.__proto__.constructor.name
'Object'
-
上記のように、JavaScript では関数はビルドインオブジェクト
Function
のインスタンスであり、第一級オブジェクトでもある。 -
第一級オブジェクトには、以下の特徴がある。
- 変数に代入可
- 配列の要素やオブジェクトのプロパティ値にできる
- 関数に引数として渡せる
-
関数を第一級オブジェクトとして扱うことができる言語の性質を「第一級関数」という。
-
関数式は
Function
オブジェクトを生成するリテラルである。// Functionオブジェクトでインスタンス生成 const sum = new Function('n','m','return n + m'); // ↓この定義と↑この定義はほぼ等価 // 関数式で定義 const add = functoin (n,m) { return n + m; }
※Function オブジェクトでインスタンス生成する場合、グローバルスコープで実行されるため推奨されない。
-
オブジェクトのプロパティとして関数(メソッド)を持たせることもできる
const dog = { name: 'pochi', bark: function() = { console.log('bow!'); }, // こうとも書けるよ↓ // bark(){ // console.log('bow!'); // } } dog.bark(); // bow!
アロー関数と無名関数
アロー関数の定義
const plusOne = (n) => {
return n + 1;
};
// この書き方でも可↓
// const plusOne = n => n + 1;
メソッドでない関数に適しており、コンストラクタとして使うことはできない
なぜアロー関数なのか
-
関数を短く描きたい
-
関数なのに、いちいち
function
を書かなくて良い -
引数が 1 つしかない場合、引数の括弧を省略できる
-
関数の文(Statement)が
return
のみの場合、return
も括弧も波括弧も省略できる -
オブジェクトから直接プロパティを取得できる
const arrays = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ]; arrays.map(({ length }) => length); // [ 3, 3, 3 ]
-
-
this
を束縛したくない(追記予定)
無名関数(匿名関数)の定義
> // 宣言文で定義しても
> function sampleFunction() {}
> sampleFunction.name
'sampleFunction'
>
> // 関数式で定義しても
> const function sampleFunc() {}
> smapleFunc.name
'sampleFunc'
関数には名前がついている(Function
インスタンスの name プロパティに関数の名前が入る)
> (function(){}).name
''
> (()=>{}).name
''
名前をつけなくても関数を定義することはできる。(無名関数)
なぜ無名関数なのか
- 名前がないため、変数に代入しない限り定義した側から消える。
- 名前を考える手間が省ける。
ここで一度、アロー関数(関数式)を思い出す。
// 関数式の定義
const twice = function (n) {
return n * 2;
};
// アロー関数による関数式の定義
const twice = (n) => {
return n * 2;
};
- 関数式での関数の定義とは、無名関数を変数(例の twice)に代入することでメモリに残すというもの
ついでに即時関数
// 即時関数の定義
const twice = (function (n) {
return n * 2;
})(2);
console.log(twice); // 4
なぜ即時関数なのか
- グローバルスコープと関数スコープを使い分けることができる
- 再利用されない関数の処理、関数スコープ外に影響を及ばさないために使用できる
参考
- 文と式 - JavaScript Primer
- りあクト! TypeScript で始めるつらくない React 開発 第 3 版【Ⅰ. 言語・環境編】
- 【JavaScript 入門】すぐわかる!無名関数とは - 侍エンジニア塾
- アロー関数 - JavaScript | MDN
- 【JavaScript】アロー関数式を学ぶついでに this も復習する話
何か指摘等ございましたら、コメントでお願いいたします。