ES6 中的 let 和 const

 目录

01.let 和 const 都是块级作用域。

02.let 和 const声明不存在变量提升,只能先声明再使用,否则会报错。

03.ES6中不允许重复声明,ES5允许

04.const 声明的是一个只读常量,再声明时就需要赋值。

05.let 与const 声明赋值问题

06. const有关知识

07.注意点:

08.案例


在 ES6 中通常用let 和 const 来声明let 表示变量、const 表示常量,ES5用var声明

 特点:

01.let 和 const 都是块级作用域。

以{ }代码块作为作用域范围 ,只能在代码块里面使用,而var声明的变量全局有效/局部(函数)内部有效.

<script>
    //{}括起来的代码块
    //let 和 const 都是块级作用域。以{ }代码块作为作用域范围 ,只能在代码块里面使用
    {
        let a = 0;
        console.log(a);   // 0
    }
    console.log(a);   // 报错 ReferenceError: a is not defined
</script>

<script>
    //var声明的变量全局有效/局部(函数)内部有效.
    {
        var a = 123;
        console.log(a,1111);  //123 1111
    }
    console.log(a,2222);      //123 2222
</script>

02.let 和 const声明不存在变量提升,只能先声明再使用,否则会报错。

在代码块内,在声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区

<script>
   //ES5中声明变量会提升
   console.log(a);      //undefined 
   var a = 666;

   //ES6中声明变量不会提升
   console.log(b);     //报错   在代码块内,在声明变量b之前,该变量b都是不可用的  所以报错
   let b = 1;   
</script>

03.ES6中不允许重复声明,ES5允许

<script>
    function test(){
        let a=1;
        let a=2;     //重复声明  报错
        console.log(a);
    }//报错
</script>

<script>
    //ES5可以重复声明
    var a = 1;  
    var a = 2;
    console.log(a);   //2
</script>

04.const 声明的是一个只读常量再声明时就需要赋值

(注意点:如果 const 声明的是一个对象,对象所包含的成员值是可以被修改的。抽象一点儿说,就是对象所指向的地址不能改变,而变量成员 是可以修改的。

const obj = {};  //对象是一块存储空间,
obj.age = 20;    //存储空间没变,修改其成员,并不改变存储空间的地址
console.log(obj);

05.let 与const 声明赋值问题

<script>
   //ES6中let可以声明不赋值
   let a;
   console.log(a);   //undefined
   //但是const声明常量时必须赋值
   // const b ;         //报错
   const b = 1;
   console.log(b);      //1
   //ES5中 var可以声明不赋值
   var c;
   console.log(c);      //undefined
</script>
<script>
    {
        let a = 10;
        let a= 20;   //报错 ,let不能在同一代码块作用域内重复声明同一个变量
    }
    //const也是如此
</script>
<script>
    let a = 20;   //用var 和 let 分别声明同一作用域的同一变量 a 也会报错
    var a = 10; 
</script>

预解析时:ES6中,let,const在预解析时会在所在代码块中{  }形成一个作用域(暂时性死区) ,但是其定义的变量不会提升

06. const有关知识

1.const声明的常量在声明时就必须要赋值,不能只声明不赋值

2.const声明的常量不能被修改,且只能初始化赋值一次。

3.当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING

4.常在项目中用于一些不变的量:比如说网址。。。。

<script>
    const a = 20;
    a = 30;        //报错
    console.log(a);
</script>
<script>
    const a;    //报错,必须要赋值
</script>

07.注意点:

  • let 和const 关键词声明的变量不具备变量提升(hoisting)特性

  • let 和 const 声明只在最靠近的一个代码块中(花括号内)有效

  • const 在声明时必须被赋值

  • const 如何做到变量在声明初始化之后不允许改变的?使用 const 声明复杂类型对象时要慎重。

08.案例

eg1:易错:要知道脚本运行初,在全局作用域先扫描关键字 var a;

<script>
    console.log(a);
    if(false){
        var a = 0;
    }
</script>

分析:if(false)不管if括号里面是false或者true,代码运行初,就会扫描到关键字 var a;进行提升,然后console.log(a);这里就会运行出undefined,不是报错哦。

eg2:分析下面代码

<script>
    let a = 90;
    if(true){
        console.log(a);    //let所在代码块,会形成一个暂时性死区,所以console.log(a);不能利用
        let a = 20;        //原型链去到外层作用域取到a = 90
    }
    console.log(a);
</script>

分析:进入if里面,因为里面有let,会把if(){代码块}形成一个作用域(相当于一个密闭空间"暂时性死区",运行期间,把let所在代码块封死),但是let声明的变量不会有提升效果,所以if里面的 console.log(a);就会报错,导致程序停止执行

<script>
    let a = 90;
    if(false){
        console.log(a);
        let a = 20;
    }
    console.log(a);
</script>

分析: 因为false判定为假,所以程序不执行if语句,就相当于 let a = 90;  console.log(a); 所以结果为90

//这是一段错误代码,分析为什么是错误的代码
<script>
    let a = 90;
    if(false){       //这里为false和true程序都是错的
        console.log(a);
        var a = 20;
    }
    console.log(a);
</script>

分析: 程序在预解析时,扫描到if语句里面的var a = 20; var声明的变量不会产生作用域,所以var a 属于全局变量并且要提升,相当于下面这种

<script>
    var a;
    let a = 90;
    .....
</script>

也就形成了用var 和 let 分别声明同一作用域的同一变量 会报错。

但如果是在不同作用域声明同一变量就不会报错:

<script> 
    //第一种情况
    var a = 90;
    if(true){
        let a = 20;
        console.log(a);   //20
    }
    console.log(a);      //90
</script>

<script>
    //第二种情况
    let a = 90;        //不同作用域,也不会报错
    if(true){
        let a = 20;
        console.log(a);   //20
    }
    console.log(a);      //90
</script>

eg3: 一道经典面试题:

    <script>
        for (var i = 0; i < 10; i++) {
            setTimeout(function () {
                console.log(i);
            }, i * 1000);
        }
    </script>

注解: setTimeout函数

setTimeout() 是属于 window 的方法,该方法用于在指定的毫秒数后调用函数或计算表达式。语法格式可以是以下两种

语法:

setTimeout(要执行的代码, 等待的毫秒数)

setTimeout(JavaScript 函数, 等待的毫秒数)

分析:一看到程序,不就一个简单的for循环嘛,结果不就为:0,1,2,3,4,5,6,7,8,9

嘛,但真实结果为:10、10、10、10、10、10、10、10、10、10 ,为什么呢?

深入分析这题:

结果为10个10的原因是for循环中使用setTimeout涉及到了异步机制。说到异步机制那就要说一下

JS的运行机制:

JS是单线程环境,也就是说代码的执行是从上到下,依次执行。也就是同一个时间只能做一件事。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。JavaScript将所有任务分成两种,一种是同步任务,另一种是异步任务同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。在所有同步任务执行完之前,任何的异步任务是不会执行的。
 

异步执行的运行机制如下:
1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
2. 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
4. 主线程不断重复上面的第三步。
主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会循环反复。

一般来说:有以下4种会放入异步任务队列:

setTimeout和setlnterval
DOM事件
ES6中的Promise
Ajax异步请求

现在来看这道面试题:

<script>
    for(var i=0;i<10;i++){
        setTimeout(function(){
         console.log(i);  
        },i*3000);
    }
</script>

 代码中的for循环是个同步任务setTimeout是个异步任务所以把for循环执行完毕后(i=10)才会执行异步任务setTimeout()函数,所以导致输出了10个10(间隔输出)的结果。

具体执行步骤如下:
1.for循环为同步任务,先执行产生了十个定时器。
(由于这里的for循环不是独立的代码块,声明的 i 为全局变量,遍历完成相当于全局环境i=10;)

这里理解:for循环,循环一次,
2.同步任务for遍历完了再执行异步任务的定时器。
(此时定时器运行环境与for循环同级,即在全局环境i=10下运行,因此输出10个10)
 

 画个草图(帮助理解,我感觉是这样),草图,草图,草图!!!

那么怎么才能输出正确答案0、1、2、3、4、5、6、7、8、9而不是连续的10个10呢?

分析:利用let声明的变量会使得所在代码块形成作用域 "暂时性死区"来做

<script>
    //就是把 var 改成 let 就是这么简单
    for(let i=0;i<10;i++){
        setTimeout(function(){
         console.log(i);  
        },i*1000);
    }
</script>

草图大概就是

这里输出 答案0、1、2、3、4、5、6、7、8、9还有其它方法,这里因为是主要讲let,所以只讲了一种。更多来自:

http://t.csdn.cn/PXMMS

本文很多内容也是借鉴该博主。 

笔试题: var ,let,const的区别? 

1.共同点:都是可以声明变量的。

2.区别:

01.var 具有变量提升的机制,let和const没有变量提升的机制

02.var 可以多次声明同一个变量,let和const不可以多次声明同一个变量(只能修饰一次)

03.var , let 声明变量,const声明常量,var和let声明的的变量可以再次赋值,但是const不可以再次赋值了。

<script>
    let a = 1;
    a = 2;
    console.log(a); //2

    const b = 3;
    b = 4;
    console.log(b);//Assignment to constant variable.(常量赋值)报错
</script>

注意点:如果const的是一个引用数据,里面的数据改了,但是引用地址没改,也不会报错 

<script>
    const obj = {
        a:1
    }
    obj.a = "123";
    console.log(obj);//{a: '123'}

    const arr = [1,2,3];
    arr[0] = "a";
    console.log(arr); //(3) ['a', 2, 3]
</script>

04. var 声明的变量没有自身作用域,let 和const声明的变量有自身的作用域("暂时性死区"),在该区域外面,访问不到该区域里面的数据。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值