El strict mode es un set de reglas que habilita un modo de operación más recomendable para Javascript.
Este modo se introdujo en ES5, y us propósito era precisamente habilitar reglas que ayudaran a escribir código con buenas prácticas de progamación. Aunque su uso se mantuvo opcional para no interferir con el estándar en ese momento.
Para identificar si un archivo de JS lo esta utilizando debes buscar la directiva:
'use strict'
Claro, conforme han salido nuevas versiones de Javascript, muchas de las nuevas funcionalidades traen implícitamente el comportamiento de strict mode. Un ejemplo son los módulos y las clases introducidos en ES6.
No obstante siempre es recomendable asegurarse de estar utlizandolo ya que hay cosas que pueden pasar en otras áreas de Javascript. Cosas que a otros lenguajes les parecería una aberración.
1.Previene la creación accidental de variables globales
Este es en mi opinión el peor de los pecados de JS. Si asignas un valor a una variable no declarada, Javascript te hace el favor de crearla, en lugar de avisarte que no lo hiciste.
newValue = 23
console.log(newValue) // 23
Esto va en contra de las buenas prácticas porque da pie a que se encuentren variables ocultas a lo largo del código y sea más dificíl debuggear cuando eso suceda.
Strict mode viene a poner las cosas en orden. Como debe ser.
'use strict'
newValue = 23
console.log(newValue) // ReferenceError: newValue is not defined
2.Evita equivocaciones al intentar borrar propiedades
Javascript por default permite borrar las propiedades de un objeto con la keyword delete
:
let obj = {
value: 50
}
console.log(obj.value) // 50
delete obj.value
console.log(obj.value) // undefined
Sin embargo no permite borrar variables ni objetos directamente:
let obj = {
value: 50
}
console.log(obj) // { value: 50 }
delete obj
console.log(obj) // { value: 50 }
Cómo puedes cuando intentar borrar un objeto simplemente lo ignora en vez de decirte algo al respecto. Por eso mismo strict mode habililta un mensaje de error apropiado:
'use strict'
let obj = {
value: 50
}
console.log(obj) // SyntaxError: Delete of an unqualified identifier in strict mode.
delete obj
console.log(obj)
3.Previene la utilización de nombres duplicados en los parámetros de una misma función
Increiblemente Javascript permite que se repitan nombres en los parámetros que definas para una función.
function addition(valueA, valueA) {
return valueA + valueA
}
console.log(addition(1,4)) // 8
*Si. El resultado es incorrecto. Precisamente por eso no debería permitirse este comportamiento en primer lugar.
Con strict mode verás el comportamiento que normalmente esperarías tras haber escrito algo así:
'use strict'
function addition(valueA, valueA) {
return valueA + valueA
}
console.log(addition(1,4)) // SyntaxError: Duplicate parameter name not allowed in this context
4.Impide asignar valores a una propiedad de solo lectura
En JS se puede especificar que una variable sea de solo lectura. Esto ayuda a prevenir que el valor de una variable cambie.
let userObject = {}
Object.defineProperty(userObject, 'username', {value: 'ProfHu1k', writable: false})
console.log(userObject.username) // ProfHu1k
userObject.username = 'BruceBan'
console.log(userObject.username) // ProfHu1k
Como puedes ver el código pareceria haber ignorado la asignación del valor nuevo BruceBan
a la propiedad username
. Esto es comportamiento esperado, pero siendo sinceros sería mejor que se lanzará un error antes de compilar el código.
Si te pones a pensarlo, si se hizo una variable de solo lectura y aun así se le esta reasignando un valor es más que obvio que no fue intencional.
'use strict'
let userObject = {}
Object.defineProperty(userObject, 'username', {value: 'ProfHu1k', writable: false})
console.log(userObject.username) // ProfHu1k
userObject.username = 'BruceBan' // throws Error: TypeError: Cannot assign to read only property 'username' of object '#<Object>'
console.log(userObject.username)
5.Impide utilizar la keyword eval
como nombre en una variable
En Javascript eval
permite ejecutar código a partir de un string. Es una funcionalidad poco recomendable de utilizar, ya que abre el camino a inyectar código malicioso por medio de texto en tus scripts. Sin embargo existe y al exisitir pero porsupuesto que se ha usado.
eval('console.log("Log from eval")') // Log from eval
let eval = () => {
console.log('custom function')
}
console.log(eval()) // ReferenceError: Cannot access 'eval' before initialization
A diferencia de casos anteriores, en este si se lanza un error. Pero no es un error adecuado. El mensaje indica que no se iinicializó la variable cuando la realidad es que se acaba de hacer eso en la línea anterior…
'use strict'
eval('console.log("Log from eval")') // Log from eval
let eval = () => { // SyntaxError: Unexpected eval or arguments in strict mode
console.log('custom function')
}
console.log(eval)
Ahora si. Con use strict
este error si tiene sentido y protege la keyword eval
como debe de ser.
6.Impide utilizar la keyword arguments
como nombre en una variable
Otro keyword importante en JS es arguments
. Sin embargo, a diferencia de evals
, su uso es más común, ya que sirve para acceder a los parámetros de una función.
function startPlaylist(playlistId, loop) {
console.log(arguments[0]) // 10
console.log(arguments[1]) // false
}
startPlaylist(10, false)
Pero como ya te imaginarás Javascript permite sobreescribir la variable, causando comportamiento inesperado:
function startPlaylist(playlistId, loop) {
console.log(arguments[0]) // ReferenceError: Cannot access 'arguments' before initialization
console.log(arguments[1])
let arguments = 34
console.log(arguments)
}
startPlaylist(10, false)
Al intentar ejecutar este código, la consola nos regresa un error sin sentido. Pero con strict mode eso se compone.
'use strict'
function startPlaylist(playlistId, loop) {
console.log(arguments[0])
console.log(arguments[1])
let arguments = 34 // SyntaxError: Unexpected eval or arguments in strict mode
console.log(arguments)
}
startPlaylist(10, false)
Estos son los mas importantes aunque también hay otros como:
- Prohibir el uso de literales de octales sin el prefijo: o
- Prohibir las secuencias de escape: \
- Prohibir el uso de
with
Por definición utilizar use strict
debería ser prácticamente obligatorio. Y de hecho como mencionaba al principio, prácticamente lo es, al menos para las nuevas funcionalidades que se han ido agregando .
No te dejes engañar. Si no ves use strict
en código de Javascript no significa que no se este usando. Sin embargo es importante que sepas de su existencia porque todavía puedes toparte con código antiguo que no hacía uso del mismo.