[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Strict_mode [Back]  [Original]

Le mode strict - JavaScript | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

Le mode strict

Le mode strict de ECMAScript 5 permet de choisir une variante restrictive de JavaScript. Le mode strict n'est pas seulement un sous-ensemble de JavaScript : il possde intentionnellement des smantiques diffrentes du code normal. Les navigateurs ne supportant pas le mode strict excuteront le code d'une faon lgrement diffrente de ceux le supportant, il ne faut donc pas compter sur le mode strict pour viter des tests sur les navigateurs qui ne le supportent pas. Les codes en mode strict et en mode non-strict peuvent coexister, ce qui permet de rcrire les scripts en mode strict de faon incrmentale.

Le mode strict apporte quelques changements la smantique normale de JavaScript:

  1. Le mode strict limine quelques erreurs silencieuses de JavaScript en les changeant en erreurs explicites (une exception sera leve).
  2. Le mode strict corrige les erreurs qui font qu'autrement il est difficile pour les moteurs JavaScript d'effectuer des optimisations. Le code sera donc excut plus rapidement en mode strict, sans changer une seule ligne si cela n'est pas ncessaire.
  3. Le mode strict interdit les mot-cls susceptibles d'tre dfinis dans les futures versions de ECMAScript.

Voir la page Passer au mode strict pour plus de dtails quant la migration d'une base de code non-stricte vers une base de code compatible avec le mode strict.

Note : Le mode non strict (celui actif par dfaut) est parfois appel sloppy mode en anglais. Bien que ce ne soit pas la dnomination officielle, on la rencontre occasionnellement.

Dans cet article

Invoquer le mode strict

Le mode strict s'applique des scripts entiers ou des fonctions individuelles. Il ne peut s'appliquer des blocs d'instructions entours d'accolades {}; essayer de l'appliquer dans ces contextes ne fera rien. Les codes prsents dans eval(), Function, les attributs d'vnements et les chanes passes setTimeout, ou autres sont des scripts entiers, et invoquer le mode strict l'intrieur de ceux-ci fonctionnera comme prvu.

Le mode strict pour les scripts

Pour invoquer le mode strict pour un script entier, on ajoutera l'instruction exacte "use strict"; (ou 'use strict';) avant toutes les autres instructions.

js
// Script entier en mode strict
"use strict";
var v = "Allo ! Je suis en mode strict !";

Cette syntaxe possde un pige dans lequel est dj tomb un site web connu : il n'est pas possible de concatner du script en mode strict et du code en mode non-strict. En effet, si on concatne du code non-strict la suite d'un code strict, tout le code sera considr comme strict. De mme si on concatne du code strict la suite d'un code non-strict, le code entier aura l'air non-strict. Ainsi, on peut concatner entre eux des codes stricts sans aucun problme et de mme concatner uniquement des codes non-stricts sans problme. En revanche, lorsqu'on mlange les deux, cela pose un problme. Lors d'une phase de transition, il est donc recommand de n'activer le mode strict que fonction par fonction.

Il est aussi possible d'adopter une approche qui consiste englober le code du script dans une fonction et donner cette dernire le mode strict. Ce procd limine le problme de concatnation mais cela signifie aussi qu'on doit exporter chaque variable globale hors de la fonction principale nouvellement cre.

Le mode strict pour les fonctions

De mme, pour activer le mode strict pour une fonction, on placera l'instruction exacte "use strict"; (ou 'use strict';) dans le corps de la fonction avant toute autre dclaration.

js
function strict() {
  // Syntaxe en mode strict au niveau de la fonction
  "use strict";
  function nested() {
    return "Ho que oui, je le suis !";
  }
  return "All ! Je suis une fonction en mode strict ! " + nested();
}
function notStrict() {
  return "Je ne suis pas strict.";
}

Mode strict pour les modules

ECMAScript 2015 a vu apparatre les modules JavaScript. Le code de ces modules est automatiquement en mode strict et aucune instruction n'est ncessaire pour passer dans ce mode.

js
function maFonctionDeModule() {
  // tant dans un module, le code prsent
  // ici sera d'office en mode strict
}
export default maFonctionDeModule;

Diffrences du mode strict

Le mode strict modifie la fois la syntaxe et le comportement l'excution. Les changements se dclinent gnralement en trois catgories : ceux qui convertissent les fautes en erreurs (comme des erreurs de syntaxe ou les erreurs d'excution), ceux qui simplifient comment une variable pour un nom donn est traite, simplifiant eval() et arguments et ceux qui permettent d'crire plus simplement du code JavaScript prenne qui anticipe les volutions futures d'ECMAScript.

Convertir les fautes en erreurs

Le mode strict change quelques fautes prcdemment acceptes, en erreurs. JavaScript a t conu pour les dveloppeurs novices et, quelquefois, il ne cre pas d'erreur explicite pour certaines instructions qui devraient tre des erreurs. Parfois cela rgle un problme immdiatement, mais cela peut aussi crer d'autres erreurs, plus loin dans le code. Le mode strict traite ces fautes comme des erreurs afin qu'elles soient dcouvertes et rapidement traites.

Premirement, en mode strict, il est impossible de crer accidentellement des variables globales. En mode normal, ne pas dclarer une variable lors d'une affectation (oublier l'instruction var) cre une nouvelle proprit sur l'objet global et le code continue de fonctionner (mme si a peut tre une source de problmes par la suite). Les affectations qui pourraient accidentellement crer des variables globales lveront une erreur en mode strict:

js
"use strict";
variableMalDclare = 17; // lve une ReferenceError

Deuximement, le mode strict fait en sorte que les affectations qui choueraient silencieusement lveront aussi une exception. Par exemple, NaN est une variable globale en lecture seule. En mode normal, une affectation NaN ne fera rien ; le dveloppeur ne recevra aucun retour par rapport cette faute. En mode strict, affecter une valeur quelconque NaN lvera une exception. Toute affectation qui chouera silencieusement en mode non-strict (affectation une proprit en lecture seule, affectation une proprit sans mthode set, affectation une nouvelle proprit sur un objet non-extensible) lvera une exception en mode strict :

js
"use strict";

// Affectation  une proprit globale en lecture seule
var undefined = 5; // dclenche une exception TypeError
var Infinity = 5; // dclenche une exception TypeError

// Affectation  une proprit en lecture seule
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // lve un TypeError

// Affectation  une proprit qui n'a qu'une mthode get
var obj2 = {
  get x() {
    return 17;
  },
};
obj2.x = 5; // lve un TypeError

// Affectation d'une nouvelle proprit  un objet non-extensible
var gele = {};
Object.preventExtensions(gele);
gele.nouvelleProp = "oh"; // lve un TypeError

Troisimement, le mode strict lvera une exception lors d'une tentative de suppression d'une proprit non-supprimable (l o cela ne produisait aucun effet en mode non strict) :

js
"use strict";
delete Object.prototype; // lve une TypeError

Quatrimement, le mode strict, avant Gecko 34, requiert que toutes les proprits nommes dans un objet littral soient uniques. En mode non-strict, les proprits peuvent tre spcifies deux fois, JavaScript ne retenant que la dernire valeur de la proprit. Cette duplication en devient alors une source de confusion, surtout dans le cas o, dans une modification de ce mme code, on se met changer la valeur de la proprit autrement qu'en changeant la dernire instance. Les noms de proprit en double sont une erreur de syntaxe en mode strict :

js
"use strict";
var o = { p: 1, p: 2 }; // !!! erreur de syntaxe

Note : Cela n'est plus le cas avec ECMAScript 2015 (bug Firefox 1041128).

Cinquimement, le mode strict requiert que les noms de paramtres de fonction soient uniques. En mode non-strict, le dernier argument dupliqu cache les arguments prcdents ayant le mme nom. Ces arguments prcdents demeurent disponibles via arguments[i], ils ne sont donc pas compltement inaccessibles. Pourtant, cette cachette n'a gure de sens et n'est probablement pas souhaitable (cela pourrait cacher une faute de frappe, par exemple). Donc en mode strict, les doublons de noms d'arguments sont une erreur de syntaxe :

js
function somme(a, a, c) {
  // !!! erreur de syntaxe
  "use strict";
  return a + b + c; // Ce code va planter s'il est excut
}

Siximement, le mode strict interdit la syntaxe octale. La syntaxe octale ne fait pas partie d'ECMAScript 5, mais elle est supporte dans tous les navigateurs en prfixant le nombre octal d'un zro : 0644 === 420 et "\045" === "%". La notation octale est supporte en utilisant le prfixe "0o" :

js
let a = 0o10; // Notation octale ES2015

Les dveloppeurs novices croient parfois qu'un zro dbutant un nombre n'a pas de signification smantique, alors ils l'utilisent comme moyen d'aligner des colonnes de nombres mais ce faisant, ils changent la valeur du nombre ! La syntaxe octale est rarement utile et peut tre utilise de manire fautive, donc le mode strict le considre comme tant une erreur de syntaxe :

js
"use strict";
var somme =
  015 + // !!! erreur de syntaxe
  197 +
  142;

Septimement, le mode strict, partir d'ECMAScript 2015 interdit de dfinir des proprits sur des valeurs primitives. Sans mode strict, de telles dfinitions sont ignores. En activant le mode strict cela lvera une exception TypeError.

js
(function () {
  "use strict";

  false.true = ""; // TypeError
  (14).calvados = "maison"; // TypeError
  "une chane".de = "caractres"; // TypeError
})();

Simplifier l'utilisation des variables

Le mode strict simplifie la faon dont les noms de variables sont mis en correspondance avec les dfinitions de variables dans le code. De nombreuses optimisations du compilateur reposent sur la capacit dire quel endroit la variable X est stocke : cela est essentiel pour optimiser pleinement le code JavaScript. JavaScript rend parfois cette mise en correspondance impossible raliser avant l'excution du code. Le mode strict limine la plupart des cas o cela se produit, de sorte que le compilateur peut mieux optimiser le code en mode strict.

Premirement, le mode strict interdit l'utilisation de with. Le problme avec with est que tout nom de variable l'intrieur du bloc peut faire rfrence une proprit de l'objet qui lui est pass, ou encore une variable dclare l'extrieur du bloc, globale ou non, l'excution : il est impossible de le savoir d'avance. Le mode strict fait de with une erreur de syntaxe, donc il n'y a aucune chance pour qu'un nom dclar dans un with fasse rfrence un lieu inconnu l'excution :

js
"use strict";
var x = 17;
with (obj) {
  // !!! erreur de syntaxe
  // Si on n'tait pas en mode strict, serait-ce var x,
  // ou serait-ce plutt obj.x?  Il est impossible en gnral
  // de le dire sans faire tourner le code, donc
  // le nom ne peut pas tre optimis.
  x;
}

Au lieu d'utiliser with, on peut trs bien assigner l'objet une variable avec un nom court, puis accder aux proprits correspondantes cette variable.

Deuximement, eval en mode strict ne doit pas crer de variables dont la porte dpasse celle du eval. En mode non-strict, eval("var x;") cre la variable x dans le code appelant eval. Ce qui signifie qu'en gnral, dans une fonction contenant un appel eval, tous les noms qui ne rfrent pas un paramtre ou une variable locale devront tre mis en correspondance avec une dfinition de variable lors de l'excution (puisque cet eval a introduit une nouvelle variable qui serait susceptible de modifier la variable externe). En mode strict, eval ne cre des variables que pour le code tant valu, ainsi eval ne peut pas raliser d'affectation une variable externe ou une variable locale :

js
var x = 17;
var evalX = eval("'use strict'; var x = 42; x");
console.log(x === 17);
console.log(evalX === 42);

De la mme manire, si la fonction eval est invoque par une expression de la forme eval(...) dans un code en mode strict, le code sera aussi valu en mode strict. Le code peut dclarer explicitement le mode strict, mais il est inutile de le faire.

js
function strict1(str) {
  "use strict";
  return eval(str); // str sera valu en mode strict
}
function strict2(f, str) {
  "use strict";
  return f(str); // pas de eval(...) : str est strict si et seulement si il est dclar en mode strict
}
function nonstrict(str) {
  return eval(str); // str est strict si et seulement si il est dclar en mode strict
}

strict1("'Mode strict!'");
strict1("'use strict'; 'Mode strict!'");
strict2(eval, "'Mode non-strict.'");
strict2(eval, "'use strict'; 'Mode strict!'");
nonstrict("'Mode non-strict.'");
nonstrict("'use strict'; 'Mode strict!'");

Ainsi, les noms dans le code eval en mode strict se comportent de la mme faon que les noms dans le code en mode strict n'tant pas valus comme le rsultat de eval.

Troisimement, le mode strict interdit la suppression des variables dclares. delete name en mode strict est une erreur de syntaxe:

js
"use strict";
eval("var x; delete x;"); // !!! erreur de syntaxe

Rendre eval et arguments plus simples

Le mode strict rend arguments et eval() moins tranges . Les deux impliquent une quantit de comportements tranges dans le code en mode non-strict : eval afin d'ajouter et d'enlever des liaisons et pour changer les valeurs de liaisons, et arguments via ses proprits indexes faisant rfrence des arguments nomms. Le mode strict permet de mieux trater eval et arguments comme des mots-cls part entire, bien qu'une rparation complte ne devrait pas arriver avant une version future d'ECMAScript.

Premirement, les chanes eval et arguments ne peuvent pas tre utilises comme identificateur. Tous les exemples suivants entranent des erreurs de syntaxe :

js
"use strict";
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) {} };
var eval;
try {
} catch (arguments) {}
function x(eval) {}
function arguments() {}
var y = function eval() {};
var f = new Function("arguments", "'use strict'; return 17;");

Deuximement, en mode strict on ne donnera pas d'alias aux proprits de arguments avec les objets cres dans la fonction. En code normal, dans une fonction dont le premier argument est arg, modifier arg modifiera aussi arguments[0], et vice versa ( moins qu'aucun argument ne soit fourni ou que arguments[0] soit supprim). Les objets de arguments pour les fonctions en mode strict stockent les argument originaux, au moment o la fonction a t appele. arguments[i] ne reflte pas la valeur de l'argument nomm correspondant, et vice-versa.

js
function f(a) {
  "use strict";
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0] === 42);
console.log(pair[1] === 17);

Troisimement, arguments.callee n'est plus support. En temps normal arguments.callee contient la rfrence de la fonction courante. Il suffit d'appeler la fonction courante par son nom si elle n'est pas anonyme. arguments.callee en mode strict est une proprit non supprimable qui lvera une erreur si elle est dfinie ou rcupre :

js
"use strict";
var f = function () {
  return arguments.callee;
};
f(); // lve une TypeError

Scuriser JavaScript

Le mode strict permet d'crire plus simplement du code JavaScript sr. Certains sites web fournissent aujourd'hui des outils pour que les utilisateurs puissent crire du JavaScript qui sera excut sur le site pour les autres utilisateurs. Dans un navigateur web, le JavaScript peut accder certaines informations prives de l'utilisateur. Il faut donc transformer le JavaScript crit par un utilisateur externe pour que le code correspondant soit excut de faon scurise pour les autres utilisateurs. Pour ce faire, il faut effectuer des vrifications au moment de l'excution. En effet, JavaScript est suffisamment flexible pour que vrifier du code avant l'excution soit trs complexe voire impossible. En revanche, vrifier le comportement du code lors de l'excution a un cot sur les performances. Pour rduire ce nombre de vrifications et bnficier de meilleures performances dans ce scnario, on peut restreindre le code qui peut tre envoy du code en mode strict.

Tout d'abord, la valeur passe en tant que this une fonction n'est pas ncessairement transforme en un objet en mode strict. Pour une fonction normale , this est toujours un objet : soit l'objet fourni si la valeur fournie pour this tait un objet, soit la valeur, transforme en un objet quand c'est un boolen, une chane de caractres ou un nombre. Cette valeur peut galement tre l'objet global si this vaut null ou undefined lorsqu'il est pass la fonction. (Les fonctions Function.prototype.call(), Function.prototype.apply() ou Function.prototype.bind() peuvent tre utilises lorsqu'on souhaite spcifier une certaine valeur pour this.) Cette conversion automatique en objet a un certain cot en termes de performances mais cela peut galement exposer l'objet global ce qui est dangereux dans les navigateurs : en effet, l'objet global permet d'accder certaines fonctionnalits qui rendraient le code non-scuris. Ainsi, en mode strict, la valeur this n'est pas transforme en un objet et si elle n'est pas dfinie, this sera undefined :

js
"use strict";
function fun() {
  return this;
}
console.log(fun() === undefined);
console.log(fun.call(2) === 2);
console.log(fun.apply(null) === null);
console.log(fun.call(undefined) === undefined);
console.log(fun.bind(true)() === true);

Cela signifie entre autres qu'il est impossible de faire rfrence l'objet window du navigateur grce this au sein d'une fonction en mode strict.

Ensuite, en mode strict, il n'est plus possible de remonter la pile d'appels grce aux extensions communment implmentes. Par exemple, dans du code non strict, lorsqu'une fonction fun est en train d'tre appele, fun.caller fait rfrence la fonction qui a appel fun la dernire et fun.arguments correspond l'objet arguments pour cet appel fun. Ces deux extensions posent problme pour la scurit car elles permettent au code d'accder des fonctions privilgies et leurs arguments (ventuellement non scuriss). Si fun est passe en mode strict, fun.caller et fun.arguments seront des proprits non-supprimables qui lveront une exception pour chaque tentative d'accs ou de modification :

js
function restricted() {
  "use strict";
  restricted.caller; // lve une TypeError
  restricted.arguments; // lve une TypeError
}
function privilegedInvoker() {
  return restricted();
}
privilegedInvoker();

Enfin, pour une fonction en mode strict, arguments ne permet pas d'accder aux variables passes la fonction lors de l'appel. Dans certaines anciennes implmentations d'ECMAScript, arguments.caller tait un objet dont les proprits taient des alias pour les variables passes la fonction. Cela entrane un problme de scurit car cela empche de cacher des valeurs privilgies via l'abstraction des fonctions. Cela empche aussi de nombreuses optimisations. Pour ces raisons, les navigateurs rcents n'implmentent plus cet objet. Cependant, tant donn sa prsence historique, en mode strict, arguments.caller est une proprit non-supprimable qui dclenche une exception pour toute tentative d'accs ou de modification :

js
"use strict";
function fun(a, b) {
  "use strict";
  var v = 12;
  return arguments.caller; // lve une TypeError
}
fun(1, 2); // n'expose pas v (ni a ou b)

Prvoir la suite : les prochaines versions d'ECMAScript

Les prochaines versions d'ECMAScript inclueront certainement une nouvelle syntaxe, de nouveaux mots-cls. Le mode strict d'ECMAScript 5 applique certaines restrictions qui permettent de prvoir les transitions venir lorsque des changements auront lieu. Il sera ainsi plus simple de modifier le code si les erreurs relatives une nouvelle syntaxe sont mises en avant grce au mode strict.

Premirement, en mode strict, une liste d'identifiants fait partie des mots-cls rservs. Ces termes sont : implements, interface, let, package, private, protected, public, static, et yield. En mode strict, il est donc impossible de nommer des variables ou des arguments avec ces noms.

js
function package(protected) {
  // !!!
  "use strict";
  var implements; // !!!

  // !!!
  interface: while (true) {
    break interface; // !!!
  }

  function private() {} // !!!
}
function fun(static) {
  "use strict";
} // !!!

Deux dfauts lis Mozilla Firefox : tout d'abord si votre code est en JavaScript 1.7 ou suprieur (par exemple pour du code qui concerne le chrome dans les extensions ou lorsqu'on utilise les balises <script type="">) et qu'il est en mode strict, let et yield fonctionnent de la faon dont ils fonctionnaient originellement au sein de Firefox. En revanche, pour du code strict utilis sur une page web et charg avec <script src=""> ou <script>...</script>, on ne pourra pas utiliser let/yield comme identifiants. Ensuite, bien qu'ES5 rserve les mots-cls class, enum, export, extends, import, et super pour le mode strict et le mode non strict, les versions antrieures Firefox 5 ne rservaient ces mots-cls que pour le mode strict.

Deuximement, le mode strict interdit les dclarations de fonctions qui ne sont pas au niveau le plus haut d'un script ou d'une fonction. En mode normal, il est possible de dclarer une fonction n'importe o avec une dclaration de fonction (voir function). Ceci ne fait pas partie de la spcification ECMAScript et est donc une extension. Le mode strict interdit cela, ce qui permet de lever toute ambiguit par rapport aux futures spcifications ECMAScript sur cette fonctionnalit. On notera que les instructions de fonctions crites en dehors du plus haut niveau sont autorises avec ES2015 :

js
"use strict";
if (true) {
  function f() {} // !!! erreur de syntaxe
  f();
}

for (var i = 0; i < 5; i++) {
  function f2() {} // !!! erreur de syntaxe
  f2();
}

function truc() {
  // OK
  function bidule() {} // OK galement
}

Cette interdiction n'est pas, proprement parler, lie au mode strict. En effet, de telles dclarations de fonctions ne font pas partie d'ES5. Cependant, c'est un choix du comit ECMAScript que cette interdiction soit implmente.

Le mode strict dans les navigateurs

Dsormais, l'ensemble des navigateurs majeurs implmentent le mode strict. Cependant, il existe toujours un certain nombre de disparits et certains navigateurs actuels ou avec leurs anciennes versions ne supportent pas le mode strict. Le mode strict modifie des lments de smantique de JavaScript ; faire appel au mode strict pour des navigateurs qui ne le supportent pas peut donc entraner des erreurs indsirables. Pour cette raison, il faut faire attention la faon dont on excute du code strict et bien tester ce code sur l'ensemble des navigateurs : ceux qui supportent le mode strict comme ceux qui ne supportent pas ce mode.

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page