for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
VM296:3 abc

1、因为let申明的变量只在他的代码块有效 所以,不会报错  for循环里面的 i 和for循环的 i 不是同一个 i

2、let不存在变量提前 但是很奇怪的是在代码块内,使用let命令声明变量之前,该变量都是不可用的。语法上都成为“暂时性死区”(temporal dead zone,简称 TDZ)。

所以搞笑的是typeof也不是一个百分之一百安全的操作

typeof x; // ReferenceError
let x;

3、let不允许在同一个相同的作用域内,重复声明一个变量。

let c=10;
var c=1;
或者
var c=10;
let c=1;
或者
let c=10;
let c=1;

都会报错

(function () {
  var tmp = ...;
  ...
}());   //es5块级作用域的写法

// 块级作用域写法
{
  let tmp = ...;
  ...
}

const 作用域和let相同  只是const一旦声明变量不得改变值;

const也存在暂时性死区,只能在声明的位置后面使用。

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

const a = [];
a.push('Hello'); // 可执行
a.length = 0;    // 可执行
a = ['Dave'];    // 报错

4 const 和 let声明的变量不会添加到全局对象上。

let b = 1;
window.b // undefined

const b = 1;
window.b // undefined