名词:
identifier 标识符

var

  1. var a; // 未初始化则为undefined
  2. /* var作用域在函数块内 function scope */
  3. function test() {
  4. var message = "hi"; // local variable
  5. }
  6. test();
  7. console.log(message); // error!
  8. /* 不用var声明的是全局变量,不推荐使用 */
  9. function test() {
  10. message = "hi"; // global variable
  11. }
  12. test();
  13. console.log(message); // "hi"
  14. /* var变量提升 Declaration Hoisting */
  15. console.log(age); // undefined
  16. var age = 26;
  17. /* var可重复声明 */
  18. var age = 16;
  19. var age = 26;
  20. var age = 36;
  21. console.log(age);

let

  1. /* let 是块级作用域 block scoped */
  2. if (true) {
  3. let age = 26;
  4. console.log(age); // 26
  5. }
  6. console.log(age); // ReferenceError: age is not defined
  7. /* let 不可重复声明 */
  8. let age;
  9. let age; // SyntaxError; identifier 'age' has already been declared
  10. /* let 没有变量提升 */
  11. /* 混合使用 */
  12. let name = "a"
  13. var name = "b" // Identifier 'name' has already been declared 因为var有变量提升

全局声明

声明全局变量时,var会把变量挂到window对象上,let不会

  1. var name = 'Matt';
  2. console.log(window.name); // 'Matt'
  3. let age = 26;
  4. console.log(window.age); // undefined

let 在for循环

  1. for (var i = 0; i < 5; ++i) {
  2. setTimeout(() => console.log(i), 0)
  3. }
  4. // 5 5 5 5 5

var声明的是同一个变量,for循环结束后,setTimeout里的函数传入的是同一个 i

  1. for (let i = 0; i < 5; ++i) {
  2. setTimeout(() => console.log(i), 0)
  3. }
  4. // console.logs 0, 1, 2, 3, 4

用let,每次for循环都会声明一个新的变量,每个setTimeout调用的都是对应的块里的i

const

  1. /* const声明必须初始化赋值 */
  2. const age = 26;
  3. /* const声明的变量不能修改赋值 */
  4. /* const和let一样是块级作用域 */
  5. /* const声明的变量不会挂到window上 */
  6. /* 用const声明一个对象,并修改其属性是可以的 */
  7. const person = {};
  8. person.name = 'Matt';
  9. /* 不能用const声明for循环里的迭代器iterator */
  10. for (const i = 0; i < 10; ++i) {}
  11. /* 不会改值的for循环是可以的 */
  12. for (const key in {a: 1, b: 2}) {
  13. console.log(key);
  14. }

总结

  1. 不要用var
  2. const 优于 let