1. let声明的变量只在它所在的代码块有效

{ let a = 10; 3 var b = 1; 4 } 5 a // ReferenceError: a is not defined.  6 b // 1 

for(var i=0; i<10; i++){ a[i]=function(){ console.log(i); } } a[6](); //10 比较 var a=[]; for(let i=0;i<10;i++){ a[i]=function(){ console.log(i); } } a[6]() let 生成6个作用域 每个作用域有各自的i 和全局作用域,,,而var 声明的 只有全局作用域和各自的函数作用域
 

2.var“变量提升”现象是变量在申明前使用,会返回underfined。let不像那样会发生“变量提升”现象。所以变量一定要在声明后使用,否则报错。

3.在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。

4 .暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

function test(x = y, y = 2) {  
  return [x, y];  
}  
test(); // 报错  

  

function test(x = 2, y = x) {  
  return [x, y];  
}  
test();   // [2, 2]  

  ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是全局对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。也就是说,从ES6开始,全局变量将逐步与全局对象的属性脱钩

var a = 1;  
// 如果在Node的REPL环境,可以写成global.a  
// 或者采用通用方法,写成this.a  
window.a // 1  
  
let b = 1;  
window.b // undefined  

 下面是一个将对象彻底冻结的函数

var constantize = (obj) => {  
  Object.freeze(obj);  
  Object.keys(obj).forEach( (key, value) => {  
    if ( typeof obj[key] === 'object' ) {  
      constantize( obj[key] );  
    }  
  });  
};  

  

const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。

 

const foo = {};  
foo.prop = 123;  
foo.prop  
// 123  
foo = {};     // TypeError: "foo" is read-only  

  考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

// 函数声明语句  
{  
  let a = 'secret';  
  function f() {  
    return a;  
  }  
}  
// 函数表达式  
{  
  let a = 'secret';  
  let f = function () {  
    return a;  
  };  
} 

  

 ES5只有两种声明变量的方法:var命令和function命令。ES6除了添加letconst命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6一共有6种声明变量的方法。

补充整理:

对于let 和 const 最大的好处就是避免了可能的运行时错误, 不过也有直观的好处:

  • 用块(Blocks)替换立即执行函数(IIFEs)
  • 定义循环变量不会外泄
  • 循环定义函数可以不用闭包了
  • 可以放心的在 if 等条件中定义函数
posted on 2018-01-18 15:50  海米柚  阅读(109)  评论(1编辑  收藏  举报