sosukesuzuki.dev

2022年 sosukesuzuki 1人アドベントカレンダー

December, 01 2022

Stage 3 Array Grouping プロポーザル の Web の互換性の問題

2022年の sosukesuzuki 1人アドベントカレンダー 1 日目です。

何日まで続くかなぁ。

初日は Array Grouping の名前を巡る問題についてです。

Array Grouping とは

Array Grouping は現在 Stage 3 のプロポーザルで、Lodash の groupBy に相当するものを ECMAScript に導入するプロポーザルです。

プロポーザルのリポジトリは https://github.com/tc39/proposal-array-grouping にあります。

このプロポーザルは Array.prototype.groupArray.prototype.groupToMap というプロトタイプメソッドを追加します。これらのメソッドは具体的には次のように使われます。

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const fn = (number) => {
if (number % 2 === 0) {
return "even";
}
return "odd";
};
const resultObj = numbers.group(fn);
console.log(resultObj);
// {
// "even": [2, 4, 6, 8, 10],
// "odd": [1, 3, 5, 7, 9]
// }
const resultMap = number.groupToMap(fn);
console.log(resultMap);
// Map {
// {even: true}: [2, 4, 6, 8, 10] },
// {odd: true}: [1, 3, 5, 7, 9],
// }

こんなふうに配列の要素をグルーピングできます。Array.prototype.groupToMapの方は結果がオブジェクトではなくMapになります。

この記事を書いているときに知ったんですが Array.prototype.groupArray.prototype.groupToMap ってすでに MDN に追加されているんですね。

命名を巡る問題

このプロポーザルの機能自体はそこまで派手なものではないのですが、命名を巡って何度か議論が行われてきました。

プロポーザルの現在の仕様では、追加されるメソッドは group という名前になっていますが、もともとは groupBy という名前でした。

しかし groupBy という名前は Web の互換性の問題があることがあとになってから明らかになりました。Sugar.js というライブラリが v1.4.0 まで Array.prototype.groupBy という名前のメソッドを実装していたのです。そして、このライブラリを使っているウェブサイトが 660 個もあったそうです。もし ECMAScript に Array.prototype.groupBy が追加され各種 JS エンジンに実装されたら、それらのウェブサイトは動かなくなってしまうかもしれません。そのため、 groupBy から group へと改名されました。

ところが、最近になって group という名前も同様の問題を抱えていることが明らかになりました。なので再度仕様を修正する必要が出てきました。

そこで2つの対処法が提示されました。

1つ目は、再度改名する方法です。候補としては groupToObject/groupToMapgrouping/groupingToMap などがあったようです。

2つ目は、Object.groupByMap.groupBy のようなスタティックメソッドとして定義する方法です。

この問題についてはまだ結論は出ていないようですが、2022 年 11 月の TC39 ミーティングでは、スタティックメソッドを定義する方法が支持されたそうです。

プロポーザルのチャンピョンはこれから仕様テキストを修正して次回のミーティングに臨むそうなので、仕様が確定するまでにはまだ時間がかかりそうです。

どうなる?

どうなるんですかね

わからないですが、もしスタティックメソッドとして定義されるのであれば Array Grouping は Stage 3 になってから大幅に修正されたプロポーザルということになるので、珍しくておもしろいですね。

また、Web を破壊しないぞという TC39 の姿勢が伝わってくる良い事例だと思いました。