본문으로 건너뛰기 JavaScript Variables and Data Types | let· const

JavaScript Variables and Data Types | let· const

JavaScript Variables and Data Types | let· const

이 글의 핵심

Deep dive into JavaScript variables: let, const, var, scope, hoisting, primitives, type coercion, and common mistakes—with runnable examples.

Introduction

What is a variable?

A variable is a named place to store data. JavaScript is a dynamically typed language: a variable’s “type” is determined by the value it holds.

1. Declarations: let, const, var

let: reassignment allowed

let age = 25;
console.log(age);  // 25
age = 26;  // reassignment OK
console.log(age);  // 26
// Declare now, assign later
let name;
console.log(name);  // undefined
name = "Alice";
console.log(name);  // Alice

const: no reassignment

const declares a constant binding; you cannot reassign it:

const PI = 3.14159;
console.log(PI);  // 3.14159
// Reassignment throws
// PI = 3.14;  // TypeError: Assignment to constant variable
// Must initialize at declaration
// const x;  // SyntaxError: Missing initializer in const declaration
// Important: object/array *contents* can still change
const person = { name: "Alice", age: 25 };
// The binding `person` cannot be reassigned
// But properties can change
person.age = 26;  // ✅ OK (mutate object contents)
console.log(person);  // { name: 'Alice', age: 26 }
// person = {};  // ❌ TypeError (rebinding not allowed)
const arr = [1, 2, 3];
// The binding `arr` cannot be reassigned
// Elements can change
arr.push(4);  // ✅ OK
console.log(arr);  // [1, 2, 3, 4]
arr[0] = 10;  // ✅ OK
console.log(arr);  // [10, 2, 3, 4]
// arr = [];  // ❌ TypeError

What const really means:

// const fixes the *reference* the variable holds
// The referenced object’s contents can still change
const obj = { x: 1 };
// obj points at a specific object in memory
obj.x = 2;  // ✅ mutate contents (same reference)
// obj = { x: 2 };  // ❌ new object (new reference)

Deep immutability:

// Object.freeze(): shallow freeze
const person = Object.freeze({ name: "Alice", age: 25 });
// person.age = 26;  // ignored (strict mode throws)
console.log(person.age);  // 25
// Nested objects are not frozen automatically
const user = Object.freeze({
    name: "Alice",
    address: { city: "Seoul" }  // inner object not frozen
});
user.address.city = "Busan";  // ✅ still mutates nested object
console.log(user.address.city);  // Busan
var x = 10;
var x = 20;  // redeclaration allowed (problematic!)
console.log(x);  // 20
// Function scope (ignores block scope)
if (true) {
    var y = 30;
}
console.log(y);  // 30 (accessible outside the block!)
// Hoisting surprise
console.log(z);  // undefined (not an error!)
var z = 40;

let vs const vs var

letconstvar
Reassignment
Redeclare (same scope)
ScopeBlockBlockFunction
HoistingTDZTDZundefined
Recommended
TDZ (Temporal Dead Zone): accessing before declaration throws ReferenceError.
// let/const: TDZ
// console.log(x);  // ReferenceError
let x = 10;
// var: hoisted as undefined
console.log(y);  // undefined
var y = 20;

2. Scope

Block scope

let and const are block-scoped:

{
    let x = 10;
    const y = 20;
    console.log(x, y);  // 10 20
}
// console.log(x);  // ReferenceError
// console.log(y);  // ReferenceError
if (true) {
    let z = 30;
    console.log(z);  // 30
}
// console.log(z);  // ReferenceError
for (let i = 0; i < 3; i++) {
    console.log(i);  // 0 1 2
}
// console.log(i);  // ReferenceError
// Nested blocks
{
    let x = 10;
    {
        let x = 20;  // shadowing
        console.log(x);  // 20
    }
    console.log(x);  // 10
}
// Closures in loops: let creates a new binding per iteration
for (let i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log(i);  // 0 1 2
    }, 100);
}
// With var, one shared binding
for (var j = 0; j < 3; j++) {
    setTimeout(() => {
        console.log(j);  // 3 3 3
    }, 100);
}

Benefits of block scope:

  1. Fewer accidental collisions
  2. Variables can be collected when the block ends
  3. Clearer lifetime
  4. Safer with closures in loops

Function scope

function test() {
    let x = 10;
    var y = 20;
    if (true) {
        let x = 30;  // new block-scoped x
        var y = 40;  // same function-scoped y
        console.log(x, y);  // 30 40
    }
    console.log(x, y);  // 10 40
}
test();

Global scope

let globalVar = "global";
function test() {
    console.log(globalVar);
}
test();
// Browser: window
// var global = "test";
// console.log(window.global);
// Node.js: global
// global.myVar = "test";

3. Data types

Primitive types

JavaScript has seven primitive types.

1. Number

let integer = 42;
let float = 3.14;
let negative = -10;
let inf = Infinity;
let negInf = -Infinity;
let notANumber = NaN;
console.log(10 / 0);  // Infinity
console.log("abc" / 2);  // NaN
console.log(isNaN(NaN));  // true
console.log(isNaN(10));   // false
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MIN_SAFE_INTEGER);

2. String

let str1 = "double quotes";
let str2 = 'single quotes';
let str3 = `template literal`;
let name = "Alice";
let age = 25;
let message = `Hello, ${name}! You are ${age}.`;
console.log(message);
let multiline = `line one
line two
line three`;
let escaped = "He said \"Hello\"";
console.log(escaped);

3. Boolean

let isTrue = true;
let isFalse = false;
console.log(10 > 5);   // true
console.log(10 === 5); // false

4. undefined

let x;
console.log(x);  // undefined
console.log(typeof x);  // undefined
function test() {
    // no return
}
console.log(test());  // undefined

5. null

let empty = null;
console.log(empty);  // null
console.log(typeof empty);  // "object" (historical quirk)
let x;           // undefined (declared only)
let y = null;    // explicit empty

6. Symbol (ES6+)

let sym1 = Symbol("description");
let sym2 = Symbol("description");
console.log(sym1 === sym2);  // false (always unique)
let obj = {
    [sym1]: "value1"
};
console.log(obj[sym1]);  // value1

7. BigInt (ES2020+)

let bigNum = 9007199254740991n;
let bigNum2 = BigInt("9007199254740991");
console.log(bigNum + 1n);
// Cannot mix with Number without conversion
// console.log(bigNum + 1);  // TypeError
console.log(bigNum + BigInt(1));  // OK

Reference types

Object

let person = {
    name: "Alice",
    age: 25,
    greet: function() {
        console.log(`Hello, I'm ${this.name}.`);
    }
};
console.log(person.name);
person.greet();

Array

let numbers = [1, 2, 3, 4, 5];
let mixed = [1, "hello", true, null, { name: "Alice" }];
console.log(numbers[0]);
console.log(numbers.length);

Function

function add(a, b) {
    return a + b;
}
console.log(typeof add);  // function

4. Type checks and conversion

typeof

console.log(typeof 42);         // number
console.log(typeof "hello");    // string
console.log(typeof true);       // boolean
console.log(typeof undefined);  // undefined
console.log(typeof null);       // object (quirk)
console.log(typeof {});         // object
console.log(typeof []);         // object
console.log(typeof function(){}); // function
console.log(Array.isArray([]));  // true
console.log(Array.isArray({}));  // false

Coercion

To string

let num = 42;
let str = String(num);
console.log(str, typeof str);
let str2 = num.toString();
let result = 42 + " apples";
console.log(result);

To number

let str = "42";
let num = Number(str);
console.log(parseInt("42px"));
console.log(parseFloat("3.14abc"));
console.log(parseInt("abc"));  // NaN
console.log("42" - 10);
console.log("42" * 2);
console.log(+"42");

To boolean

console.log(Boolean(1));
console.log(Boolean(0));
console.log(Boolean("hello"));
console.log(Boolean(""));
// Falsy values
console.log(Boolean(false));
console.log(Boolean(0));
console.log(Boolean(""));
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(NaN));
// Truthy
console.log(Boolean(1));
console.log(Boolean("hello"));
console.log(Boolean([]));
console.log(Boolean({}));
if ("hello") {
    console.log("Truthy!");
}

5. Hoisting

What is hoisting?

Hoisting means declarations are conceptually moved to the top of their scope (behavior differs for var, let/const, and functions).

var hoisting

console.log(x);  // undefined
var x = 10;
console.log(x);  // 10
// Conceptually similar to:
var x;
console.log(x);
x = 10;
console.log(x);

let/const and the TDZ

// console.log(x);  // ReferenceError (TDZ)
let x = 10;
// console.log(y);  // ReferenceError
const y = 20;

Function hoisting

greet();  // works (function declaration hoisted)
function greet() {
    console.log("Hello!");
}
// sayHello();  // ReferenceError (function expression not hoisted)
const sayHello = function() {
    console.log("Hello!");
};
sayHello();

6. Practical examples

Example 1: swapping variables

let a = 10;
let b = 20;
let temp = a;
a = b;
b = temp;
console.log(a, b);  // 20 10
let x = 10;
let y = 20;
[x, y] = [y, x];
console.log(x, y);  // 20 10

Example 2: a small getType helper

function getType(value) {
    if (value === null) return "null";
    if (Array.isArray(value)) return "array";
    return typeof value;
}

Example 3: safe integer parsing

function safeParseInt(value, defaultValue = 0) {
    const parsed = parseInt(value);
    return isNaN(parsed) ? defaultValue : parsed;
}

Example 4: config and immutability

const config = {
    apiUrl: "https://api.example.com",
    timeout: 5000
};
config.timeout = 10000;  // OK (mutate object)
const frozenConfig = Object.freeze({
    apiUrl: "https://api.example.com",
    timeout: 5000
});
const user = Object.freeze({
    name: "Alice",
    address: { city: "Seoul" }
});
user.address.city = "Busan";  // nested still mutable
function deepFreeze(obj) {
    Object.freeze(obj);
    Object.keys(obj).forEach(key => {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            deepFreeze(obj[key]);
        }
    });
    return obj;
}

7. Common mistakes

Mistake 1: using var in loops

for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 100);
}
for (let i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 100);
}

Mistake 2: misunderstanding const

const arr = [1, 2, 3];
arr.push(4);
arr[0] = 100;

Mistake 3: == vs ===

console.log(5 == "5");
console.log(5 === "5");

Mistake 4: accidental string concatenation

console.log("10" + 20);
console.log(Number("10") + 20);

Mistake 5: leaking globals

// count = 0;  // creates global in sloppy mode — avoid
let count = 0;
function increment() {
    count++;
}

8. Practical tips

Tip 1: const by default

const API_URL = "https://api.example.com";
let retryCount = 0;

Tip 2: meaningful names

let userAge = 25;
let scores = [1, 2, 3];
const MAX_USERS = 100;

Tip 3: strict mode

"use strict";
// x = 10;  // ReferenceError

9. Exercises

Exercise 1: rotate three variables

let a = 1;
let b = 2;
let c = 3;
[a, b, c] = [c, a, b];
console.log(a, b, c);  // 3 1 2

Exercise 2: toNumber

function toNumber(value, defaultValue = 0) {
    const num = Number(value);
    return isNaN(num) ? defaultValue : num;
}

Exercise 3: remove falsy values

function removeFalsy(arr) {
    return arr.filter(Boolean);
}

Summary

Key points

  1. Declarations: const default, let when rebinding, avoid var in new code.
  2. Scope: block scope for let/const, function scope for var.
  3. Types: seven primitives plus objects, arrays, functions.
  4. Coercion: prefer explicit Number/String/Boolean when unclear.
  5. Hoisting: var initializes as undefined; let/const use TDZ.

Best practices

  1. Use const, then let.
  2. Prefer === over ==.
  3. Use "use strict".
  4. Prefer descriptive names.
  5. Minimize globals.

Next steps



Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. Deep dive into JavaScript variables: let, const, var, scope, hoisting, primitives, type coercion, and common mistakes—wi…

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the JavaScript series index for the full picture.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers JavaScript, Variables, let, const, var, Data Types, Hoisting.