withステートメントと使用しない理由

この記事では、withがJavaScriptを使用する方法と、JavaScriptの使用が推奨されない理由について説明します。



構文



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が時代遅れであると考えられているためであり、パフォーマンスを考慮するためではありません。



All Articles