Javascript Strict Mode, with

21298 ワード

Strict Modeとは


JavascriptのES 5に追加されたStrict Modeについて説明します.
function func() {
  x = 10;
  return x;
}

console.log(x);
上記のコードではxは宣言されていません.
ここで、x値を参照するには、JavaScriptエンジンが変数xを宣言するスキャンチェーンを検索します.
親オブジェクトのscopeにも見つからない場合は、グローバルオブジェクトにxが作成され、グローバル変数になります.この変数を黙々としたグローバル変数と呼ぶ.このような状況の多くは開発者のミスで意図的ではない.このような状況が発生したくない場合は、宣言キーを使用して変数を宣言できます.
このような開発者の誤りを誤りで表現すればよいが,表現できない誤りがある.そうであれば,開発者はこれが誤りであることに気づきにくく,後で知ったときにも解決しにくい.このような以前無視されていた誤りが明確に支持されて誤りを生じたのはstrict modeである.このような役割を果たすツールにはESLintがあります.ESLintはstrictModeと同様の効果を得ることができる.ESLintでは、構文エラーと潜在的なエラーが報告されます.

Strict Modeの適用

'use strict';は、文法を適用したい場所に追加されます.この構文はコードの上にあることが望ましい.主にドメイン全体の最初のビットまたは関数の最初のビットに位置します.先頭に立たないと正常に仕事ができない.

グローバル使用

'use strict';

function func() {
  a = 10; 
}

func();
グローバルの一番上に追加すると、スクリプト全体がstrict modeを使用します.全域のゾーンスキャンが適用されます.上記の場合、aが定義されていないReferenceError: a is not definedが生成される.

関数の使用

function func() {
  'use strict';
  a = 10; 
}

func();
関数の一番上に追加すると、関数の内部と内部の関数にstrictmodeが使用されます.関数に適用すると、ReferenceError: a is not definedのエラーが発生します.

厳格モード使用上の注意事項


1.strict modeをグローバルに使用する場合


グローバルで使用されるstrictモードは、このスクリプトに適用されます.同じスクリプト内のすべての関数が適用されますが、他のスクリプトは適用されません.複数のスクリプトが適用されている場合は、すべてのスクリプトをグローバルに適用する必要があります.グローバル厳格モードはスクリプト単位で適用されるためです.
<!DOCTYPE html>
<html>
<body>
  <script>
    'use strict';
  </script>
  <script>
    a = 1; // 에러가 발생하지 않는다.
    console.log(a); // 1
  </script>
  <script>
    'use strict';
    b = 1; // ReferenceError: b is not defined
    console.log(b);
  </script>
</body>
</html>
外部ライブラリにnonstrictモードを使用するライブラリがあり、一部のスクリプトが適用され、一部のスクリプトが適用されない場合は、エラーが発生する可能性があります.グローバルな使用は、さまざまな状況を考慮して使用することが望ましい.考えにくい場合は、グローバルな使用は避けたほうがいいです.インスタント実行関数にstrict modeを適用する方法がある.
(function () {
  'use strict';
  ...
}());

2.関数にstrict modeを使用する場合


strictモードをグローバルにスクリプト単位で適用する場合と同様です.関数単位のうち、一番上の「use strict」.strict modeを適用できる追加.これでは、すべての関数にstrictmodeを使用する必要があります.関数を適用せずに適用すると、エラーが発生します.
グローバルで説明したように、スクリプト単位でインスタント実行関数に厳格なモードを適用すると、管理が最も容易になります.

厳格なパターンのエラーが発生しました


1.宣言されていない変数を参照

(function () {
  'use strict';
  a = 10;
  console.log(a);
}());
aを宣言せずにaを参照すると、ReferenceError: a is not definedエラーになります.

2.変数、関数およびパラメータの削除

(function () {
  'use strict';

  let a = 1;
  delete a;

  function func(b) {
    delete b;
  }
  delete func;
}());
宣言された変数、パラメータ、および関数がstrict modeから削除されると、SyntaxError: Delete of an unqualified identifier in strict mode.エラーが発生します.
strictモードがないとエラーは発生しません.

3.繰り返し使用パラメータ

(function () {
  'use strict';

  function func(a, a) {
    return a + a;
  }
  console.log(foo(1, 2));
}());
同じ名前のパラメータを1つの関数で繰り返し使用すると、SyntaxError: Duplicate parameter name not allowed in this contextエラーが発生します.

4.with文の使用

(function () {
  'use strict';

  with({ x: 1 }) {
    console.log(x);
  }
}());
with文を使用すると、構文エラーSyntaxError: Strict mode code may not include a with statementが発生します.

5.一般関数のthis

(function () {
  'use strict';

  function func() {
    console.log(this); // undefined
  }
  foo();

  function Func() {
    console.log(this); // Func
  }
  new Func();
}());
コンストラクション関数ではなく通常の関数からthisを呼び出すとundefinedになります.一般的な関数ではthisは使用されていないので、エラーは発生しません.

見知らぬwithを知りましょう。

(function () {
  let user = { 
    name: "kimcoding", 
    role: "back-end", 
    language: "java" 
  } 
  with (user) { 
    console.log(name === "kimcoding"); // true
    console.log(role === "back-end");  // true
    console.log(language === "java");  // true
    language = "javascript"; 
  } 
  console.log(user.language === "javascript"); // true
}());
userオブジェクトに情報が含まれ、with文を使用してカッコ内にオブジェクトを配置する場合、ブロックにname、roleなどのキー値にuserオブジェクト情報を入力する必要はありません.with文では言語に直接アクセスできます.これは、userオブジェクトをscope chainに追加したためです.
別の例を見てください.
(function acc() {
  let r = 10, a, x, y; 
  with (Math) { 
    a = PI * r * r; 
    x = r * cos(PI); 
    y = r * sin(PI / 2); 
  }
  console.log(a, x, y); // 314.1592653589793 -10 10
}());
Mathは、オブジェクト内のメソッドにより簡単にアクセスできます.
しかし、専門家は使えないと言っています.最大の原因はwithの曖昧性です.
(function func(value, obj) { 
  with (obj) { 
    value = "parameter or obj?"; 
    console.log(value); 
  }
}());
valueパラメータから来たのか、objのキーにvalueがあるのか、このコードでvalueキーから来たのか判断できますか?関数のパラメータが参照するオブジェクトのキー値と同じ場合、どこから参照するか分かりにくいです.
少し便利ですが、コードの毒性を低下させ、メンテナンスに混乱をもたらす可能性があるので、お勧めしません.
参考資料[All-Round Programmer]