JavaScript

Como Usar Variáveis em JavaScript: var, let, const e Escopo em Produção

6 min de leitura

Como Usar Variáveis em JavaScript: var, let, const e Escopo em Produção

var: O Velho Paradigma (e Por Que Evitá-lo) A palavra-chave foi a forma original de declarar variáveis em JavaScript. Ela possui escopo de função (function scope) e não de bloco, o que cria comportamentos inesperados. Além disso, permite redeclaração na mesma função, tornando o código frágil em projetos grandes. Em produção, você encontrará apenas em código legado. Frameworks modernos e linters (como ESLint) desestimulam seu uso. A razão é simples: comportamentos erráticos levam a bugs difíceis de rastrear em aplicações complexas. let e const: O Padrão Moderno e introduzem block scope — a variável existe apenas dentro do bloco onde foi declarada. Essa é a mudança paradigmática que tornou JavaScript mais previsível. A diferença entre elas é crucial: permite reatribuição, não. Quando Usar let vs const Use como padrão. Ela deixa clara sua intenção de não reatribuir e força pensamento sobre estrutura de dados. Use apenas quando a reatribuição for necessária. Essa convenção reduz bugs em equipes grandes. Em um

<h2>var: O Velho Paradigma (e Por Que Evitá-lo)</h2>

<p>A palavra-chave <code>var</code> foi a forma original de declarar variáveis em JavaScript. Ela possui escopo de função (function scope) e não de bloco, o que cria comportamentos inesperados. Além disso, <code>var</code> permite redeclaração na mesma função, tornando o código frágil em projetos grandes.</p>

<pre><code class="language-javascript">function exemplo() {

if (true) {

var x = 10;

}

console.log(x); // 10 — x é acessível fora do if!

}

function redeclaracao() {

var contador = 0;

var contador = 1; // Sem erro, sobrescreve

console.log(contador); // 1

}</code></pre>

<p>Em produção, você encontrará <code>var</code> apenas em código legado. Frameworks modernos e linters (como ESLint) desestimulam seu uso. A razão é simples: comportamentos erráticos levam a bugs difíceis de rastrear em aplicações complexas.</p>

<h2>let e const: O Padrão Moderno</h2>

<p><code>let</code> e <code>const</code> introduzem block scope — a variável existe apenas dentro do bloco <code>{}</code> onde foi declarada. Essa é a mudança paradigmática que tornou JavaScript mais previsível. A diferença entre elas é crucial: <code>let</code> permite reatribuição, <code>const</code> não.</p>

<pre><code class="language-javascript">function escopo() {

if (true) {

let y = 20;

const z = 30;

}

console.log(y); // ReferenceError: y is not defined

console.log(z); // ReferenceError: z is not defined

}

// Exemplo prático em produção

const usuario = { nome: &quot;Ana&quot; };

usuario.nome = &quot;Bruno&quot;; // Funciona — mudamos propriedade

usuario = {}; // TypeError: Assignment to constant variable

let contador = 0;

contador = 1; // Funciona — let permite reatribuição</code></pre>

<h3>Quando Usar let vs const</h3>

<p>Use <code>const</code> como padrão. Ela deixa clara sua intenção de não reatribuir e força pensamento sobre estrutura de dados. Use <code>let</code> apenas quando a reatribuição for necessária. Essa convenção reduz bugs em equipes grandes. Em um projeto real, você espera ver 80% <code>const</code> e 20% <code>let</code>.</p>

<pre><code class="language-javascript">// Bom

const API_URL = &quot;https://api.exemplo.com&quot;;

const dados = fetch(API_URL);

let tentativas = 0;

// Evitar

let nome = &quot;João&quot;; // Deveria ser const se não reatribuir

const config = {}; // const não garante imutabilidade interna</code></pre>

<h2>Escopo em Profundidade: Closure e Contexto</h2>

<p>Escopo em JavaScript é hierárquico. Uma função interna acessa variáveis da função externa — isso é closure. Isso é poderoso, mas também é fonte de vazamento de memória se mal usado. Em produção, você precisa entender como o garbage collector interage com closures.</p>

<pre><code class="language-javascript">// Padrão comum: factory functions

function criarContador(inicio = 0) {

let valor = inicio; // Privada, não acessível externamente

return {

incrementar: () =&gt; ++valor,

obterValor: () =&gt; valor,

resetar: () =&gt; { valor = inicio; }

};

}

const contador1 = criarContador(10);

console.log(contador1.incrementar()); // 11

console.log(contador1.obterValor()); // 11

// valor não é acessível: contador1.valor == undefined

// Problema: vazamento de closure

function cacheComVazamento() {

const cache = [];

return function adicionarAoCache(item) {

cache.push(item); // cache cresce indefinidamente

};

}

const adicionar = cacheComVazamento();

// Se chamar 1 milhão de vezes, cache usa memória desnecessária</code></pre>

<h3>Escopo Global e Efeitos Colaterais</h3>

<p>Variáveis no escopo global (declaradas fora de funções) são acessíveis em qualquer lugar. Em produção, evite isso — causa acoplamento e torna testes impossíveis. Use módulos (ES6 modules) para encapsular.</p>

<pre><code class="language-javascript">// Evitar em produção

var estadoGlobal = { usuario: null }; // Acoplamento total

// Padrão correto com módulos

// arquivo: usuario.js

let estadoLocal = { usuario: null };

export function setUsuario(u) {

estadoLocal.usuario = u;

}

export function getUsuario() {

return estadoLocal.usuario;

}

// arquivo: main.js

import { setUsuario } from &#039;./usuario.js&#039;;

setUsuario({ id: 1, nome: &quot;Carlos&quot; });</code></pre>

<h2>Boas Práticas em Produção</h2>

<p>Em código profissional, você verá padrões estabelecidos. Primeiro: sempre declare variáveis no menor escopo possível. Segundo: use nomes descritivos — <code>const userData</code> é melhor que <code>const d</code>. Terceiro: combine com destructuring para código mais limpo.</p>

<pre><code class="language-javascript">// Destructuring reduz escopo desnecessário

const { nome, email } = usuario;

const [primeiro, segundo] = array;

// Cuidado com this em closures

const obj = {

valor: 100,

incrementar: function() {

const adicionar = (x) =&gt; this.valor + x; // Arrow function mantém this

return adicionar(5); // 105

}

};

// Object.freeze para pseudo-constância

const config = Object.freeze({

timeout: 5000,

retries: 3

});

// config.timeout = 10000; // Falha silenciosamente em non-strict mode</code></pre>

<p>Linters como ESLint forçam essas práticas. Configure no seu projeto para alertar sobre <code>var</code>, variáveis não utilizadas e escopos confusos. Isso economiza horas de debugging.</p>

<h2>Conclusão</h2>

<p>Domine três pontos essenciais: <strong>use <code>const</code> por padrão</strong>, prefira block scope natural de <code>let</code>/<code>const</code> em vez de function scope de <code>var</code>, e compreenda closures para evitar vazamento de memória. JavaScript moderno é mais seguro quando você respeita escopo. Em código de produção, essas práticas não são opcionais — são o diferencial entre sistemas mantíveis e pesadelos de manutenção.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Variables" target="_blank" rel="noopener noreferrer">MDN Web Docs: var, let, const</a></li>

<li><a href="https://262.ecma-international.org/" target="_blank" rel="noopener noreferrer">ECMAScript 2015 Specification</a></li>

<li><a href="https://javascript.info/closure" target="_blank" rel="noopener noreferrer">JavaScript.info: Variable Scope</a></li>

<li><a href="https://eloquentjavascript.net/03_functions.html" target="_blank" rel="noopener noreferrer">Eloquent JavaScript - Chapter 3: Binding and Scope</a></li>

<li><a href="https://google.github.io/styleguide/jsguide.html" target="_blank" rel="noopener noreferrer">Google JavaScript Style Guide</a></li>

</ul>

Comentários

Mais em JavaScript

Como Usar Tipos de Dados em JavaScript: Primitivos, Objetos e Coerção de Tipos em Produção
Como Usar Tipos de Dados em JavaScript: Primitivos, Objetos e Coerção de Tipos em Produção

Tipos Primitivos: A Base de Tudo Em JavaScript, existem sete tipos primitivos...

Como Usar Prototype Chain em JavaScript: Herança Baseada em Protótipos em Produção
Como Usar Prototype Chain em JavaScript: Herança Baseada em Protótipos em Produção

Entendendo o Prototype Chain O prototype chain é o mecanismo fundamental de h...

Como Usar Metaprogramação em JavaScript: Object.defineProperty e Decorators em Produção
Como Usar Metaprogramação em JavaScript: Object.defineProperty e Decorators em Produção

Object.defineProperty: Controle Fino sobre Propriedades Object.defineProperty...