コンテンツにスキップ

ECMAScript/遅延評価の歴史

出典: フリー教科書『ウィキブックス(Wikibooks)』

ECMAScript(ES)における遅延評価の歴史は、言語の進化とともに少しずつ発展してきました。遅延評価は、特にジェネレータ(Generator)やイテレータ(Iterator)の導入によって顕著になり、その後、より高度な機能として導入されています。以下に、ESにおける遅延評価の歴史を時系列で解説します。

ES6(ECMAScript 2015): ジェネレータとイテレータの導入

[編集]

ES6は、遅延評価を実現するための重要な機能としてジェネレータイテレータを導入しました。

ジェネレータ(Generator

[編集]
  • ジェネレータは、function* 構文を使って定義され、yield キーワードを使って値を逐次的に生成します。
  • ジェネレータは、値を必要に応じて生成する(遅延評価)ことが可能です。

例: ジェネレータを使った遅延評価

[編集]
function* generateNumbers() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = generateNumbers();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3

イテレータ(Iterator

[編集]
  • イテレータは、Symbol.iterator メソッドを実装したオブジェクトで、next() メソッドを使って値を逐次的に取得します。
  • イテレータも遅延評価を実現するための基盤となります。

例: イテレータを使った遅延評価

[編集]
const iterable = {
  [Symbol.iterator]() {
    let count = 0;
    return {
      next() {
        count++;
        return { value: count, done: count > 3 };
      },
    };
  },
};

for (const value of iterable) {
  console.log(value); // 1, 2, 3
}

ES2018: 非同期ジェネレータと非同期イテレータ

[編集]

ES2018では、非同期ジェネレータ非同期イテレータが導入され、非同期処理における遅延評価が可能になりました。

非同期ジェネレータ(Async Generator

[編集]
  • 非同期ジェネレータは、async function* 構文を使って定義され、yield を使って非同期に値を生成します。

例: 非同期ジェネレータを使った遅延評価

[編集]
async function* generateAsyncNumbers() {
  yield 1;
  yield 2;
  yield 3;
}

(async () => {
  const asyncGenerator = generateAsyncNumbers();
  for await (const value of asyncGenerator) {
    console.log(value); // 1, 2, 3
  }
})();

非同期イテレータ(Async Iterator

[編集]
  • 非同期イテレータは、Symbol.asyncIterator メソッドを実装したオブジェクトで、next() メソッドが Promise を返します。

例: 非同期イテレータを使った遅延評価

[編集]
const asyncIterable = {
  [Symbol.asyncIterator]() {
    let count = 0;
    return {
      async next() {
        count++;
        return { value: count, done: count > 3 };
      },
    };
  },
};

(async () => {
  for await (const value of asyncIterable) {
    console.log(value); // 1, 2, 3
  }
})();

ES2020: Promise.allSettled と遅延評価

[編集]

ES2020では、Promise.allSettled が導入され、非同期処理における遅延評価の柔軟性が向上しました。

Promise.allSettled

[編集]
  • Promise.allSettled は、すべての Promise が解決または拒否されるまで待機し、その結果を配列として返します。
  • この機能は、非同期処理の遅延評価をより柔軟に制御するために役立ちます。

例: Promise.allSettled を使った遅延評価

[編集]
const promises = [
  Promise.resolve(1),
  Promise.reject("Error"),
  Promise.resolve(3),
];

Promise.allSettled(promises).then((results) => {
  results.forEach((result) => console.log(result));
  // { status: 'fulfilled', value: 1 }
  // { status: 'rejected', reason: 'Error' }
  // { status: 'fulfilled', value: 3 }
});

ES2021: WeakRefFinalizationRegistry

[編集]

ES2021では、WeakRefFinalizationRegistry が導入され、弱参照を使った遅延評価が可能になりました。

WeakRef

[編集]
  • WeakRef は、オブジェクトへの弱い参照を作成し、ガベージコレクションの対象となることを許容します。

例: WeakRef を使った遅延評価

[編集]
let obj = { data: "example" };
const weakRef = new WeakRef(obj);

obj = null; // obj への強い参照がなくなる

setTimeout(() => {
  console.log(weakRef.deref()); // undefined (GCが発生した場合)
}, 1000);

FinalizationRegistry

[編集]
  • FinalizationRegistry は、オブジェクトがガベージコレクションされたときにコールバックを実行するための仕組みです。

例: FinalizationRegistry を使った遅延評価

[編集]
const registry = new FinalizationRegistry((heldValue) => {
  console.log(`Object with value ${heldValue} was garbage collected`);
});

let obj = { data: "example" };
registry.register(obj, "some value");

obj = null; // obj への強い参照がなくなる
// GCが発生すると、コールバックが実行される

まとめ

[編集]

ECMAScriptにおける遅延評価の歴史は、以下のように進化してきました:

  1. ES6: ジェネレータとイテレータの導入により、基本的な遅延評価が可能に。
  2. ES2018: 非同期ジェネレータと非同期イテレータの導入により、非同期処理における遅延評価が実現。
  3. ES2020: Promise.allSettled の導入により、非同期処理の遅延評価が柔軟に。
  4. ES2021: WeakRefFinalizationRegistry の導入により、弱参照を使った遅延評価が可能に。