アラン・ストームのコメント私の回答に対する返答としてwith
声明考えさせられました。この特定の言語機能を使用する理由はほとんどなく、それがどのように問題を引き起こすかについてはあまり考えたことがありませんでした。今、私は、with
の落とし穴を避けながら を効果的に使用する方法を知りたいです。
この声明はどこで役立ちましたかwith
?
ベストアンサー1
今日、別の用途が思い浮かんだので、興奮しながらウェブで検索したところ、それに関する既存の言及を見つけました。ブロックスコープ内での変数の定義。
背景
JavaScript は、表面的には C や C++ に似ていますが、変数のスコープを、それが定義されているブロックに限定しません。
var name = "Joe";
if ( true )
{
var name = "Jack";
}
// name now contains "Jack"
ループ内でクロージャを宣言することは、エラーにつながる可能性がある一般的なタスクです。
for (var i=0; i<3; ++i)
{
var num = i;
setTimeout(function() { alert(num); }, 10);
}
for ループは新しいスコープを導入しないため、同じnum
- と - の値が2
3 つの関数すべてで共有されます。
新たなスコープ:let
そしてwith
let
声明の導入により、ES6、これらの問題を回避するために、必要に応じて新しいスコープを導入することが容易になります。
// variables introduced in this statement
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
setTimeout(function() { alert(i); }, 10);
}
あるいは:
for (var i=0; i<3; ++i)
{
// variables introduced in this statement
// are scoped to the block containing it.
let num = i;
setTimeout(function() { alert(num); }, 10);
}
ES6 が広く利用可能になるまで、この使用は最新のブラウザとトランスパイラを使用する意思のある開発者に限定されます。ただし、次の方法を使用してこの動作を簡単にシミュレートできますwith
。
for (var i=0; i<3; ++i)
{
// object members introduced in this statement
// are scoped to the block following it.
with ({num: i})
{
setTimeout(function() { alert(num); }, 10);
}
}
ループは意図したとおりに動作し、0から2までの値を持つ3つの別々の変数を作成します。ブロック内で宣言された変数は、C++のブロックの動作とは異なり、ブロック内にスコープされないことに注意してください(Cでは、変数はブロックの先頭で宣言する必要があるため、ある意味では似ています)。この動作は、実際にはlet
ブロック構文Mozilla ブラウザの以前のバージョンで導入されましたが、他の場所では広く採用されていません。