Javascript厳格モードの詳細

16774 ワード

一、概説
1、厳格なパターンとは何ですか.
通常モードの意外性に加えて、ES 5(2009年リリース)には「厳格モード」というモードが追加されました.このモードはjavascriptをより厳格な条件下で実行させます.
2、なぜ厳格なパターンを使うのですか.
  • javascript言語のいくつかの不合理で厳格でないところを解消し、奇妙な現象を減らす.
  • コード実行のいくつかの安全でない場所を除去し、コード実行の安全を保証する.
  • コンパイラの効率を高め、運行速度を高める.
  • は、将来の新しいバージョンのjavascriptの基礎を築きます.

  • 3、どのように厳格なモードを使いますか?(1)スクリプト全体の呼び出し:
    <script>
            "use strict";
    
    script>
    "use strict"をすべての実行可能コードの前に置くと、スクリプト全体が厳格モードで実行されます.
    この書き方は関数のマージに不利で、より良い方法です.
     <script>
           (function(){
               "use strict";
    
           })();
     script>

    (2)単一の関数について:
    function fn(){
    "use strict";
    
    }
    "use strict";をすべての実行可能コードの前に置くと、関数全体が「厳格モード」で実行されます.
    二、厳格モードと普通モードの違い:
    1、グローバル変数は宣言を表示する必要があります
    "use strict";
    a=1;
    console.log(a);//ReferenceError: a is not defined

    2、静的バインドjavasript言語には特徴があります.すなわち、動的バインドを許可します(一部のプロパティとメソッドはコンパイル時に決定されるのではなく、実行時に決定されます).厳格なモードは動的バインドに少し制限されています.場合によっては、静的バインドのみを許可する場合があります.(属性と方法がどのオブジェクトに帰属するかは、コンパイル段階で決定すべきである).利点:コンパイル効率の向上に有利であり、コードをより読みやすくし、意外なことが少なくなる.
    (1)with文の使用禁止
    "use strict";
    var obj={
        name:'lwf',
        age:21
    }
    with(obj){//SyntaxError: Strict mode code may not include a with statement
        var name1=name;
        var age1=age;
    }

    またwith文を使用するとパフォーマンスが低下し、デバッグコードが困難になるため、開発中はwithは推奨されません.
    (2)eval役割ドメインの作成
    通常モードでは、グローバル役割ドメインと関数役割ドメインの2つの役割ドメインがあり、evalの役割ドメインは、グローバル役割ドメインと関数役割ドメインに依存します.厳格モードではeval役割ドメインが増加します.eval内で生成された変数はevalでのみアクセスできます.通常モード:
    var a=1;
    var b=2;
    eval("console.log(a)");//1
    eval("var b=3;console.log(a)");//1
    eval("console.log(b)");//3

    厳格モード:
    "use strict";
    var a=1;
    var b=2;
    eval("console.log(a)");//1
    eval("var b=3;console.log(a)");//1
    eval("console.log(b)");//2

    3、安全対策の強化
    (1)thisキーがグローバル変数を指すことを禁止する
    function f1(){
        console.log(!this);//false,     ,this      
    }
    f1();
    function f2(){
        "use strict";
        console.log(!this);//true,     ,this  undefined,  !this true
    }
    f2();

    (2)関数内部で呼び出しスタックを巡回することを禁止する
    function f3(){
        console.log(f3.arguments);//{ '0': 1, '1': 2, '2': 3 }
    }
    f3(1,2,3);
    function f4(){
        "use strict";
        console.log(f4.arguments);//TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
    }
    f4(1,2,3);

    4、変数の削除禁止
    通常モードと厳格モードでは、変数の通常モードの削除は禁止されています.
    var x=4
    delete x;//         
    console.log(x);//4

    変数を削除:
    "use strict";
    var y=4;
    delete y;//SyntaxError: Delete of an unqualified identifier in strict mode.
    console.log(y);

    5、明示的なエラー(1)通常モードでは、1つのオブジェクトの読み取り専用属性に値を割り当て、エラーを報告せず、黙々と失敗するだけである.厳格モードでは、エラーを報告する.通常モード:
     var obj3={};
     Object.defineProperty(obj3,'name',{value:1,writable:false});
     obj3.name=2;
     console.log(obj3.name);//1,    

    厳格モード:
    "use strict";
    var obj4={};
    Object.defineProperty(obj4,'name',{value:1,writable:false});
    obj4.name=2;//TypeError: Cannot assign to read only property 'name' of object '#'
    console.log(obj4.name);

    (2)通常モードでは、getterメソッドで読み取った属性に値を付け、エラーを報告せず、黙って失敗するだけである.厳格モードでは、エラーを報告する
    var o={
        get v(){return 1}
    }
    console.log(o.v);//1
    o.v=2;
    console.log(o.v);//1
    "use strict";
    var o={
        get v(){return 1}
    }
    console.log(o.v);//1
    o.v=2;//TypeError: Cannot set property v of # which has only a getter
    console.log(o.v);

    (3)通常モードでは、拡張禁止の対象に属性を追加し、エラーを報告せず、黙々と失敗する.厳格モードでは、エラーを報告する
    var o={};
    Object.preventExtensions(o);
    o.v=1;
    console.log(o.v);//undefined
    "use strict";
    var o={};
    Object.preventExtensions(o);
    o.v=1;//TypeError: Cannot add property v, object is not extensible
    console.log(o.v);

    6、重複名エラー(1)関数に重複名がないパラメータ正常モードでは、関数に重複名パラメータがある場合はarguments[i]を使用して読み込むことができます.厳格モードでは、エラーが報告されます.
    function fn(a,a,b){
        console.log(arguments[0]);//1
        console.log(arguments[1]);//2
        return a;
    }
    console.log(fn(1,2,3));//2
    "use strict";
    function fn(a,a,b){//SyntaxError: Duplicate parameter name not allowed in this context
        console.log(arguments[0]);
        console.log(arguments[1]);
        return a;
    }
    console.log(fn(1,2,3));

    7、8進表記禁止
    var n=0100;
    console.log(n);//64
    "use strict";
    var n=0100;//SyntaxError: Octal literals are not allowed in strict mode.
    console.log(n);

    8、argumentsオブジェクトの制限(1)argumentsオブジェクトへの付与は許可されていない
    function fn1(){
    console.log(arguments++);//NaN
    }
    fn1(1,2);
    "use strict";
    function fn1(){
    console.log(arguments++);//SyntaxError: Unexpected eval or arguments in strict mode
    }
    fn1(1,2);
    "use strict";
    var obj = { set p(arguments) { } }; //     
    try { } catch (arguments) { } //     
    function arguments() { } //     
    var f = new Function("arguments", "'use strict'; return 17;"); //     

    (2)argumentsがパラメータの変化を追跡しない
    function fn1(a){
        a=2;
        console.log(arguments[0],a);//2,2
    }
    fn1(1);
     "use strict";
    function fn1(a){
        a=2;
        console.log(arguments[0],a);//1 2
    }
    fn1(1);

    (3)arguments.calleeの使用を禁止匿名関数で自身を呼び出すことができないことを意味する
    function fn1(){
       console.log(arguments.callee);//[Function:fn1]
    }
    fn1();
    "use strict";
    function fn1(){
       console.log(arguments.callee);//TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
    }
    fn1();

    9、関数宣言は、最上位厳格モードで、グローバル役割ドメインまたは関数役割ドメインの最上位宣言関数のみを許可する必要があります.関数以外のコードブロックで関数を宣言することはできません.
    if(true){
        function fn(){
            console.log(1);
        }
    }
    fn();
    "use strict";
    if(true){
        function fn(){
            console.log(1);
        }
    }
    fn();//ReferenceError: fn is not defined

    10、保留字厳格モードでは、implements、interface、let、package、private、protected、public、static、yieldが変数名として使用してエラーを報告します.
    function fn1(){
        var let=1;
        console.log(let);
    }
    fn1();//1
    "use strict";
    function fn1(){
        var let=1;//SyntaxError: Unexpected strict mode reserved word
        console.log(let);
    }
    fn1();

    また、ECMAscriptの第5版自体には、他の保留字(class,enum,export,extends,import,super)や、各ブラウザが独自に追加したconst保留字も変数名として使用できないことが規定されています.
    参考:チェン一峰のJavaScript厳格モードの詳細