JavaScript の Strict モードの詳細な説明

JavaScript の Strict モードの詳細な説明

導入

ES5 では、厳密モードと呼ばれる厳密モードが導入されました。対応するずさんなモードは、非厳密モードと呼ぶことができます。

厳密モードは非厳密モードのサブセットではありません。逆に、厳密モードは非厳密モードとは意味的に若干の違いがあるため、使用時には厳密なテストを実施する必要があります。厳密モードでのプログラムの実行が非厳密モードでの実行と一貫していることを確認します。

厳密モードの使用

厳密モードでは JavaScript の動作の一部が変更されます。これについては次のセクションで詳しく説明します。

厳格モードの使い方を見てみましょう。

厳密モードは主に完全なスクリプトまたは関数で使用され、ブロック {} には適用されません。 ブロック内で厳密モードを使用した場合、効果はありません。

さらに、eval 内のコード、関数コード、イベント ハンドラー属性、および WindowTimers.setTimeout() に渡される文字列はすべて、完全なスクリプトと見なすことができます。その中で Strict モードを使用できます。

スクリプトで厳密モードを使用する場合は、スクリプトの先頭に「use strict」を直接追加できます。

// スクリプト全体の厳密モード 'use strict';
var v = "こんにちは!私は厳密モードのスクリプトです!";

同様に、関数内で厳密モードを使用することもできます。

関数 strict() {
  // 関数の厳密モード 'use strict';
  function nested() { return '私もです!'; }
  return "こんにちは!私は厳密モード関数です!" + nested();
}
function notStrict() { return "私は厳格ではありません。"; }

ES6 で導入されたモジュールを使用している場合、モジュールはデフォルトですでに厳密モードになっているため、追加で「use strict」を使用する必要はありません。

関数myModule() {
    // デフォルトは厳密モードです}
デフォルトのmyModuleをエクスポートします。

厳格モードの新機能

厳密モードでは、非厳密モードと比較して、構文と実行時パフォーマンスにいくつかの違いがあります。次に、それらを 1 つずつ見ていきましょう。

例外を強制的にスローする

js では、操作が間違っている可能性が多々ありますが、言語の特性上、例外がスローされず、最終的な実行結果が期待したものと異なることがあります。

厳密モードを使用すると、例外が直接スローされます。

たとえば、厳密モードでは、未定義のグローバル変数は許可されません。

'厳密な使用';

globalVar = 10; //ReferenceError: globalVar が定義されていません

これにより、誤って間違った変数名を入力することで発生する問題を実際に回避できます。

他の例も見てみましょう:

'厳密な使用';

// 書き込み不可のグローバル変数に代入する、
var undefined = 5; // TypeError をスローします
var Infinity = 5; // TypeError をスローします

// 書き込み不可のプロパティに値を割り当てる var obj1 = {};
Object.defineProperty(obj1, 'x', { 値: 42, 書き込み可能: false });
obj1.x = 9; // TypeError をスローします

// get メソッドに値を割り当てます var obj2 = { get x() { return 17; } };
obj2.x = 5; // TypeError をスローします

// 拡張を許可しないオブジェクトへの割り当て var fixed = {};
Object.preventExtensions(固定);
fixed.newProp = 'ohai'; // TypeError をスローします

厳密モードでは、コンストラクターのプロトタイプなど、削除できないプロパティの削除を制限できます。

'厳密な使用';
Object.prototypeを削除します。 // TypeErrorをスローします

オブジェクトおよび関数パラメータ内の重複プロパティを許可しません。

'厳密な使用';
var o = { p: 1, p: 2 }; // 重複宣言

function sum(a, a, c) { // 重複宣言
    '厳密な使用';
    a + a + c を返します。
}

プリミティブ型のプロパティの設定は禁止されています。

(関数() {
'厳密な使用';

false.true = ''; // タイプエラー
(14).sailing = 'home'; // TypeError
'with'.you = 'far away'; // TypeError

})();

変数の使用を簡素化する

厳密モードを使用すると、変数の使用が簡素化され、プログラム コードが読みやすくなります。

まず、厳密モードでは with の使用が禁止されます。

with は非常に強力です。with にオブジェクトを渡すことで、変数検索のスコープ チェーンに影響を与えることができます。つまり、with ブロック内で特定の属性を使用する必要がある場合、既存のスコープ チェーン内の検索に加えて、with によって渡されたオブジェクト内でも検索することになります。

(表現)と
  声明

with は通常、次のようにコードを簡素化するために使用されます。

var a, x, y;
var r = 10;

(数学) {
  a = PI * r * r;
  x = r * cos(PI);
  y = r * sin(PI / 2);
}

上記の例では、PI は Math オブジェクト内の変数ですが、with ブロック内で直接使用できます。 Java のインポートに少し似ています。

次の例は、 with を使用した場合の問題を示しています。

関数 f(x, o) {
  (o) {と
    コンソールログ(x);
  }
}

withブロックでx変数を出力します。コードから、f関数がx変数を渡していることがわかります。しかし、with が使用するオブジェクトにも x 属性がある場合は、予期しない問題が発生します。

したがって、厳密モードでは、 with は禁止されます。

2 番目は eval への変更です。

従来のモードでは、eval で定義された変数は、eval を含むスコープに自動的に追加されます。例を見てみましょう:

var x = 17;
var evalX = eval("var x = 42; x;");
コンソールログ(x);

新しい変数 x が eval に導入されるため、x の値は最初に定義された x=17 を上書きします。最終的に、結果は 42 になります。

use strict が追加されると、eval 内の変数は既存のスコープに追加されず、結果 17 が返されます。

var x = 17;
var evalX = eval("'use strict'; var x = 42; x;");
コンソールログ(x);

これを行う利点は、既存のプログラム ロジックに対する eval の影響を回避できることです。

厳密モードでは、名前の削除は許可されません。

'厳密な使用';

var x;
delete x; // !!! 構文エラー

eval('var y; delete y;'); // !!! 構文エラー~~

議論を単純化する

js では、引数はパラメータの配列を表します。まず、Strict モードでは、引数を変数名として割り当てることはできません。

'厳密な使用';
引数++;
var obj = { p(引数) を設定します { } };
try { } catch (引数) { }
関数の引数() { }
var f = new Function('arguments', "'use strict'; return 17;");

上記の実行ではエラーが報告されます。

さらに、通常モードでは、argumentsは名前付きパラメータにバインドされ、arguments[0]とargは同期して変更され、どちらも最初のパラメータを示します。

ただし、厳密モードの場合、引数は渡される実際のパラメータを表します。

例を見てみましょう:

関数 f(a) {
    a = 42;
    [a, 引数[0]]を返します。
}
var ペア = f(17);
console.log(ペア[0]); // 42
console.log(ペア[1]); // 42

上記の例では、arguments[0]は名前付きパラメータaにバインドされています。fに渡される値に関係なく、arguments[0]の最終値は42になります。

厳密モードに切り替える場合:

関数 f(a) {
    '厳密な使用';
    a = 42;
    [a, 引数[0]]を返します。
}
var ペア = f(17);
console.log(ペア[0]); // 42
コンソール.log(ペア[1]); // 17

このモードでは、arguments[0]は渡された実際のパラメータを受け取り、結果17が返されます。

厳密モードでは、arguments.callee は無効になります。一般的に、arguments.callee は現在実行されている関数を指しており、これにより仮想マシンがインライン化を最適化できなくなるため、Strict モードでは禁止されています。

JavaScript をより安全にする

通常モードでは、関数 f() 内で this を呼び出すと、これはグローバル オブジェクトを参照します。厳密モードでは、この値は未定義です。

call または apply を通じて呼び出す場合、プリミティブ値 (基本型) が渡されると、通常モードでは、自動的にボックス クラス (Boolean、Number などのプリミティブ型に対応するオブジェクト型) を指します。 undefined または null が渡された場合、これはグローバル オブジェクトを参照します。

厳密モードでは、これは渡された値を参照し、変換や変形は行われません。

以下の値はすべて真です。

'厳密な使用';
関数 fun() { これを返す; }
コンソールで assert(fun() === undefined);
コンソールでアサートします(fun.call(2) === 2);
コンソールでアサートします(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
コンソールでアサートします(fun.bind(true)() === true);

なぜ安全なのでしょうか?つまり、厳密モードでは、これを使用してウィンドウ オブジェクトを指すことはできないため、プログラムのセキュリティが確保されます。

さらに、通常モードでは、fun.caller または fun.arguments を介して関数の呼び出し元とパラメータを取得できますが、一部のプライベート プロパティまたは安全でない変数にアクセスし、セキュリティ上の問題が発生する可能性があります。

厳密モードでは、fun.caller または fun.arguments は禁止されます。

関数制限() {
  '厳密な使用';
  limited.caller; // TypeError をスローします
  limited.arguments; // TypeError をスローします
}
関数 privilegedInvoker() {
  制限付き() を返します。
}
特権呼び出し();

予約キーワードと関数の位置

JS 標準の今後の開発を確実にするために、厳密モードではキーワードを変数名として使用することはできません。これらのキーワードには、implements、interface、let、package、private、protected、public、static、yield が含まれます。

関数パッケージ(保護) { // !!!
  '厳密な使用';
  var を実装します; // !!!

  インターフェース: // !!!
  (真)の間{
    インターフェースを中断します。//!!!
  }

  関数 private() { } // !!!
}
function fun(static) { 'use strict'; } // !!!

関数に関しては、通常モードでは関数はどこにでも定義できますが、厳密モードでは関数はスクリプトの最上位レベルまたは関数内でのみ定義できます。

'厳密な使用';
(真)の場合{
  関数 f() { } // !!! 構文エラー
  関数f();
}

(var i = 0; i < 5; i++) の場合 {
  関数 f2() { } // !!! 構文エラー
  f2();
}

function baz() { // コーシャ
  function eit() { } // これもコーシャ
}

要約する

厳密モードは、その後の JS の開発と既存のプログラミング モデルの標準化において非常に重要な役割を果たしてきました。ただし、ブラウザ側で使用する場合は、ブラウザの互換性に注意し、厳密なテストを行う必要があります。

上記はJavaScriptのStrictモードの詳細な説明です。JavaScriptのStrictモードの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • JavaScript strict モード (use strict) の使用例の分析
  • JavaScript で Strict モードを使用する
  • nodejs Assert における equal()、strictEqual()、deepEqual()、strictDeepEqual() の比較
  • Javascript strictモードの使用 strict の詳細な説明
  • JavaScript の Strict モード (Strict Mode) の詳細な理解
  • JavascriptのStrictモードの詳細な紹介
  • JavaScript の strict モードと with キーワードの紹介

<<:  MySQLカスタム関数の簡単な使用例

>>:  MySQL max_allowed_pa​​cket 設定

推薦する

この構成ファイルの排他ロックに失敗したという VMware 仮想マシンのプロンプトの解決方法

VMware が異常シャットダウンした後、再起動すると「この構成ファイルを排他的にロックできませんで...

VSCode 構成 Git メソッドの手順

Git は vscode に統合されており、git コマンドをいくつか記述しなくても、クリックするだ...

MySQL InnoDB 監視 (システム層、データベース層)

MySQL InnoDB 監視 (システム層、データベース層) MySQL の監視に関しては、My...

Linux で MySQL のルート パスワードを変更する方法

序文このサービスは数か月前からMySQLに導入されています。私の仕事は基本的にターミナルで行われるた...

テキストエリアをレイアウトしたときにテキストが左下にあり、サイズを変更できない問題の解決策

2つの小さな問題ですが、長い間私を悩ませていました。最初の質問テキストエリアの左側のテキストは常にテ...

MySQL と Golan 間の従来の分散トランザクションのための 7 つのソリューション

目次1. 基本理論1.1 取引1.2 分散トランザクション2. 分散トランザクションソリューション2...

HTML のフォームフォームのメソッド属性の紹介

1 メソッドは、データをサーバーに送信する方法を指定するプロパティです。 2 post と get ...

MySQL で最大接続数を設定するためのヒントのまとめ

方法1: コマンドラインの変更次の図に示すように、MySQL コンソールを開いて「set GLOBA...

デザイン理論: テキストの読みやすさと可読性

<br />少し前に、ビジネス上の必要性から、ラップトップに Souba をインストール...

新しいユーザーを作成し、MySQLに権限を付与する最も簡単な方法

ユーザーを作成します: 'oukele' によって識別されるユーザー 'ou...

スケルトンスクリーン効果を実現する CSS

ネットワーク データを読み込むときは、ユーザー エクスペリエンスを向上させるために、通常は円形の読み...

Vueでeslintを使用する方法の詳細な説明

目次1. 説明2. 関連する依存パッケージをダウンロードする3. 設定ファイル .eslintrc....

dockerを使用してTomcatをデプロイし、Skywalkingに接続する

目次1. 概要2. dockerを使用してTomcatをデプロイし、Skywalkingに接続する要...

MySQL binlog_ignore_dbパラメータの具体的な使用法

序文:前の記事を読んだ後、binlog はデータベースで実行されたすべての DDL および DML ...

vue3でDOMをマウントするためのプラグインを書く際の問題について

vue2と比較して、vue3にはアプリの概念が追加され、vue3プロジェクトの作成も // メイン....