let、const和var的区别
                    Contents
                    
                
                
            变量提升
变量提升:
- 所有的声明都会提升到作用域的最顶上去。
 - 函数声明的优先级高于变量声明的优先级,并且函数声明和函数定义的部分一起被提升。
 
一个变量有三个操作,声明(提到作用域顶部),初始化(赋默认值),赋值(继续赋值)。
let const 和var三者都会存在变量提升
- 
let只是创建过程提升,初始化过程并没有提升,所以会产生暂时性死区。 - 
var的创建和初始化过程都提升了,所以在赋值前访问会得到undefined - 
function的创建、初始化、赋值都被提升了 
console.log(data1); //undefined
var data1 = 'var';
console.log(data2); //Uncaught ReferenceError: Cannot access 'data2' before initialization 
let data2 = 'let';
console.log(data3); //Uncaught ReferenceError: Cannot access 'data3' before initialization
const data3 = 'const';
声明
var声明变量可以重复声明,而let、const不可以重复声明。const声明之后必须赋值,否则会报错。const定义不可变的量,改变了就会报错。但是const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的
作用域
- 比如模块或者一个方法中声明的
var a=1,如果声明在模块中,则会默认挂载到window上;如果声明在方法中,则在方法内部任何地方都可以访问;如果声明在代码块里,则会提升到上一级作用域; - 而
let、const仅作用于块级作用域,仅在该块级内起作用。 
if(true){
  var color = "red"
}
console.log(color)  //'red'
if(true){
  let color = 'red'
}
console.log(color) //ReferenceError
在es5环境下实现const
function _const(key, value) {    
    const desc = {        
        value,        
        writable: false    
    }    
    Object.defineProperty(window, key, desc)
}
    
_const('obj', {a: 1})   //定义obj
obj.b = 2               //可以正常给obj的属性赋值
obj = {}                //抛出错误,提示对象read-only