Debug veloce con ECMAScript Strict Mode

di: Rajasekharan Vengalil     22 Novembre 2011

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.

Guide JavaScript

Guida Node.js

Il framework che permette di per usare V8, l'interprete JavaScript...

Canvas, guida ai framework

Canvas, tra gli elementi di HTML5 è forse quello di maggior impatto....

Guida jQuery UI

Creare siti ricchi e dinamici con jQuery UI, il progetto ufficiale...

Altre guide

Newsletter @JavaScript

Ogni martedì, direttamente nella tua e-mail: guide, articoli, script, novità e approfondimenti tecnici su JavaScript.

Iscriviti alla newsletter

Altre newsletter

Corsi in aula

Corso Webmaster base

18 Giugno 2012 a Milano
Disponibilità: 6 Posti

Corso Google AdWords Base

25 Giugno 2012 a Milano
Disponibilità: 7 Posti

Corso JQuery e Ajax per Webmaster

03 Luglio 2012 a Milano
Disponibilità: 7 Posti

Corso Google AdWords Base

05 Giugno 2012 a Roma
Disponibilità: 7 Posti

Corso Webmaster base

11 Giugno 2012 a Roma
Disponibilità: 7 Posti