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

推薦する

nginx の 2 つのモジュールの proxy_pass の違い

1. 1.ngx_stream_proxy_moduleモジュールのproxy_passディレクティ...

無視されたDOCTYPE記述の分析

doctype もその 1 つです。 <!DOCTYPE HTML PUBLIC "...

RHEL8 /CentOS8 でマルチノード Elastic Stack クラスターを構築する方法

一般的に ELK スタックとして知られる Elastic スタックは、Elasticsearch、L...

MySQLにおけるACIDトランザクションの実装原理の詳細な説明

導入いつものように、シーンから始めましょう〜インタビュアー:「トランザクションの4つの特性をご存知で...

JSONオブジェクトのキーを置き換える最良の方法

JSON (JavaScript Object Notation、JS Object Notatio...

Ajax の JavaScript ソリューションにおける parsererror エラー ケースの詳細な説明

ajax の parsererror エラー (バックグラウンドからフロントエンドに送信される js...

MYSQLは、ショッピングカートに追加する際に重複追加を防ぐためのサンプルコードを実装します。

序文最近、仕事の都合で、APP ショッピングカートの注文支払いに取り組んでいました。テスト中にバグが...

CSS を使用して同じ親タグの左側と右側に 2 つのボタンを配置する方法

この記事では、主に同じ親タグの左側と右側にある 2 つのボタンの CSS レイアウト方法を紹介し、皆...

Linuxオンラインソフトウェアgccをオンラインでインストールする方法

Linux オンラインインストール関連コマンド: yum install: すべてインストールyum...

WiFi 開発 | WiFi ワイヤレス テクノロジーの紹介

目次WiFiワイヤレステクノロジーの紹介1. WiFiテクノロジーの概要2. ESP8266の紹介W...

Spring jdbc のデータベース操作オブジェクト モデルの詳細な例

Spring jdbc のデータベース操作オブジェクト モデルの詳細な例Spring Jdbc デー...

フォーム要素の垂直方向の中央揃えに最適なソリューション

コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC "...

Nginx+ModSecurity セキュリティモジュールの導入

目次1. ダウンロード2. 展開1.Nginxのデプロイメント2. ModSecurityの展開3....

SQL効率を分析する方法を説明する

Explain コマンドは、データベースのパフォーマンス問題を解決するために最初に推奨されるコマンド...

Ubuntu 18.04 に Nvidia グラフィック カード ドライバーをインストールするチュートリアル (画像とテキスト付き)

0. 事前準備BIOS でセキュア ブートを無効にします。無効にしないと、サードパーティ ソースを...