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声明的变量全局有效/局部(函数)内部有效.



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

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

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




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

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

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

05.let 与const 声明赋值问题

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

06. const有关知识

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

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

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

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


07.注意点:

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

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

  • const 在声明时必须被赋值

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

08.案例

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

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

eg2:分析下面代码

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

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

//这是一段错误代码,分析为什么是错误的代码

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

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

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



eg3: 一道经典面试题:

    

注解: 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异步请求

现在来看这道面试题:


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

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

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

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

ES6 中的 let 和 const_第1张图片

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

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

草图大概就是

ES6 中的 let 和 const_第2张图片

这里输出 答案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不可以再次赋值了。

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

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

你可能感兴趣的:(es6,前端,javascript)