Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Debug veloce con ECMAScript Strict Mode

Sfruttare la modalità "Strict" di ECMAScript per far emergere problemi nel codice
Sfruttare la modalità "Strict" di ECMAScript per far emergere problemi nel codice
Link copiato negli appunti

Questa è la traduzione dell'articolo Debug your site faster with ECMAScript Strict Mode di Rajasekharan Vengalil pubblicato originariamente su msdn. La traduzione viene qui presentata con il consenso dell'editore e dell'autore.

ECMAScript, ratificato come punto di riferimento per i linguaggi di scripting dall'Ecma International, si può considerare lo standard di riferimento per quello che il mondo conosce come JavaScript.

Per essere precisi, JavaScript ed ECMAScript non sono identici. JavaScript è un dialetto di ECMAScript, ma le differenze sono per lo più trascurabili e in gran parte esistono per motivi storici di compatibilità. ECMAScript 5, l'ultima versione disponibile, (d'ora in poi denominato ES5) mette sul tavolo una serie di caratteristiche molto interessanti. La maggior parte di queste nuove funzionalità sono progettate per portare maggiore disciplina la programmazione al linguaggio.

In questo articolo ci concentriamo sulla modalità Strict, una delle caratteristiche che affronta direttamente alcune delle parti più note del linguaggio. Essenzialmente, si tratta di una modalità completamente nuova per JavaScript che fa sì che il motore di esecuzione esegua codice con una semantica leggermente diversa.

Cos'è la modalità "Strict"?

La modalità Strict di Javascript forza il runtime engine ad interpretare ed eseguire il codice Javascript con una semantica diversa da quella che vedremmo in modalità normale ("unrestricted"). Il codice che gira in "strict mode" sottostà ad alcune caratteristiche:

  1. esclude alcune caratteristiche sintattiche e semantiche: non possiamo fare cose che altrimenti ci sarebbero permesse;
  2. modifica la semantica di alcune funzionalità: lo stesso codice gira diversamente in strict mode rispetto alla modalità normale;
  3. è meno tollerante in alcuni scenari: casi che sarebbero altrimenti ignorati o trattati con un comportamento di default, con questa modalità sollevano eccezioni.
  4. Si applica a specifiche unità di codice: non è possibile applicare la modalità Strict a tutti i file .js in un colpo solo (a meno di concatenarli tutti insieme).

L'idea alla base della modalità Strict è quella di introdurre una sorta di disciplina, forzata a runtime, da cotrappore ad alcune pratiche di sviluppo con Javascript. Questo può essere visto come un modo per introdurre un maggiore rigore nell'eccessivo dinamismo che caratterizza JavaScript.

Quando si contrassegna un segmento di codice come "strict", molte delle parti più spinose di JavaScript vengono forzate dal motore stesso, invece di richiedere l'intervento del programmatore.
Per esempio, riuscireste ad individuare il bug presente nel seguente frammento? Con la modalità Strict, lo fa direttamente il compilatore.

function findProduct(numbers) {
  var product = 0,
      len = numbers.length;
  for(var i = 0; i < len; ++i) {
    prodct = product * numbers[i];
  }
  return product;
}

Supporto del Browser

Praticamente tutti i browser moderni supportano la modalità Strict nei propri motori JavaScript, compresi Internet Explorer, Chrome, Firefox, Safari e Opera. In Internet Explorer (IE), la modalità Strict è disponibile a partire dalla versione 10, la cui anteprima è disponibile su IE Test Drive. Tutti gli esempi presenti in questo articolo sono stati testati sulla piattaforma IE10 utilizzando la JavaScript eval console, mentre solo alcuni di essi sono stati testati anche su Chrome 14 e su Firefox 7 versione Beta.

Il contesto della modalità Strict

Far girare un pezzo di codice JavaScript in modalità Strict è veramente semplice. Ecco un esempio:

"use strict";
alert("Look ma! Strict Mode!");

Il bello è che questo codice è perfettamente valido anche in ECMAScript 3 (ES3 è l'edizione precedente di ECMAScript). Un motore ES3 JavaScript ignora semplicemente la linea di noop e procede con l'esecuzione del resto dello script. In effetti questa sorta di compatibilità sintattica reatroattiva con ES3 era un obiettivo chiave del progetto di ES5. Una parte sorprendentemente ampia della specifica ES5 può essere implementata completamente in ES3 JavaScript. Tuttavia la modalità Strict è un esempio di funzione ES5 che forse non può essere implementata in maniera pura in ES3 JavaScript, ma necessita di un compilatore che la supporti.

Diamo uno sguardo alle tipologie di codice JavaScript che può essere scritto per girare in Strict Mode:

  1. Global code
    Si tratta semplicemente del codice che inseriamo all'interno di un tag <script>. Per esempio:

    <script >
    "use strict";
    // global Strict Mode code here
    </script >

    Notiamo che con HTML5 non è più necessario aggiungere l'attributo type nel tag <script>.

  2. Eval code
    È il codice che passiamo alla funzione Eval che ha come prefisso la direttiva Strict Mode (use strict):

    eval("'use strict'; // strict code here");

    Oppure che è invocato dal codice in modalità strict:

    "use strict";
    eval("// strict code here");
  3. Function code
    Funzioni che hanno la direttiva Strict Mode come prefisso apposto prima del resto del codice (mettere la direttiva in qualsiasi altro punto non conta):

    function foo() {
     "use strict";
     // strict code here
    }

    Le funzioni dichiarate nel codice in modalità Strict ereditano la "strictness":

    function foo() {
        "use strict";
        var bar = function () {
            // strict code here
        };
        bar();
    }

    Nota: Quest'ultimo caso è particolarmente rilevante quando si definiscono callback per gli event handler.

    È altresì importante osservare che la modalità strict non si propaga nello stack di chiamate. Ecco un esempio:

    function foo() {
        // not Strict Mode even though
        // foo is being invoked from a
        // "strict" function
    }
    function bar() {
        "use strict";
        foo();
    }
    bar();

Le restrizioni della modalità Strict

Ma quali sono esattamente le restrizioni e la semantica che si applicano in modalità strict? Rivediamo le principali restrizioni:

1. Gli identificatori devono essere dichiarati prima di poter essere assegnati

Solo per questo aspetto dovrebbe valere la pena di utilizzare la modalità Strict. Le variabili non dichiarate non vengono aggiunte automaticamente come proprietà globali dell'oggetto.

"use strict";
// ReferenceError: Variable undefined in Strict Mode
foo = 10;

Proprio per di questa restrizione, il frammento di codice che avevamo esaminato nel paragrafo "Cos'è la modalità Strict?" non gira e solleva un "ReferenceError", a causa del refuso sul nome della variabile "product" nell'assegnamento dentro il ciclo "for".

function findProduct(numbers) {
    "use strict";
    var product = 0,
        len = numbers.length;
    for(var i = 0; i < len; ++i) {
        // ReferenceError: Variable undefined in Strict Mode
        prodct = product * numbers[i];
    }
    return product;
}
print(findProduct([1, 2, 3, 4, 5]));

2. Nessun contesto automatico per le chiamate a funzioni context-less

Nelle funzioni chiamate senza impostare un contesto esplicito la parola chiave "this" non viene associata automaticamente al "global object". Si consideri il seguente frammento di codice:

function foo() {
  // prints “true”
  print(this === window);
}
foo();

Qui "foo" è invocato senza impostare un esplicito contesto per l'oggetto, cioè non abbiamo una chiamata del tipo:

foo.call({foo: "bar"});

Nella modalità unrestricted questo fa sì che il contesto venga automaticamente inizializzato con l'oggetto "globale", che nei browser è rappresentato dall'oggetto "window". Poiché il frammento di codice è stato eseguito in modalità unrestricted, l'espressione "this === window" restituisce true. Se modifichiamo la funzione in questo modo, però, vediamo che "this" non è più uguale a "window":

function foo() {
  "use strict";
  // prints “false”
  print(this === window);
}
foo();

3. Le parole chiave riservate non possono essere usate come nomi di identificatori

Nomi di variabili e funzioni come eval, arguments, implements, let, private, public, yield, interface, package, protected, e static generano errori.

"use strict";
var yield; // SyntaxError: Expected identifier

4. Violazioni alle proprietà di configurazione di ES5 generano errori

Violazioni della configurazione, specificata nelle proprietà del descrittore per ES5, generano errori se lanciate in modalità Strict, invece di essere silenziosamente ignorate. Ecco alcuni esempi:

  1. Scrivere una proprietà non editabile:

    "use strict";
    var person = Object.create({}, {
        name: {
            value: "foo",
    writable: false,
            configurable: true,
            enumerable: true
        }
    });
    // TypeError: Assignment to read only properties not allowed in
    // Strict Mode
    person.name = "bar";

    Nella riga writable: false, impostare il descrittore "writable" a "false" fa diventare la proprietà "name" dell'oggetto "person" di tipo read-only. I tentativi di assegnamento su questa proprietà sarebbero silenziosamente ignorati nella modalità unrestricted, ma causeranno un "TypeError" in Strict Mode.

  2. Cambiare la configurazione di una proprietà non configurabile

    "use strict";
    var person = Object.create({}, {
        name: {
            value: "foo",
            writable: false,
    configurable: false,
            enumerable: true
        }
    });
    // TypeError: Cannot redefine non-configurable property 'name'
    Object.defineProperty(person, "name", {
        value: "bar",
        writable: true,
        configurable: true,
        enumerable: true
    });

    Qui abbiamo cercato di modificare il descrittore di proprietà di un oggetto non configurabile. Ancora una volta, un errore che sarebbe passato inosservato nella modalità unrestricted genera un "TypeError" nella modalità strict.

5. Scrivere una proprietà di sola lettura

La scrittura di una proprietà che non ha un metoto "setter" definito genera un errore nello Strict Mode che nella modalità unrestricted sarebbe stato ignorato silenziosamente:

"use strict";
var person = Object.create({}, {
    name: {
        get: function() {
            return "foo";
        },
        configurable: false,
        enumerable: true
    }
});
// TypeError
person.name = "bar";

Qui, "name" è una proprietà che non ha un metodo "setter" definito. I tentativi di assegnare un valore a questa proprietà causa un errore nella modalità Strict pur essendo tranquillamente ignorato in quella unrestricted.

6. Non è possibile estendere oggetti non-extensible

Estendere un oggetto non-extensible genera un errore nello Strict Mode che altrimenti verrebbe semplicemente ignorato:

"use strict";
var person = {
    name: "foo"
};
Object.preventExtensions(person);
// TypeError: Cannot create property for a non-extensible object
person.age = 10;

7. Altre restrizioni

Ci sono altre piccole restrizioni per la modalità Strict che vengono utilizzate meno frequentemente:

  1. Le costanti numeriche non vengono interpretate in base ottale mettendo uno zero iniziale.
  2. Le istanze di variabile e/o funzioni nel codice "eval" della modalità Strict occorrono in un ambiente che è locale al codice "eval" e non nel contesto del codice chiamante. Questo significa che il codice "eval" non può introdurre nuovi identificatori nel chiamare l'esecuzione di un context e/o scope.
  3. Gli "arguments" sono immutabili. Non si può estendere arbitrariamente l'oggetto "arguments" girando una proprietà su di esso. Ora, potremmo chiederci perché qualcuno dovrebbe anche voler fare questo, ma deve essere stato fatto abbastanza spesso perché Ecma arrivasse a specificare che non si può fare in modalità Strict.
  4. "Arguments.callee" e "arguments.caller" non sono disponibili nelle funzioni strict.
  5. Duplicare le definizioni delle proprietà su un oggetto non è consentito in Strict Mode. Il seguente frammento, ad esempio, produce un errore in in Strict Mode:

    "use strict";
    var o = Object.create({}, {
        name: {
            value: "foo"
        },
        name: {
            value: "bar"
        }
    });

    Questo codice genera un "SyntaxError" con il messaggio "Multiple definitions of a property not allowed in Strict Mode" ("definizioni multiple di una proprietà non ammesse in modalità strict"). Nella modalità unrestrict, "o.name" avrebbe il valore "bar".

  6. La chiamata "delete" su una proprietà ES5 che ha la sua proprietà "configurable" impostato su "false" si traduce in un errore in Strict Mode. Questa è una variante alla restrizione presentata al punto 4.
  7. La statement JavaScript "with" non è consentito nel codice Strict Mode.
  8. Non è consentito creare funzioni con i nomi di parametro duplicati in Strict Mode.

Suggerimenti e best practices

Ecco alcune cose che si dovrebbero tenere in considerazione mentre si scrive un codice che utilizza la modalità strict:

  1. Poiché la modalità Strict è un fenomeno abbastanza recente, ci sono molte probabilità che alcuni visitatori delle proprie web app abbiano un motore JS che non capisce la modalità Strict. Ciò significa che tutto il codice verrà eseguito in modo unrestricted, che abbiate usato o meno la modalità strict. Quindi è sempre importante testare il proprio codice anceh in modalità unrestricted e assicurarsi che tutto funzioni correttamente.
  2. Ora, anche se c'è un gran numero di utenti finali con browser che non supportano la modalità Strict, continua ancora ad aver senso utilizzare la modalità Strict nel proprio ambiente di sviluppo perché la modalità Strict consente di rafforzare le best practices di JavaScript.
  3. Attivare la modalità Strict piccoli incrementi invece di una soluzione one-shot. Se avete un file JS con 3000 linee di codice, per esempio, probabilmente non è intelligente aggiungere semplicemente la direttiva "use strict"; nella parte superiore del file. Le differenze semantiche tra le due modalità potrebbero potenzialmente causare piccoli bug imprevisti. Meglio farlo girare in blocchi più piccoli a livello di funzioni.

Link utili

Alcune risorse utili per sperimentare ed approfondire le tematiche sulla modalità Strict sono reperibili ai seguenti indirizzi:

Note sull'autore

Rajasekharan Vengalil
Rajasekharan Vengalil ha sviluppato codice per oltre 9 anni e lavora come Developer Evangelist presso Microsoft. Ha lavorato su una vasta gamma di prodotti e tecnologie Microsoft che vanno dalla programmazione di VC + +, MFC e Win32 per il web, JavaScript e. NET. Il suo focus attuale è sui progressi nello sviluppo web, HTML5 e la creazione di applicazioni internet. Leggi il suo Nerdworks Blogorama

Ti consigliamo anche