やあ。今日もコードと格闘しているかな?
フロントエンドの世界は進化が早いが、モダンなフレームワークの裏側にある「JavaScriptの泥臭い歴史」を知っているかどうかで、トラブルシューティングの質は劇的に変わる。
今日は、現代の現場では「禁忌」とされている、しかしJavaScriptという言語の深淵を覗くには避けて通れない`with`文について話そう。なぜこれが駆逐されたのか、そしてブラウザのエンジンが泣きを見る仕組みはどうなっているのか。中級者の君なら、この「なぜ」を理解することで、一歩上の視座を手に入れられるはずだ。
—
`with`文とは何だったのか?
一言で言えば、「スコープチェーンの強制的な汚染」だ。
通常、変数を参照するとき、JavaScriptエンジンは現在のスコープから外側へと順に探索していく。`with`文は、その探索ルートの先頭に、指定したオブジェクトを強引に割り込ませる仕組みなんだ。
現場で見る「かつての魔法」
const user = {
name: ‘Alice’,
age: 25,
job: ‘Frontend Engineer’
};
// with文を使うと、オブジェクトのプロパティを「ローカル変数」のように扱える
with (user) {
console.log(`名前は${name}、職業は${job}です。`); // 内部的に user.name, user.job として解決される
}
一見すると、`user.`という冗長なプレフィックスを省略できてスマートに見えるだろう? 昔のエンジニアは、DOM操作などでこれが便利だと信じていたんだ。だが、これが地獄の入り口だった。
—
なぜ現代のJavaScriptでは「悪」と断定されるのか
理由は大きく分けて2つある。「パフォーマンスの低下」と「予測不能なバグの温床」だ。
1. ブラウザエンジンの最適化を殺す
現代のV8エンジン(Chrome等)は、変数の場所をコンパイル時に予測して高速化(インラインキャッシュなど)を行っている。しかし、`with`文があると、エンジンは「この識別子がスコープ内にあるのか、それとも`with`で渡されたオブジェクトの中にあるのか」を実行時まで判断できない。
結果として、コンパイラは最適化を諦めるしかない。`with`を使った関数内では、コードの実行速度がガクンと落ちるんだ。これはパフォーマンスが命のフロントエンドにおいて、許されない選択だ。
2. 意図しない変数汚染(スコープの不透明化)
これが一番厄介だ。次のコードを見てほしい。
const user = { name: ‘Bob’ };
let name = ‘Global Alice’;
with (user) {
// ここで name は誰を指す?
// もし user に name があれば user.name だが、なければ外側の name になる
console.log(name);
}
このコード、`user`オブジェクトの構造を完全に把握していないと、どちらの `name` を参照しているか確信が持てないだろう? さらに悪いことに、`with`ブロック内で新しい変数を代入しようとした時、それがオブジェクトの更新なのか、外側のスコープへの変数定義なのか、コードを読むだけでは判別不能になることがある。
これが、コードの「可読性」と「保守性」を破壊するんだ。チーム開発でこんなコードを残されたら、後任者は夜も眠れなくなるよ。
—
「代替案」はどうすべきか?
今の現場では、素直に「解体代入(Destructuring Assignment)」を使うのがベストプラクティスだ。
const user = {
name: ‘Charlie’,
age: 30,
job: ‘Architect’
};
// withを使わず、必要な変数だけをスコープに引き出す
const { name, job } = user;
console.log(`名前は${name}、職業は${job}です。`);
// これなら、どこから値が来たのか明確だし、エンジンも爆速で最適化できる
解体代入は、名前の競合も防げるし、TypeScriptを使っていれば型推論も完璧に効く。`with`文が持っていた「利便性」を、安全かつ高速に再現できるんだ。
—
アーキテクトからの助言
結論として、`with`文は「存在しないもの」として扱ってほしい。
Strictモード(`’use strict’;`)では、そもそも`with`文は構文エラーとして弾かれる。もし君のプロジェクトで`with`文を見かけたら、それは「負債」だ。即座にリファクタリング対象としてチケットを切ることを勧める。
JavaScriptは柔軟な言語だ。だからこそ、「書けるから書く」のではなく、「なぜこれを使うのか、他にリスクはないか」を自問自答できるエンジニアが、結局のところ最強なんだ。
次は、`var`の巻き上げ(Hoisting)と、なぜ私たちが `const` / `let` を愛してやまないのかについて話そうか。また現場で会おう。

コメント