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


Source: https://habr.com/ru/post/J120364/


All Articles