JavaScript 動的な連想配列の管理方法
? (JavaScript) (動的)な(連想配列)を (entries|Array|Object) で(管理)する
JavaScript のオブジェクトを使うと、場合によっては脆弱性になりうる。
code: js
const data = {
a: 1,
b: 2,
// ...
};
const key = /* ユーザー入力値 */;
// ユーザーが key に "hasOwnProperty" とかを入力してきたら危ない。
console.log(datakey);
id 付きの Array を使うと、データの探索に計算コストがかかって、連想配列としてのメリットは失われそう。
code: js
const data = [
{ id: "a", value: 1 },
{ id: "b", value: 2 },
];
const key = /* ユーザー入力値 */;
// 探索の計算コストがかかる。
console.log(data.find(({id}) => id === key));
entries で data を持っておいて、データを探索したり操作するときだけ Map を使うのはどうか?
Map は JavaScript エンジンがネイティブで実装している。
一時的ではなく、常にデータを Map で持つのもありだと思う。
code: js
const data = [
"a", 1,
"b", 2,
];
const key = /* ユーザー入力値 */;
console.log(new Map(data).get(key));
スピード測定
Node.js v16.13.0
n = 10000
code: js
const indexes = ...Array(10000).keys();
(() => {
const array = indexes.map((index) => ({ id: index, value: Math.random() }));
const startTime = performance.now();
indexes.forEach((index) => array.find(({ id }) => id === index)?.value);
const endTime = performance.now();
console.log("Array");
console.log(${endTime - startTime} ms);
})();
(() => {
const entries = indexes.map((index) => index, Math.random());
const map = new Map(entries);
const startTime = performance.now();
indexes.forEach((index) => map.get(index));
const endTime = performance.now();
console.log("Map を1度だけ生成する");
console.log(${endTime - startTime} ms);
})();
(() => {
const entries = indexes.map((index) => index, Math.random());
const startTime = performance.now();
indexes.forEach((index) => new Map(entries).get(index));
const endTime = performance.now();
console.log("Map を毎回生成する");
console.log(${endTime - startTime} ms);
})();
結果
code: bash
$ node test.mjs
Array
61.54491899907589 ms
Map を1度だけ生成する
0.4302249997854233 ms
Map を毎回生成する
7529.377149000764 ms
Map を1度だけ生成する 0.4302 ms
143倍
Array 61.54 ms
122 倍
Map を毎回生成する 7529 ms
まあ、パフォーマンスを最適化するのは明らかに動作が遅いときだけにして、
普段は Array でも Map でも書きやすい方法を選んだほうがコードを書く効率良さそう。