- 定义变量声明语法var upperA = ‘A’;let upperB = ‘B’;const upperC = ‘C’;只声明不初始化的结果,【const定义的常量不可以修改,而且必须初始化。】// var 声明变量var upperA;console.log(‘打印大写的A:%s’, upperA);// 结果:打印大写的A:undefined// let 声明变量var upperB;console.log(‘打印大写的B:%s’, upperB);// 结果:打印大写的B:undefined// const 声明常量const upperC;console.log(‘打印大写的C:%s’, upperC);// 错误:SyntaxError: Missing initializer in const declaration声明后值是否可修改,【const定义的常量不可以修改,而且必须初始化。】// var 声明变量初始化并修改值var upperA = ‘A’;console.log(‘打印upperA:%s’, upperA);// 结果:打印upperA:AupperA = ‘LetterA’;console.log(‘打印upperA:%s’, upperA);// 结果:打印upperA:LetterA// let 声明变量初始化并修改值var upperB = ‘B’;console.log(‘打印大写的B:%s’, upperB);// 结果:打印upperB:BupperB = ‘LetterB’;console.log(‘打印大写的B:%s’, upperB);// 结果:打印upperB:LetterB// const 声明常量初始化并修改值const upperC = ‘C’;console.log(‘打印upperC:%s’, upperC);// 结果:打印upperC:CupperC = ‘LetterC’;console.log(‘打印upperC:%s’, upperC);// 错误:TypeError: Assignment to constant variable.2. 变量提升浏览器在运行代码之前会进行预解析,首先解析函数声明,定义变量,解析完之后再对函数、变量进行运行、赋值等不论var声明的变量处于当前作用域的第几行,都会提升到作用域的头部。 var 声明的变量会被提升到作用域的顶部并初始化为undefined,而let声明的变量不会被提升到作用域的顶部。console.log(‘打印upperA:%s’, upperA);// 结果:打印upperA:undefinedconsole.log(‘打印upperB:%s’, upperB);// 错误:ReferenceError: upperB is not definedvar upperA = ‘A’;let upperB = ‘B’;3. 是否允许重复声明同一个变量** var允许在相同作用域内,重复声明同一个变量,后面声明的变量会覆盖前面声明的变量。** let不允许在相同作用域内,重复声明同一个变量。var upperA = ‘A’;let upperB = ‘B’;// 重复声明var upperA = ‘LetterA’;let upperB = ‘LetterB’;console.log(‘打印upperA:%s’, upperA);console.log(‘打印upperB:%s’, upperB)// 错误:SyntaxError: Identifier ‘upperB’ has already been declared4. 作用域在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围。// ———- 例如: ———-{ var upperA = ‘A’;}console.log(‘打印upperA:%s’, upperA);# 结果: 打印upperA:A// ———- ES6新增的let,可以声明块级作用域的变量。———-{ let upperB = ‘B’;}console.log(‘打印upperB:%s’, upperB);// 错误: ReferenceError: upperB is not defined5. let配合for循环的独特应用let非常适合用于 for循环内部的块级作用域。** JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。// ———- 看一个常见的面试题目: ———-for (var i = 0; i <10; i++) { setTimeout(function() { // 同步注册回调函数到 异步的 宏任务队列。 console.log(i); // 执行此代码时,同步代码for循环已经执行完成 }, 0);}// 输出结果:10 共10个// 这里面的知识点: JS的事件循环机制,setTimeout的机制等// ———- 如果把 var改成 let声明:———-// i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。for (let i = 0; i < 10; i++) { setTimeout(function() { console.log(i); // i 是循环体内局部作用域,不受外界影响。 }, 0);}// 输出结果:0 1 2 3 4 5 6 7 8 9