跳到主要内容

语句和申明✅

let const var 区别

答案
特性/区别varletconst
作用域函数作用域块级作用域块级作用域
变量提升有,声明提升但不会初始化无,必须先声明后使用无,必须先声明后使用
暂时性死区(TDZ)
是否允许重复声明允许不允许不允许
是否必须初始化是,声明时必须赋值
是否可修改可以可以不可重新赋值(但对象属性可变)
是否绑定到全局对象是(全局var变量为window属性)
变量泄露循环变量可能泄露为全局变量不会不会

核心总结:

  • letconst 不存在变量提升,存在暂时性死区,不能重复声明。
  • const 声明常量,声明时必须初始化,且不可重新赋值,但对象属性可变。
  • var 声明的变量会绑定到全局对象(如 window),letconst 不会。
  • 作用域采用词法作用域,let/const 为块级,var 为函数级。

示例说明

// let-const-var.test.js
describe('var, let, const 基本特性与区别', () => {
  test('var 是函数作用域,let/const 是块级作用域', () => {
    if (true) {
      var a = 1
      const b = 2
      const c = 3
    }
    expect(a).toBe(1)
    expect(() => b).toThrow(ReferenceError)
    expect(() => c).toThrow(ReferenceError)
  })

  test('var 存在变量提升,let/const 不存在变量提升', () => {
    expect(a).toBeUndefined()
    var a = 10
    // TODO: 完善用例
  })

  test('var 允许重复声明,let/const 不允许', () => {
    var x = 1
    var x = 2
    expect(x).toBe(2)
  })

  test('const 声明时必须初始化,let/var 不需要', () => {
    let a
    let b
    expect(a).toBeUndefined()
    expect(b).toBeUndefined()
    // 注意该用例在 parser 阶段就会报错而不是运行时,所以通过 eval 来转换为运行时错误
    expect(() => {
      // eslint-disable-next-line no-undef
      throw eval('const c')
    }).toThrow(SyntaxError)
  })

  test('const 不可重新赋值,但对象属性可变', () => {
    const obj = { a: 1 }
    obj.a = 2
    expect(obj.a).toBe(2)

    const n = 5
    expect(() => {
      // eslint-disable-next-line no-const-assign
      n = 10
    }).toThrow(TypeError)
  })

  test.skip('var 声明的变量会绑定到全局对象,let/const 不会', () => {
    // TODO: 完善用例

  })

  test('for 循环中 var 变量可能泄露为全局变量,let/const 不会', () => {
    // TODO: 完善用例
  })

  test('let/const 采用词法作用域', () => {
    const a = 1
    {
      const a = 2
      expect(a).toBe(2)
    }
    expect(a).toBe(1)

    const b = 3
    {
      const b = 4
      expect(b).toBe(4)
    }
    expect(b).toBe(3)
  })
})

Open browser consoleTests

变量提升

答案

变量提升(Hoisting)是 JavaScript 中的一个重要概念,指的是变量和函数声明会在代码执行前被“提升”到当前作用域的顶部。这意味着你可以在声明之前访问变量或调用函数,但行为会因声明方式不同而异。JavaScript 在执行代码前,会先进行“预解析”阶段,把所有的变量声明(var)和函数声明提升到作用域顶部。这是因为 JS 采用了先解析后执行的机制,保证变量和函数在整个作用域内都可用。

  • var 声明的变量:只提升声明,不提升赋值。访问时值为 undefined
  • letconst 声明的变量:不会被提升(实际上会被提升但不会初始化),在声明前访问会报错(暂时性死区)。
  • 函数声明:整个函数会被提升,可以在声明前调用。
  • 函数表达式:如果用 var 声明,只提升变量名,不能提前调用。
console.log(a) // undefined
var a = 10

foo() // 输出 'hello'
function foo () {
console.log('hello')
}

console.log(b) // ReferenceError
const b = 20
  • 避免在声明前访问变量,尤其是 letconst,否则会报错。
  • 推荐先声明再使用,代码更清晰、可维护。
  • 理解提升机制有助于避免“意外的 undefined”或报错。

变量提升是 JS 预解析的结果,理解它有助于写出更健壮的代码。建议优先使用 letconst,减少因提升带来的困惑。

for...offor...infor 循环的区别简表

答案
循环类型适用对象遍历内容是否保证顺序常见用途
for数组、类数组等索引(可取值)固定次数、数组遍历
for...in对象、数组可枚举属性名对象属性遍历
for...of可迭代对象元素值数组、Set、Map等
  • for...of 适合遍历数组、字符串、Set、Map等可迭代对象的元素值。
  • for...in 适合遍历对象的可枚举属性(包括原型链上的)。
  • for 适合需要手动控制循环次数或按索引遍历数组的场景。

说一下 JS regexp 的常用方法

数字千分位

url 查询字段解码

48%