構文
with (object) statement
withは新しいスコープを作成し、オブジェクトのプロパティをステートメントのローカル変数として表します。 例(1つの式にブラケットは必要ありませんが、使用することをお勧めします):
with({ first: "John" }) { console.log("Hello " + first); } // Hello John
プロパティが同時にグローバル変数である同様のオブジェクトがあります-このオブジェクトはグローバルと呼ばれます(ブラウザではこれはウィンドウです)。 ただし、グローバルオブジェクトとは異なり、withステートメント(ステートメントブロック)で宣言された変数はオブジェクトに追加されませんが、外部スコープにリークして存在し続けます。
with({}) { var x = "abc"; } console.log(x) // 'abc'
withステートメントは非推奨です
withステートメントを使用することはお勧めできません。 厳格モードではその使用は禁止されています 。
function foo() { "use strict"; with({}); } // SyntaxError: strict mode code may not contain 'with' statements
置き換える方法:
with(foo.bar.baz) { console.log("Hello "+first+" "+last); }
変数をwithに渡す代わりに、短い名前を使用します。
var b = foo.bar.baz; console.log("Hello "+b.first+" "+b.last);
スコープ内で一時変数を宣言したくない場合は、 IIFEを使用します 。
(function() { var b = foo.bar.baz; console.log("Hello "+b.first+" "+b.last); }());
このオブジェクトをIIFEパラメーターとして転送することもできます。
(function(b) { console.log("Hello "+b.first+" "+b.last); }(foo.bar.baz));
なぜ悪いのか
withが推奨されない理由を理解するために、例を見て、関数の引数がその動作をどのように変えるかを見てみましょう。 関数は次のとおりです。
function foo(arg) { with(arg) { console.log("arg: " + arg) } }
異なるパラメーターで関数を実行します。
foo("Hello"); // arg: Hello - arg foo({}); // arg: [object Object] - arg foo({ arg: "Hello" }); // arg: Hello - arg.arg!
withが廃止される理由は2つあります。
パフォーマンス :withステートメントは、argが実際の変数またはwith内の変数プロパティを参照する場所が事前にわからないため、自動的に最適化できません。 これは、呼び出しごとに変わる場合があります。
安全性 :変数が周囲(レキシカル環境)を参照する場所を特定することは不可能です。 Brendan Eichによれば、これはwithが時代遅れであると考えられているためであり、パフォーマンスを考慮するためではありません。