Porque precisamos de modo restrito no JavaScript?

Converter erros para erros

Encorajar erros são convertidos em erros. Eram anteriormente aceites em modo não restritivo. O modo restrito restringe o uso de sintaxe de erro e não deixará o código correr com erros no lugar.

Torna difícil criar variáveis globais ao não nos deixar declarar variáveis com var, ou const, pelo que a criação de variáveis sem as declarar com essas palavras-chave não funcionará. Por exemplo, o seguinte código irá lançar um ReferenceError:

'use strict';
badVariable = 1;

Não podemos executar o código acima em modo estrito porque este código irá criar uma variável global badVariable se o modo estrito estiver desligado. O modo estrito impede isto para evitar a criação acidental de variáveis globais.

Qualquer código que falhe silenciosamente irá agora lançar uma excepção. Isto inclui qualquer sintaxe inválida que tenha sido ignorada silenciosamente antes.

Por exemplo, não podemos atribuir a variáveis apenas de leitura como argumentsNaN, ou eval com o modo estrito ligado.

Ainda atribuição a propriedades apenas de leitura como propriedades globais não escritas, atribuição de propriedades apenas de getter, e atribuição de coisas a propriedades em objectos não extensíveis lançará uma excepção em modo estrito.

Below são alguns exemplos de sintaxe que falharão com modo estrito em:

Todos os exemplos acima lançarão um TypeErrorundefined e Infinity são objectos globais não escrevíveis. obj é uma propriedade não escrevível.

obj2‘s foo a propriedade é apenas uma propriedade não escrevível e por isso não pode ser definida. fixedObj foi impedido de lhe adicionar mais propriedades com o Object.preventExtensions método.

Também, apagando propriedades não apagáveis, será lançada uma TypeError quando houver código a tentar fazê-lo. Por exemplo:

'use strict';
delete Array.prototype

Isto irá lançar um TypeError.

O modo restrito também desativa nomes de propriedades duplicadas num objecto antes de ES6 ser introduzido, pelo que o seguinte exemplo irá lançar um erro de sintaxe:

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

O modo restrito requer que os nomes de parâmetros de funções sejam únicos. Sem modo restrito, se dois parâmetros tiverem o nome um, então o definido mais tarde será aceite como valor do parâmetro quando os argumentos forem passados em.

Com modo restrito, não é mais permitido ter múltiplos parâmetros de função com o mesmo nome, por isso o exemplo seguinte não será executado com um erro de sintaxe:

const multiply = (x, x, y) => x*x*y;

Sintaxe octal também não é permitido em modo restrito. Não faz parte da especificação, mas é suportada em navegadores por prefixar números octais com um 0.

Isto confunde os programadores, pois alguns podem pensar que o 0 que precede o número não tem significado. Portanto, o modo estrito desativa esta sintaxe e irá lançar um erro de sintaxe.

O modo estrito também impede o uso de sintaxe que dificulta as optimizações. Precisa de saber que uma variável é realmente armazenada no local onde pensa estar armazenada antes de fazer optimizações, por isso temos de evitar o tipo de sintaxe que impede que as optimizações aconteçam.

Um exemplo disto é a declaração with. Se o utilizarmos, impede que o intérprete JavaScript saiba a que variável ou propriedade se refere, pois é possível ter uma variável com o mesmo nome dentro ou fora da declaração with.

se tivermos algo como o seguinte código:

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

Então, JavaScript não saberia se a declaração x dentro do with se referisse à variável x ou à propriedade de objobj.x.

pelo que a localização da memória de x é ambígua. Assim, o modo rigoroso impede que a declaração with seja utilizada. Se tivermos o modo strict como o seguinte:

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

Então o código acima terá um erro de sintaxe.

Outra coisa que o modo strict impede é a declaração de variáveis dentro de uma declaração eval.

Por exemplo, sem modo estrito, eval('let x') declararia a variável x no código. Isto permite às pessoas ocultar declarações de variáveis em strings que podem sobrepor-se à mesma declaração de variável que está fora da declaração eval.

Para evitar isto, o modo estrito desativa declarações de variáveis no argumento de string que passamos para uma declaração eval statement.

O modo estrito também proíbe a eliminação de nomes de variáveis simples, pelo que o seguinte irá lançar um erro de sintaxe:

'use strict';
let x;
delete x;