let 和 const

2019-04-11  本文已影响0人  CRJ997

作用域

在ES6之前,并没有块级作用域这种概念,有的只有函数作用域和全局作用域。然后变量的声明方式来讲,也就只有var。但是var 声明的变量由于存在变量提升这个机制,导致var声明的变量都会在整个作用域(整个函数作用域或者全局作用域)中可见。为了减少对作用域命名空间的污染和规避冲突,也就引入了let这个关键词。

//例如使用with把一个对象的作用域扩展到当前作用域时,相当于一个块级作用域
var a = 90;
var obj = {
    a:8;
    b:10;
};
with(obj){   //这一部分就类似于块级作用域
  console.log(a);  //这边的a覆盖外部的a定义
  console.log(b);
}
console.log(a);//外部无法访问obj内部的a

let 的使用

和var的用法相同,但是并不存在变量提升。也就是下面的代码会导致Reference error错误

console.log(a);// Uncaught ReferenceError: a is not defined  at index.html:9
let a = 9;

比较有用的用法:

  1. 使垃圾回收没有顾虑
    考虑下面的代码,这些代码包含在一个函数作用域中的话
function process(data){
     //do something
}
var someReallyBigData  = {....};
processs(someReallyBigData);
var btn = document.getElementById('myButton');
btn.addEventListener('click',function click(event){
     console.log('button clicked');
},false);

click函数的点击回调并不需要someReallyBigData变量,理论上来讲这意味着当process(...)执行完成后,在内存中占用大量空间的数据结构就可以被垃圾回收了。但是,由于click函数形成了一个覆盖整个作用域的闭包,因此JS引擎极有可能仍然保存着这个结构(取决于具体实现)

这时候可以这么做:
用{}把这个比较大的数据结构括起来,用let定义someReallyBigData:

function process(data){
     //do something
}
//这里声明块级作用域,就很显式的告诉垃圾回收机制,这个地方的内存在结束之后可以马上回收
{
    let someReallyBigData  = {....};
    processs(someReallyBigData);
}
var btn = document.getElementById('myButton');
btn.addEventListener('click',function click(event){
     console.log('button clicked');
},false);

垃圾回收机制也就没有顾虑了

  1. let 循环
    for循环中定义循环变量。
for(let i=0;i<10;i++){
   console.log(i);
}
console.log(i); //Reference Error

let在for循环中的作用:

 {
   let j;
   for(j=0; j<10;j++){
       let i=j;   //每个迭代都重新绑定
      console.log(i);
   }
}

说说const

  1. 首先const创建的也是块级变量
  2. 正如其名,常量

可以看看const定义和其ES5等效代码:

//ES6
const a = 10;

//ES5
Object.defineProperty(this,'a',{
     configurable:false,
     enumerable:true,
     writable: false,
     value: 10
}
上一篇 下一篇

猜你喜欢

热点阅读