# 变量声明

# 目录

  1. 基本概念
  2. 使用规范
  3. 代码示例
  4. 作用域对比

# 基本概念

# var声明

  • 函数作用域:变量在函数内部都可以访问
  • 变量提升:声明会被提升到函数或全局作用域顶部
  • 可重复声明:同一作用域内可以多次声明同名变量
  • 可重新赋值:声明后可以修改变量值

# let声明

  • 块级作用域:变量只在声明的代码块内有效
  • 暂时性死区:声明前不可访问(Temporal Dead Zone)
  • 不可重复声明:同一作用域内不能重复声明
  • 可重新赋值:声明后可以修改变量值

# const声明

  • 块级作用域:变量只在声明的代码块内有效
  • 暂时性死区:声明前不可访问
  • 不可重复声明:同一作用域内不能重复声明
  • 不可重新赋值:声明后不能修改绑定(但对象属性可修改)

# 使用规范

# 1. 优先级推荐

//推荐顺序:const > let > var
const PI = 3.14159;        // 优先使用const
let counter = 0;           //需要重新赋值时使用let
var globalVar = 'legacy'; // 仅在必要时使用var

# 2. 使用场景规范

# const 使用场景

-值(数字、字符串、布尔值)

  • 对象和数组引用(引用不可变,内容可变) -函数表达式 -循中的不变引用
# let 使用场景

-循计数器 -条变量 -需要重新赋值的变量

  • 临时计算变量
# var 使用场景

-全局变量(谨慎使用) -需要函数作用域的变量 -兼旧代码(遗留系统)

# 3.禁止使用的情况

//❌错误的用法
var x = 1;           // 使用let或const替代
let y; y = 2;        //直接声明并赋值
const z;             // const必须初始化

# 代码示例

# 基础声明示例

// var 示例
function varExample() {
    console.log('var声明前:', typeof undeclaredVar); // undefined
    var undeclaredVar = 'hello';
    console.log('var声明后:', undeclaredVar);         // hello
    
    if (true) {
        var blockVar = 'block';
    }
    console.log('块级外部访问:', blockVar); // block (函数作用域)
}

// let 示例
function letExample() {
    // console.log(tempVar); // ReferenceError: Cannot access 'tempVar' before initialization
    let tempVar = 'temp';
    console.log('let声明后:', tempVar);
    
    if (true) {
        let blockLet = 'block let';
        console.log('块级内部:', blockLet);
    }
    // console.log(blockLet); // ReferenceError: blockLet is not defined
}

// const 示例
function constExample() {
    const API_URL = 'https://api.example.com';
    // API_URL = 'new url'; // TypeError: Assignment to constant variable
    
    const config = { debug: true };
    config.debug = false; // 对象属性可以修改
    console.log(config);  // { debug: false }
    
    // config = {}; // TypeError: Assignment to constant variable
}

# 循环中的使用

// var 在循环中的问题
function varLoopProblem() {
    var callbacks = [];
    for (var i = 0; i < 3; i++) {
        callbacks.push(function() {
            console.log('var循环值:', i); //都是3
        });
    }
    callbacks.forEach(cb => cb()); // 输出: 3, 3, 3
}

// let 解决循环问题
function letLoopSolution() {
    let callbacks = [];
    for (let i = 0; i < 3; i++) {
        callbacks.push(function() {
            console.log('let循环值:', i); // 0, 1, 2
        });
    }
    callbacks.forEach(cb => cb()); // 输出: 0, 1, 2
}

// const 在循环中
function constLoop() {
    const items = ['a', 'b', 'c'];
    for (const item of items) {
        console.log('const循环项:', item);
    }
    // item = 'd'; // TypeError: Assignment to constant variable
}

# 实际应用场景

//配置对象 - 使用const
const APP_CONFIG = {
    version: '1.0.0',
    debug: true,
    apiUrl: 'https://api.example.com'
};

//计数器 - 使用let
function counterExample() {
    let count = 0;
    
    return {
        increment() {
            count++;
            return count;
        },
        decrement() {
            count--;
            return count;
        },
        getCount() {
            return count;
        }
    };
}

//条件变量 - 使用let
function processUserInput(input) {
    let result;
    
    if (input > 10) {
        result = 'large';
    } else if (input > 5) {
        result = 'medium';
    } else {
        result = 'small';
    }
    
    return result;
}

// 数组操作 - const引用
const numbers = [1, 2, 3, 4, 5];
numbers.push(6);        //可以修改数组内容
numbers[0] = 10;        // 可以修改元素
// numbers = [7, 8, 9]; //错误:不能重新赋值引用

# 作用域对比

# 作用域范围对比表

方式 全局作用域 函数作用域 块级作用域 暂时性死区 可重复声明
var
let
const

# 作用域示例

//全局作用域
var globalVar = 'global var';
let globalLet = 'global let';
const GLOBAL_CONST = 'global const';

function scopeDemo() {
    //函数作用域
    var functionVar = 'function var';
    let functionLet = 'function let';
    const FUNCTION_CONST = 'function const';
    
    if (true) {
        //块级作用域
        var blockVar = 'block var';      //函数作用域
        let blockLet = 'block let';      //块级作用域
        const BLOCK_CONST = 'block const'; //块级作用域
        
        console.log('块级内部访问:');
        console.log('var:', blockVar);
        console.log('let:', blockLet);
        console.log('const:', BLOCK_CONST);
    }
    
    console.log('函数作用域访问:');
    console.log('var:', blockVar);    // 可访问
    // console.log('let:', blockLet);   // ReferenceError
    // console.log('const:', BLOCK_CONST); // ReferenceError
}
本章目录