Modo estrito (use strict)
Nesta aula, vamos explorar o modo estrito do JavaScript ('use strict'), entendendo o que ele muda, por que ativá-lo e as principais diferenças de comportamento em relação ao modo não estrito. Você aprenderá como essa diretiva ajuda a escrever código mais seguro e a evitar erros comuns.
O modo estrito ('use strict') é uma funcionalidade introduzida no ECMAScript 5 que permite optar por uma variante restrita do JavaScript. Ao ativar o modo estrito, o interpretador passa a aplicar regras mais rígidas de sintaxe e semântica, transformando erros silenciosos em erros lançados, proibindo certas construções e impedindo ações que podem levar a bugs sutis. Essa diretiva é essencial para escrever código moderno e robusto, e é recomendada em todos os novos projetos.
Nesta aula, vamos detalhar o que muda com o modo estrito, os motivos para ativá-lo e as diferenças de comportamento em relação ao modo normal. Ao final, você terá uma compreensão sólida de como usar o 'use strict' para melhorar a qualidade do seu código JavaScript.
O que muda
O modo estrito altera vários comportamentos do JavaScript. Em vez de listar exaustivamente todas as mudanças, vamos focar nas mais relevantes para o dia a dia do desenvolvimento. A ativação é feita com a string 'use strict' no início de um script ou de uma função. Quando colocada no início de um arquivo, aplica-se a todo o código; quando dentro de uma função, apenas àquela função (e às funções aninhadas).
Uma das mudanças mais significativas é que o modo estrito elimina alguns erros silenciosos, fazendo com que eles lancem exceções. Por exemplo, atribuir valor a uma variável não declarada, que no modo normal cria uma variável global implicitamente, no modo estrito lança um ReferenceError. Isso ajuda a evitar poluição do escopo global e bugs decorrentes de erros de digitação.
// modo normal
nome = 'Maria'; // cria uma variável global (em navegadores)
console.log(nome); // 'Maria'
// modo estrito
'use strict';
nome = 'Maria'; // ReferenceError: assignment to undeclared variable nome
Outra mudança importante é que o modo estrito proíbe a utilização de palavras reservadas para futuras versões do ECMAScript, como implements, interface, package, private, protected, public, static, let, yield (em algumas versões). Isso garante que o código não quebre quando novas funcionalidades forem adicionadas à linguagem.
Além disso, o modo estrito torna mais fácil escrever código seguro, pois proíbe o uso de with, que é considerado perigoso e prejudicial à performance. A declaração with adiciona um objeto ao escopo, o que pode causar ambiguidades e dificultar a otimização do código. No modo estrito, usar with resulta em um erro de sintaxe.
// modo normal
var obj = { x: 10 };
with (obj) {
console.log(x); // 10
}
// modo estrito
'use strict';
var obj = { x: 10 };
with (obj) { // SyntaxError: Strict mode code may not include a with statement
console.log(x);
}
Por que ativar
Ativar o modo estrito é uma prática recomendada por diversos motivos. Primeiramente, ele ajuda a detectar erros cedo, transformando erros silenciosos em exceções que podem ser capturadas e corrigidas durante o desenvolvimento. Isso reduz a probabilidade de bugs que passam despercebidos em produção.
Em segundo lugar, o modo estrito melhora a segurança do código. Ao proibir o acesso a propriedades de objetos como this em funções chamadas sem contexto, ele evita que o valor global (window no navegador, global no Node.js) seja usado indevidamente. Em funções normais, no modo não estrito, this é forçado a ser o objeto global quando a função é chamada sem um receptor; no modo estrito, this permanece undefined. Isso é mais lógico e evita modificações acidentais no objeto global.
function mostrarThis() {
console.log(this);
}
mostrarThis(); // no modo normal: Window (ou global); no modo estrito: undefined
'use strict';
function mostrarThisEstrito() {
console.log(this);
}
mostrarThisEstrito(); // undefined
Além disso, o modo estrito torna o JavaScript mais alinhado com boas práticas de programação, como declarar todas as variáveis antes de usá-las. Isso é especialmente importante em equipes, pois o código fica mais previsível e fácil de revisar.
Outro benefício é a compatibilidade futura. Ao proibir o uso de palavras reservadas, o modo estrito garante que o código não quebre quando novas funcionalidades forem adicionadas ao ECMAScript. Isso é crucial para bibliotecas e frameworks que precisam manter compatibilidade com várias versões do JavaScript.
Diferenças de comportamento
Vamos explorar algumas diferenças específicas de comportamento entre o modo estrito e o modo não estrito. Uma delas é a atribuição a propriedades não graváveis ou getters sem setter. No modo normal, essa atribuição falha silenciosamente; no modo estrito, lança um TypeError.
// modo normal
var obj = {};
Object.defineProperty(obj, 'x', { value: 42, writable: false });
obj.x = 99; // silenciosamente ignora
console.log(obj.x); // 42
// modo estrito
'use strict';
var obj = {};
Object.defineProperty(obj, 'x', { value: 42, writable: false });
obj.x = 99; // TypeError: Cannot assign to read only property 'x' of object
Outra diferença é a atribuição a propriedades de um objeto não extensível. No modo normal, a atribuição é ignorada; no modo estrito, lança um TypeError.
// modo normal
var obj = {};
Object.preventExtensions(obj);
obj.x = 1; // silenciosamente ignora
console.log(obj.x); // undefined
// modo estrito
'use strict';
var obj = {};
Object.preventExtensions(obj);
obj.x = 1; // TypeError: Cannot add property x, object is not extensible
Além disso, o modo estrito altera o comportamento de eval. No modo normal, eval pode introduzir variáveis no escopo circundante; no modo estrito, eval cria variáveis apenas no escopo do próprio eval, isolando o código avaliado. Isso evita vazamentos de escopo e problemas de segurança.
// modo normal
var x = 1;
eval('var y = 2;');
console.log(y); // 2 (y vaza para o escopo externo)
// modo estrito
'use strict';
var x = 1;
eval('var y = 2;');
console.log(y); // ReferenceError: y is not defined
Outra diferença importante é que, no modo estrito, os argumentos de uma função não são sincronizados com os parâmetros nomeados. No modo normal, alterar arguments[0] altera o valor do parâmetro correspondente e vice-versa; no modo estrito, eles são independentes.
// modo normal
function soma(a, b) {
arguments[0] = 10;
return a + b; // a agora é 10
}
console.log(soma(1, 2)); // 12
// modo estrito
'use strict';
function somaEstrito(a, b) {
arguments[0] = 10;
return a + b; // a continua 1
}
console.log(somaEstrito(1, 2)); // 3
Boas práticas
Para aproveitar ao máximo o modo estrito, é recomendável ativá-lo em todos os seus arquivos JavaScript. No entanto, ao trabalhar com código legado ou com bibliotecas que não estão preparadas, você pode ativá-lo apenas em funções específicas. Uma prática comum é envolver todo o conteúdo do arquivo em uma IIFE (Immediately Invoked Function Expression) e colocar 'use strict' no início, evitando que o modo estrito afete outros scripts concatenados.
(function() {
'use strict';
// seu código aqui
})();
Além disso, é importante lembrar que o modo estrito é ativado por padrão em módulos ES6 (quando usamos import/export) e em classes. Portanto, se você já usa módulos, o modo estrito é aplicado automaticamente, não precisando da diretiva explícita.
Em resumo, o modo estrito é uma ferramenta valiosa para evitar erros comuns, melhorar a segurança e preparar seu código para o futuro. Adotá-lo é um sinal de maturidade no desenvolvimento JavaScript.
Referências
- MDN: Modo estrito
- MDN: use strict
- ECMAScript 5.1 Specification - Strict Mode
- ECMAScript 2015 Specification - Strict Mode Code
- MDN: Transitioning to strict mode
- W3Schools: JavaScript Use Strict
Exercícios
- O que acontece quando você tenta atribuir um valor a uma variável não declarada em modo estrito? Explique e dê um exemplo de código.
ReferenceError. Exemplo: 'use strict';
x = 10; // ReferenceError: x is not definedundefined ao ser chamada sem um objeto receptor (ou seja, this deve ser undefined).'use strict';
function mostrarThis() {
return this;
}
console.log(mostrarThis()); // undefinedwith? Dê um exemplo.with é proibida e causa um erro de sintaxe. Exemplo: 'use strict';
var obj = { a: 1 };
with (obj) { // SyntaxError
console.log(a);
}arguments e os parâmetros nomeados no modo estrito. Dê um exemplo.arguments não são sincronizados com os parâmetros nomeados. Alterar arguments[0] não altera o parâmetro correspondente. Exemplo: 'use strict';
function soma(a, b) {
arguments[0] = 10;
return a + b; // a permanece o valor original
}
console.log(soma(1, 2)); // 3TypeError. Exemplo: 'use strict';
var obj = {};
Object.defineProperty(obj, 'x', { value: 42, writable: false });
obj.x = 99; // TypeError