Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
JavaScriptの便利な構文に潜む罠
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
kentaro ishida
October 10, 2025
Programming
16
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
JavaScriptの便利な構文に潜む罠
kentaro ishida
October 10, 2025
More Decks by kentaro ishida
See All by kentaro ishida
UXから考えるクライアントサイドのパフォーマンス監視設計
ishida2002
0
30
Storybookのインタラクションテストで UIの仕様をテストする
ishida2002
0
33
Renovateを(できるだけ)ノールックマージする
ishida2002
0
16
Other Decks in Programming
See All in Programming
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
290
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
250
The Arts and Crafts of Work in the AI Era — Toward Mastery in Software Development
kuranuki
1
720
Oxcを導入して開発体験が向上した話
yug1224
4
290
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
4.2k
Modding RubyKaigi for Myself
yui_knk
0
890
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
560
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
3.5k
net-httpのHTTP/2対応について
naruse
0
440
プロパティの順序で型推論が壊れる!? TypeScript6.0の修正からContext-Sensitivityの仕組みを追う
bicstone
2
1.3k
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
310
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
190
Featured
See All Featured
KATA
mclloyd
PRO
35
15k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
380
Utilizing Notion as your number one productivity tool
mfonobong
4
310
Music & Morning Musume
bryan
47
7.2k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
550
[SF Ruby Conf 2025] Rails X
palkan
2
1.1k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
150
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
320
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
Marketing to machines
jonoalderson
1
5.4k
Transcript
JavaScriptの便利な構文に潜む罠 石田 健太郎 2025年10月10日
自己紹介 石田 健太郎(いしだ けんたろう) 株式会社kubell 新卒2年目のフロントエンドエンジニア 「Chatwork」のブラウザ版・デスクトップ版の開発 を担当 学生時代は競技プログラミングをやってました パフォーマンス改善とかが好きです
今日はパフォーマンス改善について話します
便利構文と罠
スプレッド構文、使ってますか?
スプレッド構文 配列やオブジェクトを展開する構文 Object.assign() や Array.prototype.concat() 相当の処理を簡潔に記述できる const obj = {
a: 'foo' }; const newObj = { ...obj, b: 'bar' }; console.log(newObj); // { a: "foo", b: "bar" } const arr = [1, 2, 3]; const newArr = [...arr, 4, 5]; console.log(newArr); // [1, 2, 3, 4, 5]
便利ですねー
さて、こんなコードがあります
問題のコード よくあるAPIからのレスポンスを整形しているコード 別にいいんじゃないの? const rooms = Object.entries(response.room_dat).reduce( (accumulator, [roomId, room])
=> { // 処理 return { ...accumulator, [roomId]: formattedRoom }; }, {}, );
スプレッド構文についてもう少し深掘り
スプレッド構文 スプレッド構文は1段階のシャローコピーを生成する ネストしたオブジェクトでなければ書き換えても影響が無いので便利 const obj = { a: 'foo', b:
{ c: 'bar' } }; const newObj = { ...obj }; newObj.a = 123; newObj.b.c = 456; console.log(obj.a); // foo console.log(obj.b.c); // 456
ここに落とし穴
スプレッド構文の落とし穴 コピーを生成するということは、コピーする要素数に応じた処理が必要になる オーダー記法で O(N) と表記される const obj = { a:
'foo', b: { c: 'bar' } }; const newObj = { ...obj }; // obj の要素数に応じた処理が必要 newObj.a = 123; newObj.b.c = 456; console.log(obj.a); // foo console.log(obj.b.c); // 456
問題のコード(再掲)
問題のコード reduce の中で accumulator をスプレッド構文で展開している const rooms = Object.entries(response.room_dat).reduce( (accumulator,
[roomId, room]) => { // 処理 return { ...accumulator, [roomId]: formattedRoom }; // ここが問題 }, {}, );
何が問題なのか reduce が進むにつれて展開されるオブジェクトが増えていく N個の要素を処理するには 0 + 1 + 2 ...
N-3 + N-2 + N-1 個分のオブジェクトが展 開される オーダー記法にすると O(N^2) 理論上要素数の二乗に比例する処理が必要 手元の環境では1万を超えると顕著に重くなり、10万を超えたあたりで分単位の時間が かかるようになった {}; // 1回目のreduceで展開されるaccumulator { 1: 'foo' }; // 2回目のreduceで展開されるaccumulator { 1: 'foo', 2: 'bar' }; // 3回目のreduceで展開されるaccumulator { 1: 'foo', 2: 'bar', 3: 'buz' }; // 4回目のreduceで展開されるaccumulator { 1: 'foo', 2: 'bar', 3: 'buz', 4: 'qux' }; // 5回目のreduceで展開されるaccumulator
改善しよう
改善しよう 基本的にどの言語も key-value 形式のデータ構造の操作は O(1) 単純に accumulator に代入する処理に変えることで O(N^2) から
O(N) に改善 reduce 内で accumulator に破壊的な操作をした場合、第二引数で渡した初期値が影響 を受ける 今回は初期値が空オブジェクトなので問題なし 変更を加えたくない場合は引数に渡す時点でスプレッド構文で展開すればOK const rooms = Object.entries(response.room_dat).reduce( (accumulator, [roomId, room]) => { // 処理 accumulator[roomId] = formattedRoom; return accumulator; }, {}, );
まとめ
まとめ スプレッド構文は展開する要素数に応じた処理が必要 reduce 等の O(N) の処理の中で使用すると、 O(N^2) になってしまうことがある forループや map
, forEach 等の配列の高階関数も注意 単に要素の追加や上書き処理にスプレッド構文を使用している場合は、一時変数を直接 上書きするように変更すれば改善できる
None