enumをどう書くか?
JavaScript には C/C++ で使われる enum のような仕組みがない。
雑な作り方でいいのであれば、以下のようにプロパティとして値を設定する方法がある。
code:mjs
const MyConst = {
XXX: 1,
YYY: 2
};
// モジュールとして外部に公開する場合
export default MyConst;
code:mjs
import MyConst from "./MyConst.mjs"
console.log(MyConst.XXX);
唯一無二のユニークIDとして作りたい場合は、Symbol を使うのが望ましい。
code:mjs
const MyEnum1 = {
XXX: Symbol("XXX"),
YYY: Symbol("YYY")
};
const MyEnum2 = {
XXX: Symbol("XXX"),
YYY: Symbol("YYY")
};
console.log(MyEnum1.XXX == MyEnum2.XXX); // false
パフォーマンスを気にするならば、オブジェクトのメンバーアクセスを避けるのが望ましい。
しかしそれでもせいぜい1.4倍程度の差しかない。
code:js
// メンバーの解決が必要
const MAIN = {
SUB: Symbol("SUB")
};
// 直接
const MAIN_SUB = Symbol("SUB");
Chrome でパフォーマンス測定した結果
code:txt
ウォームアップ実行中...
1,000,000 回の繰り返しでベンチマークを実行します
ネストしたアクセス (MAIN.SUB): 1.90 ms
直接アクセス (MAIN_SUB): 1.40 ms
差分: 0.50 ms
比率: 直接アクセスはネストしたアクセスの 1.36 倍速い
本番ベンチマーク開始...
5 回のベンチマークを実行して平均を計算します
===== ベンチマーク実行 1/5 =====
10,000,000 回の繰り返しでベンチマークを実行します
ネストしたアクセス (MAIN.SUB): 12.00 ms
直接アクセス (MAIN_SUB): 10.70 ms
差分: 1.30 ms
比率: 直接アクセスはネストしたアクセスの 1.12 倍速い
===== ベンチマーク実行 2/5 =====
10,000,000 回の繰り返しでベンチマークを実行します
ネストしたアクセス (MAIN.SUB): 11.90 ms
直接アクセス (MAIN_SUB): 10.90 ms
差分: 1.00 ms
比率: 直接アクセスはネストしたアクセスの 1.09 倍速い
===== ベンチマーク実行 3/5 =====
10,000,000 回の繰り返しでベンチマークを実行します
ネストしたアクセス (MAIN.SUB): 11.80 ms
直接アクセス (MAIN_SUB): 10.70 ms
差分: 1.10 ms
比率: 直接アクセスはネストしたアクセスの 1.10 倍速い
===== ベンチマーク実行 4/5 =====
10,000,000 回の繰り返しでベンチマークを実行します
ネストしたアクセス (MAIN.SUB): 11.80 ms
直接アクセス (MAIN_SUB): 10.70 ms
差分: 1.10 ms
比率: 直接アクセスはネストしたアクセスの 1.10 倍速い
===== ベンチマーク実行 5/5 =====
10,000,000 回の繰り返しでベンチマークを実行します
ネストしたアクセス (MAIN.SUB): 11.40 ms
直接アクセス (MAIN_SUB): 10.50 ms
差分: 0.90 ms
比率: 直接アクセスはネストしたアクセスの 1.09 倍速い
===== 平均結果 =====
平均ネストしたアクセス時間: 11.78 ms
平均直接アクセス時間: 10.70 ms
平均差分: 1.08 ms
平均比率: 直接アクセスはネストしたアクセスの 1.10 倍速い
Claude により作成
(ダミー操作は効いてないかも?)
code:js
(
() => {
// メンバーの解決が必要なケース
const MAIN = {
SUB: Symbol("SUB")
};
// 直接アクセスのケース
const MAIN_SUB = Symbol("SUB");
// ベンチマーク用の関数
function runBenchmark(iterations = 10000000) {
console.log(${iterations.toLocaleString()} 回の繰り返しでベンチマークを実行します);
// メンバーアクセスのベンチマーク
const startNested = performance.now();
for (let i = 0; i < iterations; i++) {
const symbol = MAIN.SUB;
// 最適化で除去されないようにするためのダミー操作
if (symbol !== MAIN.SUB) console.log("This will never happen");
}
const endNested = performance.now();
const nestedTime = endNested - startNested;
// 直接アクセスのベンチマーク
const startDirect = performance.now();
for (let i = 0; i < iterations; i++) {
const symbol = MAIN_SUB;
// 最適化で除去されないようにするためのダミー操作
if (symbol !== MAIN_SUB) console.log("This will never happen");
}
const endDirect = performance.now();
const directTime = endDirect - startDirect;
// 結果の表示
console.log(ネストしたアクセス (MAIN.SUB): ${nestedTime.toFixed(2)} ms);
console.log(直接アクセス (MAIN_SUB): ${directTime.toFixed(2)} ms);
console.log(差分: ${(nestedTime - directTime).toFixed(2)} ms);
console.log(比率: 直接アクセスはネストしたアクセスの ${(nestedTime / directTime).toFixed(2)} 倍速い);
return {
nestedTime,
directTime,
difference: nestedTime - directTime,
ratio: nestedTime / directTime
};
}
// 複数回実行して平均を取る
function runMultipleBenchmarks(runs = 5, iterations = 10000000) {
const results = [];
console.log(${runs} 回のベンチマークを実行して平均を計算します);
for (let i = 0; i < runs; i++) {
console.log(\n===== ベンチマーク実行 ${i + 1}/${runs} =====);
results.push(runBenchmark(iterations));
}
// 平均値の計算
const avgNestedTime = results.reduce((sum, r) => sum + r.nestedTime, 0) / runs;
const avgDirectTime = results.reduce((sum, r) => sum + r.directTime, 0) / runs;
const avgDifference = avgNestedTime - avgDirectTime;
const avgRatio = avgNestedTime / avgDirectTime;
console.log("\n===== 平均結果 =====");
console.log(平均ネストしたアクセス時間: ${avgNestedTime.toFixed(2)} ms);
console.log(平均直接アクセス時間: ${avgDirectTime.toFixed(2)} ms);
console.log(平均差分: ${avgDifference.toFixed(2)} ms);
console.log(平均比率: 直接アクセスはネストしたアクセスの ${avgRatio.toFixed(2)} 倍速い);
}
// ベンチマークの実行
// 少ない回数でウォームアップ
console.log("ウォームアップ実行中...");
runBenchmark(1000000);
// 本番ベンチマーク
console.log("\n本番ベンチマーク開始...");
runMultipleBenchmarks(5, 10000000);
}
)();
関連