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 設定

推薦する

JavaScript におけるシリアル操作と並列操作

目次1. はじめに2. es5メソッド3. 非同期関数のシリアル実行4. 非同期関数の並列実行5. ...

MySQLトランザクションとMySQLログの詳細な説明

取引特性1. アトミック性: トランザクションの開始後、すべての操作が完了するか、まったく実行されな...

better-scrollプラグインのスライドできないバグについて(2021年プラグインで解決)

より良いスクロールの原則親コンテナーであるため、ラッパーの高さはコンテンツのサイズに応じて増加します...

Linux 環境変数の設定方法のまとめ (.bash_profile と .bashrc の違い)

Linux では、アプリケーションをダウンロードしてインストールすると、起動時にアプリケーション名...

Nginxでネットワーク分離を解決した実践記録を詳しく解説

必要最近、Node オンライン サービスを移行する必要があったため、2 つの新しいオンライン サーバ...

MySQL 5.7 でブロックポジショニング DDL の問題を解決する

前回の記事「MySQL テーブル構造の変更、メタデータ ロックを知っておく必要があります」では、MD...

Vueはユーザーログインとトークン検証を実装します

フロントエンドとバックエンドを完全に分離する場合、Vue プロジェクトでトークン検証を実装する一般的...

MySQL データベース アカウントの作成、認証、データのエクスポートおよびインポート操作の例

この記事では、MySQL データベースでのアカウントの作成、認証、データのエクスポートおよびインポー...

CSS グリッドレイアウトを使用してレスポンシブな縦棒グラフを作成する方法

私はしばらくの間チャートをいじっていましたが、好奇心から、CSS を使用してチャートを作成するより良...

体験をデザインする: ボタンには何があるか

<br />最近、UCDChina は「インターフェース上のテキストに注意を払う」という...

CentOS 6 および 7 での MySQL 5.7 の詳細なインストール チュートリアル

開発には常にデータが必要です。サーバーとしての Linux では、テスト データを格納するためのデー...

ウェブページのメモリとCPU使用量を削減する方法

<br />Web ページによっては、サイズは大きくないように見えても開くのに非常に時間...

Spring Cloud での Docker デプロイメントに jib を使用する詳細な手順

ジブの紹介Jib は Google が開発した、Java アプリケーションの Docker および ...

MySQLの文字列インターセプト関連関数の概要

この記事では、MySQL の文字列インターセプト関連の機能を紹介します。具体的な内容は以下のとおりで...

Vue 開発プロジェクトで Font Awesome 5 を使用する方法

目次依存関係をインストールする構成使用1.アイコン検索ページに入る2. 使用したいアイコンの英語名を...