JavaScript
ECMAScript
Vue.js
フロントエンド
React
758
どのような問題がありますか?

投稿日

更新日

Organization

モダンフロント開発に必須の知識(ES2015~ES2022まとめ + 高階関数)

はじめに

モダンフロント開発に必須の知識であるES2015〜以降の記法と、実務でよく使用される高階関数について、自分の中で改めて復習、整理しておきたいと思います。
それぞれの項目に★~★★★の重要度も記述しています。

★★★ => 必ず覚えておくべき
★★ => 覚えておくべきだが、使う場面が限られる
=> 知識としては知っておいた方が良い

現在フロントエンドエンジニアの方やフロントエンジニアになりたての方、フロントエンドエンジニアを目指して勉強中の方に読んでいただけたら幸いです。

ES(ECMAScript)とは?

JavaScriptの標準仕様。
現在ブラウザで使われているJavaScriptは、ECMAScriptの仕様に則って開発されています。
JavaScriptは他の言語のようにversionなどが存在せず、「ECMAScriptのversion~~に対応しているJavaScript」というような扱いになっています。
なので、年々アップデートされるECMAScriptの仕様をインプットし続けることがフロントエンドエンジニアには必須となるのです。
特に、大きな変更があったES2015からの記法が現在のフロント開発の基盤となっているため、まとめてみました。

注意点 ECMASCriptの対応状況はブラウザによって違うので、今現在の、ブラウザのECMAScript対応状況をよく確認しておく必要があります。 ※最新のESを古いESに変換することができる「トランスパイラ」についての説明は割愛いたします。

ES2015

変数宣言(letconst)

重要度 ★★★

ES2015が出るまではvarによる変数宣言のみだったが、再代入可能や、スコープがグローバルだったため、バグが多発する恐れがあった。
そこで新しい変数宣言のletconstが追加される。

  • let・・・再代入可能なブロックスコープのローカル変数宣言
  • const・・・再代入不可能なブロックスコープのローカル変数宣言
// 再代入可能
let num = 1
num = 2
console.log(num) //=> 2

// 再代入不可能
const age = 18
age = 22 // NG

// ブロックスコープ(let、const共通)
let name = taro
{
  let name = hana
  console.log(name) //=> hana
}
console.log(name) //=> taro

基本的にはconstを使用し、どうしてもという場合のみletを使用するというのがベストだと思います。(varは使用しない)

クラス構文

重要度★

RubyやJavaでお馴染みのクラス構文がJavaScriptにも実装される。
constructorprototypestaticという3つのメソッドとクラスの継承(extends)が可能。

  • constructorメソッド・・・クラスがnewされた時に実行されるメソッド
  • prototypeメソッド・・・クラスのインスタンスから呼び出せるメソッド
  • staticメソッド・・・インスタンスを生成しなくても呼び出せるメソッド
class Human {
  // constructorメソッド
  constructor(name) {
    this.name = name;
  }

  // prototypeメソッド
  hello() {
    console.log('My name is ' + this.name);
  }

  // staticメソッド
  static num_of_hands() {
    console.log(2)
  }
}

// prototypeメソッドの呼び出し
obj = new Human('Koyabu')
obj.hello() //=> 'My name is Koyabu'

// staticメソッドの呼び出し
Human.num_of_hands() //=> 2
class Animal { 
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

// 継承
class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}

注意点 クラス構文は、現在フロント開発で主流となっている、React、Vue、Svelteなどを使用した開発ではほとんど使われていないため、「重要度★」としています。

アロー関数

重要度★★★

従来のfunctionではなく、=>を用いた関数宣言。

  • 匿名関数
  • 引数が一つの場合は()が省略可能
  • 単一式の場合は、{}returnを省略できる
// 従来の関数
function (a, b){
  return a + b + 100;
}

// アロー関数
(a, b) => a + b + 100;

const num = (a, b) => a + b + 100;
console.log(num(5, 10)) //=> 115

注意点 thisやsuperへの結びつけを持たないので、メソッドとして使用することができなかったり、コンストラクターとしても使用することは出来ません。

分割代入

重要度★★★

一度に複数の変数に、配列やオブジェクトなどの複数の値を代入できる。
また、オブジェクトのkeyとvalueの変数名が同じ時は省略することが可能に。

const [name, age] = ['Taro', 22];

console.log(name) //=> Taro
console.log(age) //=> 22
const hero = {name: 'Taro', age: 22}
const {name, age} = hero

console.log(name) //=> Taro
console.log(age) //=> 22

// keyとvalueの変数名が同じ時は省略可能
const user = {name: name, age: age} // ↓と同じ
const user = {name, age}

配列展開

重要度★★★

...(スプレッド構文)を用いて、配列を展開することができる。
※ES2018より、オブジェクトにも...(スプレッド構文)が使用できるようになりました。

const array = [1, 2, 3]
console.log([...array, 4, 5, 6]) //=> [1, 2, 3, 4, 5, 6]
// ES2018の項目で改めて紹介します。
const hero = {name: 'Taro', age: '22'}
console.log({...hero, weapon: 'sword'}) //=> {name: 'Taro', age: '22', weapon: 'sword'}

可変長引数

重要度★★

上記の配列展開と同じく、...(スプレッド構文)を使用することで、複数の引数を一つの配列で受け取ることができる。
配列展開とは逆のイメージとも言える。

const f = (a, b, ...c) => {
  console.log(a, b, c)
}

f(1, 2, 3, 4) //=> 1, 2, [3, 4]

デフォルト引数

重要度★★★

関数宣言時に引数に値を代入しておくことで、デフォルト引数とすることができる。

const multiply = (a, b = 2) => {
  console.log(a * b);
}
multiply(5); // 10

テンプレート文字列

重要度★★★

``で文字列を囲むことで、その中に ${}を使用し変数を記述できる。

const name = 'Taro'
const greet = `こんにちは!${name}さん!`
console.log(greet) //=> こんにちは!Taroさん!

非同期処理(Promise)

重要度★★★

非同期処理を扱うオブジェクトPromise
PromiseにはPromiseStatusと呼ばれる3つの状態がある。

  • pending・・・未解決(処理が終わるのを待っている状態)
  • resolved・・・解決済み(処理が終わり解決した状態)
  • rejected・・・拒否(処理が失敗に終わってしまった状態)
const promise = new Promise((resolve, reject) => {});
const promise = new Promise((resolve, reject) => {
  resolve("test");
}).then((val) => {
    console.log(`then1: ${val}`);
    return val;
  }).catch((val) => {
    console.log(`catch: ${val}`);
    return val;

※Promiseに関しての詳しい説明は割愛いたします。

現在非同期処理を扱う場合は、ES2017で追加されたasync/awaitを使用するのが主流です。

Map

重要度★

キーと値の組み合わせからなる抽象データ型。
オブジェクトとほぼ同じだが、オブジェクトと違う点は2点。

  • Objectprototypeオブジェクトからプロパティを継承されない
  • 文字列やSymbol以外の値もkeyとして使用できる
// Mapの作成
const map = new Map();

// 新しい要素の追加
map.set("name", "Taro");

console.log(map.size); // => 1
console.log(map.get("name")); // => "Taro"

Set

重要度★

重複する値がないことを保証したコレクション。

// Setの作成
const set = new Set();

// 値の追加
set.add("Taro");

console.log(set.size); // => 1

// 重複する値は追加されない
set.add("Taro");
console.log(set.size); // => 1

for..of

重要度★★

配列MapSetなどに対して、反復処理ができる。

const array1 = ['a', 'b', 'c'];

for (const element of array1) {
  console.log(element);
}

//=> 'a'
//=> 'b'
//=> 'c'

注意点 配列に対する処理は、基本的に、後述する「高階関数」を使用するのが推奨です。

ES2016

Array.prototype.includes()メソッド

重要度★★★

配列の中に指定した要素が含まれているかをbooleanで返す関数。

const array = ['a', 'b', 'c'];

console.log(array.includes('c')); //=> true
console.log(array.includes('d')); //=> false

指数演算子

重要度★★★

ES2016より、指数演算子**と、それに伴う代入演算**=が追加される。

console.log(2 ** 4); //=> 16

let a = 2, b = 3;
a **= b
console.log(a) //=> 8

ES2017

async / await

重要度★★★

Promiseを使った非同期処理に対して新しいシンタックス(構文)。
async functionを定義し、その中の非同期処理にawaitを記述することで、非同期処理が完了するまで以降の処理を待ってくれる。

const fetchData = async () => {
  try{
    const data = await // awaitに続けて非同期処理を記述する
    console.log(data) // ↑の非同期処理が完了するまでこの処理は実行されない
  }catch(error){
    console.log(error)
  }
}

Object.values() / Object.entries()メソッド

重要度★★★

オブジェクトに存在するキーを取り出す Object.keys() に対応するメソッドとして、値を取り出す Object.values() と キーバリューペアを取り出す Object.entries() の2メソッドが追加された。

const obj = { a: 1, b: 2, c: 3 };

// キー一覧を取得
console.log(Object.keys(obj)); //=> ['a', 'b', 'c']

// 値一覧を取得
console.log(Object.values(obj)); //=> [1, 2, 3]

// キー、バリューのペアを配列で取得
console.log(Object.entries(obj)); //=> [['a', 1], ['b', 2], ['c', 3]]

String.prototype.padStart() / String.prototype.padEnd()メソッド

重要度★

文字列を加工し、固定文字列長になるよう指定文字で空白を埋めてくれるメソッド。

  • padStart・・・右寄せで左側を埋める
  • padEnd・・・左寄せで右側を埋める
"abc".padStart(10);         // "       abc"
"abc".padStart(6,"123465"); // "123abc"
"abc".padStart(8, "0");     // "00000abc"
"abc".padStart(1);          // "abc"

"abc".padEnd(10);           // "abc       "
"abc".padEnd(6,"123465");   // "abc123"
"abc".padEnd(8, "0");       // "abc00000"
"abc".padEnd(1);            // "abc"

ES2018

残余プロパティ / 分割プロパティ

重要度★★★

ES2015で追加された...(スプレッド構文)がオブジェクトにも適用。

// 残余プロパティ
const {x, y, ...z} = {x: 1, y: 2, a: 3, b: 4, c: 5 };
console.log(x)   // 1
console.log(y)   // 2
console.log(z)   // {a: 3, b: 4, c: 5}

// 分割プロパティ
const num = {x, y, ...z};
console.log(num)   // {x: 1, y: 2, a: 3, b: 4, c: 5}

Promise.prototype.finally()メソッド

重要度★★

明示的なfinally()が追加。
finally()で例外が発生した場合、再度Promiseが生成される。

const fetchData = async () => {
  try{
    const data = await // awaitに続けて非同期処理を記述
    console.log(data) 
  }catch(error){
    console.log(error)
  }finally{
    // ここにfinallyの処理が書ける
  }
}

ES2019

Array.prototype.flat()/ Array.prototype.flatMap()メソッド

重要度★★

多階層の配列を任意の階層に減らすこと(フラット化)ができる。

const ar1 = [[1, 2], 3, 4].flat();
console.log(ar1) //=> [1, 2, 3, 4]

const ar2 = [0, 1, 2, [[[3, 4]]]].flat(2);
console.log(ar2) //=> [0, 1, 2, [3, 4]]

const userData = [
  {
    name: "Taro",
    hobby: ["ゲーム", "漫画", "野球"]
  },
  {
    name: "Hana",
    hobby: ["映画", "カラオケ"]
  },
  {
    name: "Ken",
    hobby: ["ランニング", "サッカー", "旅行"]
  }
];
const hobbyList = userData.flatMap(data => data.hobby);
console.log(hobbyList) //=> ["ゲーム", "漫画", "野球", "映画", "カラオケ", "ランニング", "サッカー", "旅行"]

Object.fromEntries()メソッド

重要度★★

キー・値のペアからオブジェクトを生成する。
ES2017で追加されたentries()メソッドの逆。

const user = Object.fromEntries([["id", 1], ["name", "Taro"]]);
console.log(user) //=> {id: 1, name: "Taro"}

String.prototype.trimStart()/String.prototype.trimEnd()メソッド

重要度★

文字列の先頭または末尾の空白を除去するメソッド。

const name = "    Taro    ".trimStart();
console.log(name) //=> "Taro    "

const lunch = "    寿司    ".trimEnd();
console.log(lunch) //=> "    寿司"

ES2020

オプショナルチェーン演算子

重要度★★★

?.を使用することで、参照がnullish(null または undefined)の場合にエラーとなるのではなく、式が短絡されundefinedが返される。

const userData = {
  name: 'Taro',
  dog: {
    name: 'Pochi'
  }
};

console.log(userData.name) //=> Taro
console.log(userData.dog.name) //=> Pochi
console.log(userData.cat?.name) //=> undefined

Null合体演算子

重要度★★

??を使用し、左辺がnullish(null または undefined)の場合に右の値を返し、それ以外の場合に左の値を返す。

const hero = null ?? 'Taro';
console.log(hero); //=> Taro

const num = 0 ?? 10
console.log(num) //=> 0

動的import

重要度★

通常のimportと違い、Promiseの形でimportすることができるようになったので、使いたいときだけimportすることが可能。

module.js
export const name = "Taro"
import("./module.js").then(module => {
  console.log(module.name) //=> Taro
})

setTimeout(async () => {
  const { name } = await import("./module.js")
  console.log(name) //=> Taro
}, 1000)

Promise.allSettled

重要度★

Promise.allと違い、複数のうちどれか1つがrejectされても他のPromiseは問題なく実行されます。

const promiseList = [
  Promise.resolve("ok"),
  Promise.resolve("ok"),
  Promise.reject("ng"),
  Promise.resolve("ok")
]

Promise.allSettled(promiseList).then(
  resolveList => {
    console.log("resolve")
    resolveList.forEach(resolve => console.log(resolve))
  },
  reject => {
    console.log("reject")
    console.log(reject)
  }
) 
// => resolve
// => { status: 'fulfilled', value: 'ok' }
// => { status: 'fulfilled', value: 'ok' }
// => { status: 'rejected', reason: 'ng' }
// => { status: 'fulfilled', value: 'ok' }

BigInt

重要度★

Numberより大きな整数2^53以上の整数を扱えるオブジェクト。
数値にnを追加することで使用することができる。

console.log(BigInt(Number.MAX_SAFE_INTEGER) + 2n) // => 9007199254740993

ES2021

Promise.any

重要度★★

複数のPromiseを渡したときに、ひとつでも成功した時点で解決されるPromise

const promise1 = xxx;
const promise2 = xxx;
const promise3 = xxx;

Promise.all([promise1, promise2, promise3])
    .then(values => {
        // 全てのPromiseがfulfillされたときに呼ばれる
    })
    .catch(error => {
        // ひとつでもrejectされたら呼ばれる
    });

Promise.any([promise1, promise2, promise3])
    .then(first => {
        // ひとつでもfulfillされたら呼ばれる
    })
    .catch(error => {
        // 全てのPromiseがrejectされたときに呼ばれる
    });

String.prototype.replaceAllメソッド

重要度★

一致する文字列を全て置換する。
replaceの場合、最初に一致した文字列のみ置換されていた。

// 従来のreplaceの場合
const test = "Taro Hana Ken Taro Hana".replace("Taro", "Jiro")
console.log(test) //=> "Jiro Hana Ken Taro Hana"

// replaceAllの場合
const test2 = "Taro Hana Ken Taro Hana".replaceAll("Taro", "Jiro")
console.log(test2) //=> "Jiro Hana Ken Jiro Hana"

論理+代入演算子

重要度★

論理演算子やnull合体演算子と代入演算子を合わせたもの。

// 論理和代入
a ||= b;
a || (a = b); // ↑と同じ

// 論理積代入
a &&= b;
a && (a = b); // ↑と同じ

// null合体代入
a ??= b;
a ?? (a = b); // ↑と同じ

numeric separator

重要度★

数値セパレータ。数値を_で区切って表記できる。

100000000 === 100_000_000; // true

ES2022

Top-level await

重要度★★

async関数の外側でawaitを使えるようになった。

export const hoge = await f();

注意点 asyncでない関数の中では今まで通り使用できません。

Object.hasOwnメソッド

重要度★★

オブジェクト自身が(継承されていない)指定されたプロパティを持っているかどうかを示す真偽値を返す。
hasOwnPropertyのショートハンド。

const user = {name: "Taro"}

// 従来
Object.prototype.hasOwnProperty.call(user, "name");

// hasOwnの場合
Object.hasOwn(user, "name");

.at

重要度★

Array・String・TypedArrayに、指定位置の値を取得するメソッド.at()が追加された。
従来では-での指定ができなかった。

// 従来
'abcdef'[1]; //=> b
'abcdef'[-1]; //=> undefined

// .at()の場合
'abcdef'.at(1); //=> b
'abcdef'.at(-1); //=> f

[1, 2, 3].at(1); //=> 2
[1, 2, 3].at(-1); //=> 3

Class privateメソッド

重要度★

Class内のprivateメソッドの追加。
#を使用して、プライベートクラスメンバーを生成することができる。

class Foo{
  #privatemethod() {
    return "privatemethod";
  }
  publicmethod() {
    return "publicmethod";
  }
}

Class publicフィールド/privateフィールド

重要度★

JSでは、publicフィールドは後から追加できるのだが、明示的に指定できるようになった。

class Foo{
  x = 1;
  #y = 1;
}

Class 静的フィールド/静的メソッド

重要度★

静的フィールド・メソッドの追加。上記で紹介したprivateフィールドやメソッドにも対応している。

class Foo{
  static x = 1;
  static #y = 2;

  static bar(){}
  static #baz(){}
}

実務でよく使用される高階関数

使用頻度の高い高階関数7選の紹介。

forEach

重要度★★★

与えられた関数を、配列の各要素に対して一度ずつ実行する。
単純に、配列の全ての要素に対して何かしらの処理をしたい場合に使用する。

const array1 = ['a', 'b', 'c'];

array1.forEach(element => console.log(element));
//=> a
//=> b
//=> c

注意点 forEachは、後に紹介する6つの関数が利用できない場合のみ使用するのが好ましいです。

filter

重要度★★★

与えられた関数によって、trueと評価された要素のみの配列を生成する。
配列の中から特定の要素のみを抜き出したい場合に使用する。

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(result); //=> ["exuberant", "destruction", "present"]

find

重要度★★★

与えられた関数によって、trueと評価された最初の要素のみを返す。
配列の中から特定の値を取得したい場合に使用する。

const array1 = [5, 12, 8, 130, 44];

const found = array1.find(element => element > 10);

console.log(found); //=> 12

map

重要度★★★

与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成する。
配列の中の要素に処理を加え、要素の値を変更したい場合に使用する。

const array1 = [1, 4, 9, 16];

const map1 = array1.map(x => x * 2);

console.log(map1); //=> [2, 8, 18, 32]

reduce

重要度★★★

配列のそれぞれの要素に対して、順番通りに、コールバック関数を呼び出す。その際、直前の要素における計算結果の返値を渡す。
配列の要素全ての和などを求めたい場合に使用する。

const array1 = [1, 2, 3, 4];
const reducer = (previousValue, currentValue) => previousValue + currentValue;

console.log(array1.reduce(reducer)); //=> 10

some

重要度★★

配列のそれぞれの要素に対して、与えられた関数で評価し、1つでもtrueと評価されたかどうかをbool値で返す。
配列の中に目的の値があるかどうか調べるときなどに使用できる。

const array = [1, 2, 3, 4, 5];
const someTest = array.some((element) => element % 2 === 0)
console.log(someTest) //=> true

every

重要度★★

配列のそれぞれの要素に対して、与えられた関数で評価し、全てtrueと評価されたかどうかをbool値で返す。
複数の評価値がtrueになったときに何か処理をしたい場合などに使用できる。

const array = [1, 2, 3, 4, 5];
const everyTest = array.every((element) => element < 10)
console.log(everyTest) //=> true

おわりに

ここまでお読みいただきありがとうございました。
長くなりましたが、以上の知識を覚えておくと、快適にモダンフロント開発ができると思います。
内容はES2015~2022までに追加された仕様のまとめと高階関数の紹介ですが、開発に大きく関わらない部分や、正規表現の仕様など、若干省いているものもあるためご了承ください。
それぞれの項目毎に自分なりにシンプルにまとめたつもりですが、記述ミスや間違えなどありましたら、ご指摘いただけますと幸いです。

参考にさせていただいた記事

ES2015 (ES6)についてのまとめ
ES2015(ES6) 入門
ECMAScript 2016 (ES7) まとめ
ECMAScript 2017 (ES8) まとめ
ECMAScript 2018 (ES9) まとめ
JavaScriptの‍ES2019で追加された新機能まとめ
ES2020の仕様には、こんなのが追加されました!
【JavaScript】ES2021の新機能
【JavaScript】ES2022の新機能

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
c-shiraga
フロントエンドエンジニアです!
arsagapartners
最高品質を最速で。 業務未経験でも最速最高の成長を!
この記事は以下の記事からリンクされています
Qiita月間トレンド記事一覧からリンク

コメント

リンクをコピー
このコメントを報告

@ljud ありがとうございます!
すぐに修正いたします!

プロパティ名の修正 by ljud 2022/02/08 16:11

0
リンクをコピー
このコメントを報告

@tanakyut ご指摘ありがとうございます!

flatの結果の修正 by tanakyut 2022/02/09 08:50

1
リンクをコピー
このコメントを報告

クラスっていりますかね?ReactもVueもクラスを使わない書き方が主流に。Vueはvue-class-componentの人がコアメンバーから一人もいなくなったとききました。Svelteも使わないですし。Angularを使う人は必要ですが。

2
リンクをコピー
このコメントを報告

@htsign ご指摘ありがとうございます!

構文エラーです by htsign 2022/02/11 14:01

0
リンクをコピー
このコメントを報告

@tkihira
コメントありがとうございます!
追加させていただきます!

0
リンクをコピー
このコメントを報告

@shibukawa
コメントありがとうございます!
ご指摘の通りだと思います!
クラス関連を記述するべきか迷ったのですが、ES2022でクラス関連の更新があるあたり知識としては知っておいても良いのかな思い記述しました。
ですが、重要度★★★というのは大袈裟でしたので、その部分を修正させていただきます。
ありがとうございました!

1
リンクをコピー
このコメントを報告

@suzuneu ご指摘ありがとうございます!

getterではないので関数化 by suzuneu 2022/02/12 19:03

0
リンクをコピー
このコメントを報告

"replaceAll"って最近なんですね。
そう言えば、正規表現で"/g"を付けてましたね。

1
リンクをコピー
このコメントを報告

@qiiChan
コメントありがとうございます!
そうみたいですね!
replaceAllで正規表現を扱う場合は、"/g"は必須みたいです!

1
リンクをコピー
このコメントを報告

for .. of は配列に関しては確かに一切使用する必要がないのですが、forEachの定義されていないイテレーターオブジェクトもないわけではないので★★くらいでもいいかもしれません。
頻出パターンは Map.keys() 等に対するforeach。いかに Map.forEach() なり Array.from() を使えば事足りるとはいえ、キーだけ、あるいは値だけを回したいところで両方回すのも、配列に全部コピーするのもあまり好ましくないように思います。
また、ジェネレーターに対しては forEach メソッドがないばかりか、無限ジェネレーターになる可能性があり Array.from() すら使えないため、 for .. of が必須レベルになります。もっとも、こちらに関してはジェネレーターそのものが★でしょうから、 for .. of の評価には影響しませんが……。

そういえばES2015はMapSet・ジェネレータも(どんなに高くとも★★止まりだろうとは思いますが)重要かと思うので追加のご検討をお願いします。

3
(編集済み)
リンクをコピー
このコメントを報告

forEach や find は 関数を引数に取る関数 であって 高階関数 ではないですね。
この文脈なら高階関数という単語を使わないほうがいいかと。

0
リンクをコピー
このコメントを報告

@sonodar ちょっとよく分からないのですが、関数を引数に取る関数ならばそれは高階関数では?

関数を引数/返り値とするような関数を高階関数(higher-order function)と呼ぶ.

-- 高階関数,多相性,多相的関数
-- https://www.fos.kuis.kyoto-u.ac.jp/~igarashi/class/isle4-05w/mltext/ocaml005.html

関数を引数に取る関数、および、返り値が関数である関数*1を総称して高階関数 (higher-order function)
と言う。

-- ソフトウェア技法: No.7 (高階関数とその型付け)
-- http://www.cs.tsukuba.ac.jp/~kam/lecture/fp2017/7.pdf

Higher-order functions are just a fancy way of saying that the function takes a function as one of its arguments.

-- Functional Programming – OCaml
-- https://ocaml.org/learn/tutorials/functional_programming.html

A higher order function is a function that either:

  1. Takes one or more functions as arguments
  2. Returns a function as its result

-- Clojure - Higher Order Functions
-- https://clojure.org/guides/higher_order_functions

ただし、MDNには関数を引数に取る関数が高階関数であるという説明はありませんでした。
MDNを元にして言うならば確かに高階関数であると定義付けることはできませんが、しかし一般的には高階関数でいいと思います。

A function that returns a function is called a Higher-Order Function.

-- First-class Function - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
-- https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function

4
リンクをコピー
このコメントを報告

@rew106
コメントありがとうございます!
for..ofに関しての貴重なご意見、とても参考になりました!
あと、Map、Set、ジェネレータについては、社内外のフロントエンドエンジニア数名にヒアリングしたところ、実務の開発では全く使ったことがないとのご意見を多数頂きました。自分も使用したことがないため、今回の記事では紹介しなかったのですが、ライブラリを開発するときなどに使用したりするそうなので、MapとSetのみ★で追加させていただきます。
ありがとうございました!

0
リンクをコピー
このコメントを報告

@sonodar @htsign
コメントありがとうございます!
「高階関数」という呼び方については曖昧な部分があり、「関数を引数に取る関数」、「関数を引数に取ることができる関数」、「関数を返す関数」など様々な意味で使われているみたいです。
今回は「関数を引数に取る関数」という意味で記述させていただきました!

1
リンクをコピー
このコメントを報告

高階関数を紹介する順番として、

  1. map と forEach
  2. filter と find

という順番ではいかがでしょうか。

自分の使い方では、基本は map を使い、戻り値に興味がなく副作用を目的としているときにあえて forEach または for...of を使い意図を明確にしています。

When not to use map()

When not to use map()
Since map builds a new array, using it when you aren't using the returned array is an anti-pattern; use forEach or for...of instead.

You shouldn't be using map if:

you're not using the array it returns; and/or
you're not returning a value from the callback.

また、filter と find も同様に、条件を満たす全ての要素を配列で得たいときは filter を使い、条件を満たす最初の要素だけで十分でループを途中で打ち切りたいときに find を使っています。

2
リンクをコピー
このコメントを報告

@susumuota
コメントありがとうございます!
私としては、forEachは最終手段で使用するもので、中にどんなロジックも書ける便利なものだが、中身を読む手間が増えるものという認識を持っています。
なので、今回の紹介は「最終手段で使うforEach」と「それ以外」というような紹介にしています。

0
どのような問題がありますか?
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
758
どのような問題がありますか?
ユーザー登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
ユーザー登録ログイン
ストックするカテゴリー