El modo estricto es una parte importante del JavaScript moderno. Es este modo el que permite a los desarrolladores usar una sintaxis más limitada que la estándar.
La semántica del modo estricto es diferente del modo no estricto tradicional, que a veces se denomina "modo descuidado". En este modo, las reglas de sintaxis del lenguaje no son tan estrictas, y cuando ocurren algunos errores, el sistema no notifica al usuario sobre ellos. Es decir, los errores se pueden ignorar y el código en el que se realizan se puede ejecutar más. Esto puede conducir a resultados inesperados de ejecución de código.

El modo estricto introduce algunos cambios en la semántica de JavaScript. Evita que el sistema haga la vista gorda ante los errores al lanzar las excepciones apropiadas. Esto hace que la ejecución del programa se detenga.
El modo estricto, además, ayuda a escribir programas en los que no hay defectos que impidan que los motores JS optimicen el código. Además, en este modo está prohibido usar elementos de sintaxis que puedan tener un significado especial en futuras versiones del lenguaje.
Características del uso del modo estricto
El modo estricto se puede aplicar a funciones individuales o a un script completo. No se puede aplicar solo a instrucciones individuales o a bloques de código encerrados entre llaves. Para usar el modo estricto a nivel de toda la secuencia de comandos, al comienzo del archivo, antes de cualquier otro comando, debe poner el
"use strict"
o
'use strict'
construcción
'use strict'
.
Si el proyecto tiene algunos scripts que no usan el modo estricto y otros que usan este modo, puede suceder que estos scripts se fusionen.
Esto conducirá al hecho de que el código que no está destinado a ejecutarse en modo estricto estará en tal estado cuando el sistema intente ejecutarlo en modo estricto. También es posible lo contrario: el código escrito para el modo estricto caerá en el modo no estricto. Por lo tanto, es mejor no mezclar scripts "estrictos" y "no estrictos".
Como ya se mencionó, el modo estricto se puede aplicar a funciones individuales. Para hacer esto, la construcción
"use strict"
o
'use strict'
debe colocarse en la parte superior del cuerpo de la función, antes que cualquier otro comando. El modo estricto con este enfoque se aplica a todo lo que se coloca en el cuerpo de la función, incluidas las funciones anidadas.
Por ejemplo:
const strictFunction = ()=>{ 'use strict'; const nestedFunction = ()=>{
En los módulos JavaScript que aparecieron en el estándar ES2015, el modo estricto está habilitado de forma predeterminada. Por lo tanto, cuando trabaje con ellos, no necesita incluirlo explícitamente.
Cambios introducidos en el código JS por modo estricto
El modo estricto afecta tanto la sintaxis del código como el comportamiento del código durante la ejecución del programa. Los errores en el código se convierten en excepciones. El hecho de que en modo silencioso se bloquee silenciosamente en modo estricto provoca un mensaje de error. Esto es similar a cómo el sistema responde a los errores de sintaxis en modo lax. En modo estricto, el trabajo con variables se simplifica, el uso de la función
eval
y el objeto de
arguments
están estrictamente regulados, y el trabajo con construcciones que se pueden implementar en futuras versiones del lenguaje se simplifica.
▍ Convertir errores silenciosos en excepciones
Los errores silenciosos se convierten en modo estricto a excepciones. En modo laxo, el sistema no responde explícitamente a tales errores. En modo estricto, la presencia de tales errores conduce a la inoperancia del código.
Entonces, gracias a esto, es difícil cometer el error de declarar accidentalmente una variable global, ya que las variables y constantes en modo estricto no pueden declararse sin usar las directivas
var
,
let
o
const
. Como resultado, la creación de variables sin estas directivas conducirá a la inoperancia del programa. Por ejemplo, intentar ejecutar el siguiente código arrojará una excepción
ReferenceError
:
'use strict'; badVariable = 1;
Dicho código no se puede ejecutar en modo estricto, ya que si el modo estricto se desactivara, crearía la variable global
badVariable
. El modo estricto protege al programador de la creación inadvertida de variables globales.
Un intento de ejecutar cualquier código que, en modo normal, simplemente no funciona, ahora arroja una excepción. Se considera que los errores son construcciones sintácticas incorrectas que simplemente se ignoraron en modo laxo.
Entonces, por ejemplo, en modo estricto, no puede realizar operaciones de asignación de valores en entidades de solo lectura como
arguments
,
NaN
o
eval
.
En modo estricto, se generará una excepción, por ejemplo, en los siguientes casos:
- un intento de asignar un valor a una propiedad de solo lectura, como algún tipo de propiedad global regrabable;
- un intento de escribir un valor en una propiedad que solo tiene un captador;
- Un intento de escribir algo en una propiedad de un objeto no extensible.
Aquí hay ejemplos de construcciones de sintaxis que conducen a excepciones de modo estricto:
'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;
Intentar ejecutar dichos fragmentos de código en modo estricto generará una excepción
TypeError
. Por ejemplo,
undefined
e
Infinity
son entidades globales cuyos valores no se pueden sobrescribir, y la propiedad
foo
del objeto
obj
no admite la reescritura. La propiedad
foo
de
obj2
solo tiene un captador. El objeto
fixedObj
hace no extensible utilizando el método
Object.preventExtensions
.
Un intento de eliminar una
TypeError
no
TypeError
también dará como resultado
TypeError
:
'use strict'; delete Array.prototype
El modo estricto prohíbe asignar propiedades con el mismo nombre a un objeto. Como resultado, un intento de ejecutar el siguiente código dará como resultado un error de sintaxis:
'use strict'; let o = { a: 1, a: 2 };
El modo estricto requiere que los nombres de los parámetros de la función sean únicos. En modo no estricto, si, por ejemplo, dos parámetros de función tienen el mismo nombre
one
, entonces, al pasar la función de argumento, el valor del parámetro será el que cayó en el argumento declarado en último lugar.
En modo estricto, los parámetros de funciones con el mismo nombre están prohibidos. Como resultado, un intento de ejecutar el siguiente código dará como resultado un error de sintaxis:
'use strict'; const multiply = (x, x, y) => x*x*y;
En modo estricto, no puede usar la notación octal de números, precediendo el número con cero. Esto no está en la especificación, pero esta característica es compatible con los navegadores.
Este estado de cosas confunde a los desarrolladores, obligándolos a creer que el 0 que precede al número simplemente se ignora, sin mucho sentido. En modo estricto, intentar usar un número al principio del cual sea 0 dará como resultado un error de sintaxis.
El modo estricto también prohíbe el uso de construcciones que impiden la optimización. El intérprete, antes de realizar la optimización del código, necesita saber que la variable se almacena exactamente donde, según el intérprete, se almacena. En modo estricto, las cosas que interfieren con las optimizaciones están prohibidas.
Un ejemplo de tal prohibición se refiere a la declaración
with
. Si usa esta instrucción, esto evita que el intérprete JS descubra a qué variable o qué propiedad nos referimos, ya que es posible que exista una entidad con el mismo nombre tanto fuera como dentro del bloque de la instrucción
with
.
Supongamos que hay un código como este:
let x = 1; with (obj) { x; }
El intérprete no podrá averiguar si la variable
x
ubicada dentro del bloque
with
se refiere a la variable externa
x
, oa la propiedad
obj.x
del objeto
obj
.
Como resultado, no está claro exactamente dónde se ubicará el valor
x
en la memoria. Para deshacerse de tales ambigüedades, en modo estricto está prohibido el uso de la declaración
with
. Veamos qué sucede si intentas ejecutar el siguiente código en modo estricto:
'use strict'; let x = 1; with (obj) { x; }
El resultado de este intento será un error de sintaxis.
Incluso en modo estricto, está prohibido declarar variables en el código pasado al método
eval
.
Por ejemplo, en modo normal, un comando de la forma
eval('let x')
dará como resultado la declaración de la variable
x
. Esto permite a los programadores ocultar declaraciones de variables en cadenas, lo que puede conducir a sobrescribir las definiciones de las mismas variables fuera de
eval
.
Para evitar esto, en modo estricto está prohibido declarar variables en el código pasado como una cadena al método
eval
.
El modo estricto también prohíbe la eliminación de variables regulares. Como resultado, intentar ejecutar el siguiente código dará como resultado un error de sintaxis:
'use strict'; let x; delete x;
▍ Prohibir construcciones de sintaxis incorrectas
En modo estricto, el uso incorrecto de
eval
y
arguments
prohibido. Esta es una prohibición de todo tipo de manipulaciones con ellos. Por ejemplo, esto es algo así como asignarles nuevos valores, usando sus nombres como nombres de variables, funciones, parámetros de función.
Aquí hay ejemplos de mal uso de
eval
y
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 modo estricto, no puede crear alias para el objeto de
arguments
y establecer nuevos valores de
arguments
través de estos alias.
En modo normal, si el primer parámetro de la función es
a
, entonces establecer el valor de
a
en el código de la función también conduce a un cambio en el valor de los
arguments[0]
. En modo estricto, los
arguments
siempre contendrán la lista de argumentos con los que se llamó a la función.
Supongamos que tiene el siguiente código:
const fn = function(a) { 'use strict'; a = 2; return [a, arguments[0]]; } console.log(fn(1))
La consola obtendrá
[2,1]
. Esto se debe a que escribir un valor de 2 en a no escribe un valor de 2 en los
arguments[0]
.
▍ Optimizar el rendimiento
En modo estricto, la propiedad
arguments.callee
no es compatible. En el modo normal, devuelve el nombre de la función principal de la función cuya propiedad
callee
del objeto de
arguments
que estamos examinando.
El soporte para esta propiedad interfiere con las optimizaciones, como las funciones de alineación, ya que el uso de
arguments.callee
requiere la disponibilidad de una referencia a una función no incrustada al acceder a esta propiedad. En modo estricto, el uso de
arguments.callee
genera una excepción
TypeError
.
En modo estricto,
this
no tiene que ser siempre un objeto. En circunstancias normales, si
this
función está vinculada, utilizando
call
,
apply
o
bind
, a algo que no es un objeto, a un valor de un tipo primitivo como
undefined
,
null
,
number
o
boolean
, dicho valor debería ser un objeto.
Si el contexto de
this
cambia a algo que no es un objeto, un objeto global toma su lugar. Por ejemplo,
window
. Esto significa que si llama a una función estableciendo
this
en un valor que no es un objeto, en lugar de este valor, una referencia al objeto global caerá en
this
.
Considere un ejemplo:
'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);
Todos los comandos de
console.log
generarán
true
, porque en modo estricto el valor de
this
en la función no se reemplaza automáticamente por una referencia al objeto global si
this
establece en un valor que no es un objeto.
▍ Cambios relacionados con la seguridad
En modo estricto, no puede hacer públicas las propiedades de la función de
caller
y
arguments
. El hecho es que la
caller
que
caller
, por ejemplo, puede dar acceso a la función que llamó a la función cuya propiedad de la
caller
que
caller
estamos accediendo.
El objeto de
arguments
almacena los argumentos pasados a la función cuando se llamó. Por ejemplo, si tenemos una función
fn
, esto significa que a través de
fn.caller
puede acceder a la función que llamó a la función, y usando
fn.arguments
puede ver los argumentos pasados a
fn
cuando se llamó.
Estas características plantean un riesgo potencial de seguridad. Como resultado, el acceso a estas propiedades está prohibido en modo estricto.
function secretFunction() { 'use strict'; secretFunction.caller; secretFunction.arguments; } function restrictedRunner() { return secretFunction(); } restrictedRunner();
En el ejemplo anterior, no podemos, en modo estricto, acceder a
secretFunction.caller
y
secretFunction.arguments
. El hecho es que estas propiedades se pueden usar para obtener una pila de llamadas a funciones. Si intenta ejecutar este código, se generará una excepción
TypeError
.
En modo estricto, los identificadores que pueden usarse en futuras versiones de JavaScript no pueden usarse para nombrar variables o propiedades de objetos. Por ejemplo, estamos hablando de los siguientes identificadores:
implements
,
interface
,
let
,
package
,
private
,
protected
,
public
,
static
y
yield
.
En ES2015 y en versiones posteriores del estándar, estos identificadores se convirtieron en palabras reservadas. Y no se pueden usar para nombrar variables o propiedades en modo estricto.
Resumen
El modo estricto es un estándar que existe desde hace muchos años. Disfruta de un soporte de navegador extremadamente amplio. Los problemas con el código de modo estricto solo pueden ocurrir en navegadores antiguos, como Internet Explorer.
Los navegadores modernos no deberían tener dificultades con el modo estricto de JavaScript. Como resultado, podemos decir que este modo debe usarse para evitar errores "silenciosos" y aumentar la seguridad de la aplicación. Los errores silenciosos se convierten en excepciones que impiden la ejecución de programas y, en términos de mejorar la seguridad, por ejemplo, se pueden observar mecanismos de modo estricto que restringen la
eval
y evitan el acceso a la pila de llamadas de función. Además, el uso del modo estricto facilita la optimización del código con los motores JS y obliga al programador a manejar cuidadosamente las palabras reservadas que pueden encontrar uso en futuras versiones de JavaScript.
Estimados lectores! ¿Utiliza el modo estricto cuando escribe código JS para sus proyectos?
