Pourquoi JavaScript est-il requis en mode strict?

Le mode strict est une partie importante du JavaScript moderne. C'est ce mode qui permet aux développeurs d'utiliser une syntaxe plus limitée que la syntaxe standard.

La sémantique du mode strict est différente du mode traditionnel non strict, qui est parfois appelé «mode bâclé». Dans ce mode, les règles de syntaxe de la langue ne sont pas aussi strictes et lorsque certaines erreurs se produisent, le système n'en informe pas l'utilisateur. Autrement dit, les erreurs peuvent être ignorées et le code dans lequel elles sont produites peut être exécuté davantage. Cela peut conduire à des résultats d'exécution de code inattendus.



Le mode strict introduit quelques changements dans la sémantique de JavaScript. Il empêche le système de fermer les yeux sur les erreurs en lançant des exceptions appropriées. Cela provoque l'arrêt du programme.

Le mode strict, en outre, aide à écrire des programmes dans lesquels il n'y a pas de défauts qui empêchent les moteurs JS d'optimiser le code. De plus, dans ce mode, il est interdit d'utiliser des éléments de syntaxe qui pourraient avoir une signification particulière dans les futures versions du langage.

Caractéristiques de l'utilisation du mode strict


Le mode strict peut être appliqué à des fonctions individuelles ou à un script entier. Il ne peut pas être appliqué uniquement à des instructions individuelles ou à des blocs de code entre accolades. Afin d'utiliser le mode strict au niveau de l'ensemble du script, au tout début du fichier, avant toute autre commande, vous devez mettre l' "use strict" ou 'use strict' construction 'use strict' .

Si le projet contient des scripts qui n'utilisent pas le mode strict et d'autres qui utilisent ce mode, il peut arriver que ces scripts soient fusionnés.

Cela conduira au fait que le code qui n'est pas destiné à être exécuté en mode strict sera dans un tel état lorsque le système essaiera de l'exécuter en mode strict. L'inverse est également possible - le code écrit pour le mode strict tombera en mode non strict. Par conséquent, il est préférable de ne pas mélanger les scripts «stricts» et «non stricts».

Comme déjà mentionné, le mode strict peut être appliqué aux fonctions individuelles. Pour ce faire "use strict" ou 'use strict' doit être placée en haut du corps de la fonction, avant toute autre commande. Le mode strict de cette approche s'applique à tout ce qui est placé dans le corps de la fonction, y compris les fonctions imbriquées.

Par exemple:

 const strictFunction = ()=>{  'use strict';  const nestedFunction = ()=>{    //        } } 

Dans les modules JavaScript apparus dans la norme ES2015, le mode strict est activé par défaut. Par conséquent, lorsque vous travaillez avec eux, vous n'avez pas besoin de l'inclure explicitement.

Modifications apportées au code JS par mode strict


Le mode strict affecte à la fois la syntaxe du code et la façon dont le code se comporte pendant l'exécution du programme. Les erreurs dans le code sont converties en exceptions. Le fait qu'en mode silencieux plante silencieusement en mode strict provoque un message d'erreur. Ceci est similaire à la façon dont le système répond aux erreurs de syntaxe en mode laxiste. En mode strict, le travail avec les variables est simplifié, l'utilisation de la fonction eval et l'objet arguments sont strictement réglementés, et le travail avec les constructions qui peuvent être implémentées dans les futures versions du langage est rationalisé.

▍ Convertir les erreurs silencieuses en exceptions


Les erreurs silencieuses sont converties en mode strict en exceptions. En mode laxiste, le système ne répond pas explicitement à de telles erreurs. En mode strict, la présence de telles erreurs conduit à une inopérabilité du code.

Ainsi, grâce à cela, il est difficile de commettre l'erreur de déclarer accidentellement une variable globale, car les variables et les constantes en mode strict ne peuvent pas être déclarées sans utiliser les directives var , let ou const . Par conséquent, la création de variables sans ces directives entraînera une inopérabilité du programme. Par exemple, la tentative d'exécution du code suivant lèvera une exception ReferenceError :

 'use strict'; badVariable = 1; 

Un tel code ne peut pas être exécuté en mode strict, car si le mode strict était désactivé, il créerait une variable globale badVariable . Le mode strict empêche le programmeur de créer par inadvertance des variables globales.

Une tentative d'exécution d'un code qui, en mode normal, ne fonctionne tout simplement pas, lève maintenant une exception. Les erreurs sont considérées comme des constructions syntaxiques incorrectes qui ont simplement été ignorées en mode laxiste.

Ainsi, par exemple, en mode strict, vous ne pouvez pas effectuer d'opérations d'attribution de valeur sur des entités en lecture seule telles que des arguments , NaN ou eval .

En mode strict, une exception, par exemple, sera levée dans les cas suivants:

  • une tentative d'attribution d'une valeur à une propriété en lecture seule, telle qu'une sorte de propriété globale réinscriptible;
  • une tentative d'écrire une valeur dans une propriété qui n'a qu'un getter;
  • Une tentative d'écrire quelque chose dans une propriété d'un objet non extensible.

Voici des exemples de constructions de syntaxe menant à des exceptions de mode strictes:

 'use strict'; let undefined = 5; let Infinity = 5; let obj = {}; Object.defineProperty(obj, 'foo', { value: 1, writable: false }); obj.foo = 1 let obj2 = { get foo() { return 17; } }; obj2.foo = 2 let fixedObj = {}; Object.preventExtensions(fixedObj); fixed.bar= 1; 

Tenter d'exécuter de tels fragments de code en mode strict TypeError une exception TypeError . Par exemple, undefined et Infinity sont des entités globales dont les valeurs ne peuvent pas être écrasées et la propriété foo de l'objet obj ne prend pas en charge la réécriture. La propriété foo de obj2 n'a qu'un getter. L'objet fixedObj rendu non extensible à l'aide de la méthode Object.preventExtensions .

Une tentative de suppression d'une TypeError entraînera également TypeError :

 'use strict'; delete Array.prototype 

Le mode strict interdit d'attribuer des propriétés du même nom à un objet. Par conséquent, une tentative d'exécution du code suivant entraînera une erreur de syntaxe:

 'use strict'; let o = { a: 1, a: 2 }; 

Le mode strict requiert que les noms des paramètres de fonction soient uniques. En mode non strict, si, par exemple, deux paramètres d'une fonction ont le même nom, alors, lors du passage de la fonction d'argument, la valeur du paramètre sera celle qui est tombée dans l'argument déclaré en dernier.

En mode strict, les paramètres des fonctions du même nom sont interdits. Par conséquent, une tentative d'exécution du code suivant entraînera une erreur de syntaxe:

 'use strict'; const multiply = (x, x, y) => x*x*y; 

En mode strict, vous ne pouvez pas utiliser la notation octale des nombres, précédant le nombre de zéro. Ce n'est pas dans la spécification, mais cette fonctionnalité est prise en charge par les navigateurs.

Cet état de choses confond les développeurs, les obligeant à croire que le 0 précédant le nombre est simplement ignoré, sans grand sens. En mode strict, essayer d'utiliser un nombre au début duquel est 0 entraînera une erreur de syntaxe.

Le mode strict interdit également l'utilisation de constructions qui entravent l'optimisation. L'interpréteur, avant d'effectuer l'optimisation du code, doit savoir que la variable est stockée exactement où, selon l'interprète, elle est stockée. En mode strict, les choses qui interfèrent avec les optimisations sont interdites.

Un exemple d'une telle interdiction concerne la déclaration with . Si vous utilisez cette instruction, cela empêche l'interpréteur JS de savoir à quelle variable ou à quelle propriété nous faisons référence, car il est possible qu'une entité du même nom existe à la fois à l'extérieur et à l'intérieur du bloc de l'instruction with .

Supposons qu'il existe un code comme celui-ci:

 let x = 1; with (obj) {  x; } 

L'interpréteur ne pourra pas savoir si la variable x située à l'intérieur du bloc with fait référence à la variable externe x ou à la propriété obj.x de l'objet obj .

Par conséquent, on ne sait pas exactement où la valeur x sera située en mémoire. Afin de se débarrasser de telles ambiguïtés, en mode strict, l'utilisation de l'instruction with est interdite. Voyons ce qui se passe si vous essayez d'exécuter le code suivant en mode strict:

 'use strict'; let x = 1; with (obj) {  x; } 

Le résultat de cette tentative sera une erreur de syntaxe.

Même en mode strict, il est interdit de déclarer des variables dans le code passé à la méthode eval .

Par exemple, en mode normal, une commande de la forme eval('let x') entraînera la déclaration de la variable x . Cela permet aux programmeurs de masquer les déclarations de variables dans des chaînes, ce qui peut conduire à écraser les définitions des mêmes variables en dehors de eval .

Pour éviter cela, en mode strict, il est interdit de déclarer des variables dans le code passé en chaîne à la méthode eval .

Le mode strict interdit également la suppression des variables régulières. Par conséquent, la tentative d'exécution du code suivant entraînera une erreur de syntaxe:

 'use strict'; let x; delete x; 

▍ Interdire les constructions de syntaxe incorrectes


En mode strict, l'utilisation incorrecte de eval et des arguments interdite. Il s'agit d'une interdiction de toutes sortes de manipulations avec eux. Par exemple, cela revient à leur attribuer de nouvelles valeurs, en utilisant leurs noms comme noms de variable, fonctions, paramètres de fonction.

Voici des exemples d'utilisation abusive de l' eval et des arguments :

 'use strict'; eval = 1; arguments++; arguments--; ++eval; eval--; let obj = { set p(arguments) { } }; let eval; try { } catch (arguments) { } try { } catch (eval) { } function x(eval) { } function arguments() { } let y = function eval() { }; let eval = ()=>{ }; let f = new Function('arguments', "'use strict'; return 1;"); 

En mode strict, vous ne pouvez pas créer d'alias pour l'objet arguments et définir de nouvelles valeurs d' arguments via ces alias.

En mode normal, si le premier paramètre de la fonction est a , la définition de la valeur de a dans le code de fonction entraîne également une modification de la valeur dans les arguments[0] . En mode strict, les arguments contiendront toujours la liste des arguments avec lesquels la fonction a été appelée.

Supposons que vous ayez le code suivant:

 const fn = function(a) {  'use strict';  a = 2;  return [a, arguments[0]]; } console.log(fn(1)) 

La console obtiendra [2,1] . En effet, l'écriture d'une valeur de 2 dans a n'écrit pas une valeur de 2 dans les arguments[0] .

▍Optimisez les performances


En mode strict, la propriété arguments.callee n'est pas prise en charge. En mode normal, il retourne le nom de la fonction parent de la fonction dont nous callee propriété callee de l'objet arguments .

La prise en charge de cette propriété interfère avec les optimisations, telles que les fonctions en ligne, car l'utilisation d' arguments.callee nécessite la disponibilité d'une référence à une fonction non intégrée lors de l'accès à cette propriété. En mode strict, l'utilisation d' arguments.callee déclenche une exception TypeError .

En mode strict, le this - this ne doit pas toujours être un objet. Dans des circonstances normales, si this fonction est liée, à l'aide de call , apply ou bind , à quelque chose qui n'est pas un objet, à une valeur de type primitif comme undefined , null , number ou boolean , une telle valeur doit être un objet.

Si le contexte de this change en quelque chose qui n'est pas un objet, un objet global prend sa place. Par exemple, window . Cela signifie que si vous appelez une fonction en définissant son this sur une valeur qui n'est pas un objet, au lieu de cette valeur, une référence à l'objet global y tombera.

Prenons un exemple:

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

Toutes les commandes console.log afficheront true , car en mode strict, la valeur de this dans la fonction n'est pas automatiquement remplacée par une référence à l'objet global si this définie sur une valeur qui n'est pas un objet.

▍ Modifications liées à la sécurité


En mode strict, vous ne pouvez pas rendre publiques les propriétés de la fonction caller et arguments . Le fait est que l' caller , par exemple, peut donner accès à la fonction qui a appelé la fonction dont nous accédons à la propriété de l' caller .

L'objet arguments stocke les arguments passés à la fonction lors de son appel. Par exemple, si nous avons une fonction fn , cela signifie que via fn.caller vous pouvez accéder à la fonction qui a appelé la fonction, et en utilisant fn.arguments vous pouvez voir les arguments passés à fn lors de son appel.

Ces fonctionnalités présentent un risque potentiel pour la sécurité. Par conséquent, l'accès à ces propriétés est interdit en mode strict.

 function secretFunction() {  'use strict';  secretFunction.caller;  secretFunction.arguments; } function restrictedRunner() {  return secretFunction(); } restrictedRunner(); 

Dans l'exemple précédent, nous ne pouvons pas, en mode strict, accéder à secretFunction.caller et secretFunction.arguments . Le fait est que ces propriétés peuvent être utilisées pour obtenir une pile d'appels de fonction. Si vous essayez d'exécuter ce code, une exception TypeError sera TypeError .

En mode strict, les identifiants pouvant être utilisés dans les futures versions de JavaScript ne peuvent pas être utilisés pour nommer des variables ou des propriétés d'objets. Par exemple, nous parlons des identifiants suivants: implements , interface , let , package , private , protected , public , static et yield .

Dans ES2015 et dans les versions ultérieures de la norme, ces identifiants sont devenus des mots réservés. Et ils ne peuvent pas être utilisés pour nommer des variables ou des propriétés en mode strict.

Résumé


Le mode strict est une norme qui existe depuis de nombreuses années. Il bénéficie d'un support de navigateur extrêmement large. Les problèmes avec le code en mode strict ne peuvent se produire que dans les navigateurs plus anciens, comme Internet Explorer.

Les navigateurs modernes ne devraient pas avoir de difficulté avec le mode JavaScript strict. Par conséquent, nous pouvons dire que ce mode doit être utilisé pour éviter les erreurs «silencieuses» et pour augmenter la sécurité des applications. Les erreurs silencieuses sont converties en exceptions qui gênent l'exécution des programmes et en termes d'amélioration de la sécurité, par exemple, des mécanismes en mode strict qui restreignent l' eval et empêchent l'accès à la pile d'appels de fonction peuvent être notés. De plus, l'utilisation du mode strict facilite l'optimisation du code du moteur JS et oblige le programmeur à gérer soigneusement les mots réservés qui pourraient être utilisés dans les futures versions de JavaScript.

Chers lecteurs! Utilisez-vous le mode strict lors de l'écriture de code JS pour vos projets?


Source: https://habr.com/ru/post/fr477284/


All Articles