La Strict mode in JavaScript

La strict mode consente di introdurre in JavaScript una serie di limitazioni per ottimizzare il codice ed eliminare dei possibili errori come per il contenuto del riferimento this

La Strict mode, introdotta a partire da ECMAScript 5, consente di utilizzare una variante limitata di JavaScript. Non si tratta di un insieme di istruzioni, ma si tratta principalmente di una serie di regole semantiche per la scrittura del codice. Codice in strict code e codice non in strict mode possono coesistere (retro compatibilità) anche se le fonti di errori possono essere tante.

I vantaggi di usare la strict mode sono:

  • Elimina una serie di errori silenti lanciando delle eccezioni;
  • Ottimizza una serie di processi che in genere fanno degradare le performance dell’interprete JavaScript;
  • Vieta l’utilizzo di alcune sintassi che potrebbero essere utilizzate nelle future versioni di JavaScript;
  • Setta in maniera diversa il contesto (vedi Il riferimento this e come invocare le funzioni in JavaScript).

Per utilizzare la strict mode bisogna scrivere l’istruzione “use strict”; prima di ogni blocco in cui lo vogliamo utilizzare. Ad esempio:

    "use strict";
    var myName = "Datrevo";

Nell’esempio appena mostrato la strict mode viene applicata all’intero script. E’ possibile utilizzare la strict mode solo alle funzioni scrivendola all’inizio del corpo della funzione:

    // No strict mode
    function myFunction(){
        "use strict";
        // Strict mode
    }
    // No strict mode

La strict mode si applica solo all’interno script o alle funzioni, non si applica all’intero statement racchiuso tra le parentesi graffe {}. Di conseguenza il seguente codice non genererà errori:

    if(true) {
        "use strict";
        myVar = 1;
    }

La strict mode mette in risalto un gran numero di possibili errori che i programmatori ignorano

Le regole sintattiche e il comportamento a runtime degli script introdotti dalla strict mode sono molte. In particolare molte regole semantiche che potrebbero generare strani comportamenti durante l’esecuzione dello script sono state vietate e rese degli errori.

Ecco una lista di regole con la strict mode:

  • Non è possibile definire per sbaglio variabili globali. Ogni dichiarazione di variabile deve essere preceduta da var (senza var si dichiara una variabile globale);
        "use strict";
        myVar = 1; // => Uncaught ReferenceError: myVar is not defined

  • L’assegnamento a variabili non modificabili viene tramutato in errore. Ad esempio non è possibile modificare il valore della variabile NaN, ma eseguendo questo codice non verrà mostrato nessun errore:

        console.log(NaN); // => NaN
        NaN = 1;
        console.log(NaN); // => NaN

    Utilizzando la strict mode verrà lanciato un errore indicandoci che si tratta di una variabile di sola lettura.

        "use strict";
        NaN = 1; // => Uncaught TypeError: Cannot assign to read only property 'NaN'

  • Lancia un errore se si cerca di eliminare proprietà non cancellabili. Ad esempio scrivendo delete NaN; non avremo errori, mentre usando la strict mode:

        "use strict";
        delete NaN; // => Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

    Non è possibile cancellare variabili o oggetti:

        "use strict";
        var myVar = 1;

        delete myVar; // => SyntaxError: Delete of an unqualified identifier in strict mode.

    E non è possibile cancellare funzioni:

        "use strict";
        function myFunction(a, b) {};

        delete myFunction; // => SyntaxError: Delete of an unqualified identifier in strict mode.

  • Prima di Gecko 34 non era consentito duplicare i campi di un oggetto:

        "use strict"
        var myPerson = {
            name: "Datrevo",
            name: "Datrevo2" // <= Error
        };


    Da ECMAScript 2015 è possibile definire lo stesso campo di un oggetto più volte (l’ultima assegnazione nasconde le precedenti).

  • Non è possibile definire lo stesso parametro tra gli argomenti di una funzione:

        function myFunction(a, a, c) { // <= SyntaxError: Duplicate parameter name not allowed in this context
            "use strict";
            // ...
        };


    Non avremo errori senza lo strict mode e il valore di a corrisponde all’ultima assegnazione, quindi:

        function myFunction(a, a, c) { // <= a = 2, c = 3
            // ...
        };
        myFunction(1,2,3);

  • Non è possibile definire numeri in base otto. A partire da ECMAScript 5 si è deciso di proibire l’utilizzo dei numeri ottali in quanto essendo sono preceduti da uno zero (ad es. 010) potrebbero causare non pochi problemi ai sviluppatori meno esperti che potrebbero scrivere lo zero prima di un numero pensando che non faccia differenza.

        "use strict";
        var myVar = 011; // <= SyntaxError: Octal literals are not allowed in strict mode.

  • È vietato assegnare valori ai tipi primitivi:

        "use strict";

        false.newField = ""; // <= TypeError: Cannot create property 'newField' on boolean 'false'     (11).newField = "Datrevo"; // <= TypeError: Cannot create property 'newField' on number '11'     "MyString".siteName = "Datrevo"; // <= TypeError: Cannot create property 'siteName' on string     'MyString'

La Strict mode semplifica l’uso delle variabili con la strict mode

La Strict mode consente di semplificare la mappatura delle variabili dando la possibilità ai compilatori di ottimizzare il codice. Molti compilatori mappano i nomi delle variabili con il nome delle stesse, di conseguenza in alcuni casi è impossibile risalire a quale variabile si sta facendo riferimento.

La strict mode proibisce l’utilizzo di width in quanto qualsiasi nome utilizzato al suo interno genera confusione se si sta facendo riferimento ad una variabile esterna o ad una proprietà dell’oggetto:

    "use strict";
    var myVar = 1;

    with (myObject) { // <= SyntaxError: Strict mode code may not include a with statement
        console.log(myVar); // Si sta facendo riferimento a myVar o myObject.myVar?

    }


Nell’esempio la variabile myVar non può essere ottimizzata in quanto non si può conoscere a priori a quale myVar si sta facendo rifermento finché non si è a runtime.

È vietato introdurre nuove variabili con eval. Il motivo di tale limitazione è dovuto al fatto che se ci troviamo una funzione, qualsiasi chiamata a eval potrebbe introdurre delle nuove variabili nella nuova funzione o a livello globale. Ciò comporta che per qualsiasi nome che non i riferisce gli argomenti della funzione a variabili locali, deve essere mappato a runtime. Nello strict mode la funzione eval creerà variabili solo per il codice eseguito in modo da non influenzare i riferimenti alle variabili esterne o locali.

    "use strict";
    eval("var myVar = 2");

    console.log(myVar); // => ReferenceError: myVar is not defined

Semplificato l’utilizo di eval e arguments

L’utilizzo della strict mode vieta l’utilizzo inappropriato delle parole arguments e eval trattandole come keyword:

    "use strict";

    var eval; // => SyntaxError: Unexpected eval or arguments in strict mode

    eval = 10; // => SyntaxError: Unexpected eval or arguments in strict mode

    arguments++; // => SyntaxError: Unexpected eval or arguments in strict mode

    var myObject = {

        var myFunction = function (arguments) { // => SyntaxError: Unexpected identifier
        }

    };

    function eval() { // => SyntaxError: Unexpected eval or arguments in strict mode
    };

Vietando l’utilizzo di arguments, è possibile accedere al valore iniziale dei parametri passati in una funzione. Normalmente avremo che:

    function myFunction(a) {
        a = 1;
        return [a, arguments[0]];
    }
    var array = myFunction(2);
    console.log(array[0]); // => 1
    console.log(array[1]); // => 1

Con la strict mode in arguments[0] è presente ancora il valore originale del parametro passato in ingresso a myFunction():

    function myFunction(a) {
        "use strict";
        a = 1;
        return [a, arguments[0]];
    }
    var array = myFunction(2);
    console.log(array[0]); // => 1
    console.log(array[1]); // => 2

Ciò è dovuto al fatto che nell’esecuzione di un codice normale, in una funzione il primo argomento è arg, andando a settare arg viene settato anche arguments[0] e viceversa (a meno che non ci siano parametri o arguments[0] è cancellato).

    function myFunction(a) {
        arguments[0] = 3;
        return [a, arguments[0]];
    }

    var array = myFunction(2);

    console.log(array[0]); // => 3
    console.log(array[1]); // => 3

    function myFunction(a) {
        // use strict;
        arguments[0] = 3;
        return [a, arguments[0]];

    }

    var array = myFunction(2);

    console.log(array[0]); // => 3
    console.log(array[1]); // => 2

Infine non è stato vietato l’utilizzo di arguments.callee in quanto poco affidabile. In una funzione senza strict mode arguments.callee restituisce la funzione stessa, poco affidabile e nasconde possibili ottimizzazioni.

Senza la strict mode:

    function myFunction() {

        console.log(arguments.callee); // => function myFunction() { console.log(arguments.callee); }

    }
    var array = myFunction();

Con la strict mode:

    "use strict";
    var myFunction = function() { return arguments.callee; };

    myFunction(); // TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    function myFunction2() {

        // => TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    }
    var array = myFunction2();

Scrivere codice JavaScript più sicuro con la strict mode

Utilizzare la strict mode consente di scrivere facilmente codice JavaScript “sicuro“. Una delle funzionalità più importanti della strict mode è il valore che assume this all’interno delle funzioni in modo da poterne limitare l’accesso a dati esterni. Per approfondire il valore che assumerà this con le strict mode vi rimando all’articolo su this.

Viene inoltre disabilitato l’accesso ad una serie di funzioni che possono accede a funzioni “privilegiate” che potrebbero risultare insicure. Ad esempio, dal nome di una funzione non è più possibile accedere al campo “caller” e “arguments” (rispettivamente il primo corrisponde alla funzione più recente che l’ha invocata, il secondo sono gli argomenti con cui è stata invocata la funzione).

    function myFunction() {
        "use strict";

        myFunction.caller; // => TypeError: 'caller' and 'arguments' are restricted

        myFunction.arguments; // => function properties and cannot be accessed in this context.

    }
    myFunction();

Infine, non è più possibile accedere al campo caller in quanto in alcune vecchie versioni di ECMAScript, myFunction.caller contiene le proprietà con gli alias delle variabili nella funzione. Ciò consente di non poter più nascondere valori privilegiati attraverso le funzioni astratte. Di conseguenza dato che myFunction.caller non cancellabile, verrà lanciato un errore ogni volta che si tenta di modificarlo e di recuperare il suo contenuto.

    function myFunction (a, b) {
        var myNewVar = 3;
        return arguments.caller;
    };
    console.log(myFunction(1, 2));

    "use strict";
    function myFunction (a, b) {
        var myNewVar = 3;
        "use strict";

        return arguments.caller; // => TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

    };
    console.log(myFunction(1, 2));

Pubblicato in Front-end, JavaScript Taggato con: , ,

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*