跳到主要内容

变量声明

var、let、const 的作用域与提升行为有何不同?​

关键字作用域提升行为重复声明全局绑定
var函数作用域提升声明并初始化为 undefined允许浏览器中挂到 window
let块作用域提升但不初始化, 访问抛 ReferenceError禁止不挂到 window
const块作用域同 let禁止不挂到 window
console.log(name); // undefined; var 已提升
var name = "Jake";

console.log(age); // ReferenceError; 暂时性死区
let age = 26;
  • 混合声明冲突: 同一作用域内 var 与 let 声明同名标识符均抛 SyntaxError, 冲突取决于作用域而非关键字;
  • 使用原则: 少用 var, 优先 const, 需要重新赋值时才用 let;

const 声明有什么限制与优势?​

  • 必须初始化: const 声明时就要给出值;
  • 绑定不可变: 不能重新赋值, 但对象内容仍可修改;
  • 优化空间: 常量更容易被引擎内联替换, 省去运行时查表;

标识符有哪些命名与保留字规则?​

  • 命名: 大小写敏感, 由字母、下划线、$、数字组成, 且不能以数字开头, 变量用小驼峰, 常量用大写加下划线;
  • 关键字: 如 break、class、const、function、typeof、var、with 等, 不能作为标识符;
  • 保留字: 如 enum、implements、interface、package、private、protected、public、static、let、await 等, 为未来语义保留;

循环中声明变量为什么推荐 let?​

  • var 版本: 整个循环共用一个变量, 回调异步执行时读到循环结束后的值;
  • let 版本: 每轮迭代创建新的绑定, 各回调引用不同变量;
  • const: 不能用作需要自增的循环迭代器;
for (var i = 0; i < 5; ++i) setTimeout(() => console.log(i), 0); // 5 5 5 5 5
for (let j = 0; j < 5; ++j) setTimeout(() => console.log(j), 0); // 0 1 2 3 4

同名变量与同名函数冲突时以谁为准?​

  • 同名变量: 后声明被忽略;
  • 同名函数: 后声明覆盖先声明;
  • 函数与变量同名: 函数提升早于变量, 但变量赋值会覆盖, 最终以赋值结果为准;
var a = undefined;
function a() {}
a(); // TypeError; 此时 a 已被赋值为 undefined

不声明就赋值会发生什么?​

  • 非严格模式: 自动成为全局对象属性 (浏览器为 window), 等价于隐式创建全局变量;
  • 严格模式: 直接抛错;
  • 结论: 始终显式声明变量;