ES6中let和const详解
let和var一样也是用来定义变量,不同之处在于let是块级作用域,只在所定义的块级作用域中生效,一个花括号便是一个块级作用域
{var a="我是var定义的";let b="我是let定义的"}
console.log(a); //我是var定义的
console.log(b); //b is not defined
可以看出let定义的变量在全局作用域内并没有生效
如果我们在全局作用域中定义,试一下看在函数或者流程控制语句中是否会输出
let a="我是let定义的"
var b=0;
while(b<5){b++;console.log(a)}//⑤我是let定义的变量
if(true){console.log(a)}//我是let定义的变量
我们发现这样可以输出
如果我们反向来一下呢
for(let i=0;i<5;i++){
let a="流程控制语句花括号中的let";
var b="流程控制语句花括号中的var";
console.log(i)}
//0,1,2,3,4
console.log(a);
//a is not defined
console.log(b);
//流程控制语句中的var
for(var j=0;j<1;j++){
console.log(j)}
//
console.log(j);
//
我们发现let定义的变量不会被提升,只要有块级括号存在,它就只在该块级中有意义
如果在函数中呢
function test(){console.log(a)}() //报错
我们发现并不能输出
我们可以得出结论,流程控制语句中的变量均属于全局变量,但是在流程控制语句中的括号中定义则为块级,不会提升为全局变量
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域
for(let i=0;i<3;i++){
let i="abc";
console.log(i)}
//abc,abc,abc
let在for循环声明的变量每一次循环的值都会被引擎内部记下,但是var声明的变量则会刷新覆盖掉上一次的值
var a=[];
for(var i=0;i<10;i++){
a[i]=function(){return i};}
console.log(a)//[f,f,f,f,f,f,f,f,f,f]
a.forEach((e)=>{console.log(e())})
//⑩10
我们可以看出,这种方式其实将未执行的函数push进数组了,当每次调用时候发现此刻的i早已经被循环覆盖掉,最终输出都为此刻的i值10
var a=[];
for(let i=0;i<10;i++){
a[i]=function(){return i};}
console.log(a)//[f,f,f,f,f,f,f,f,f,f]
a.forEach((e)=>{console.log(e())})
//0,1,2,3,4,5,6,7,8,9
但是对于let声明的变量,每一次引擎都会自动存储记录i的值,而不会覆盖掉,因此每次输出都是push当时的i值
let不存在变量提升,只有在定义后再使用才不会报错
console.log(a);var a=1;//undefined
console.log(b);let b=2;//报错
let具有强制性绑定变量的能力,原先var声明的变量,当被let重新声明的时候会被强制性绑定,原先var声明的所有被let所管辖的块级作用域里的变量均被let强制为自己声明的值,形成暂时性死区,let所处块级作用域中let声明之前的该变量均报错
var a=1;
{console.log(a);
let a=2;}
//a is not defined
var a=1;
{let a=2;
console.log(a);//
};
console.log(a)//
var a=1;
console.log(a);//
{let a=2;
console.log(a);//
};
let不允许在相同作用域内,重复声明同一个变量。
{var a=0;
let a=1;
console.log(a)}//报错
{let a=0;
var a=1;
console.log(a)}//报错
{
let a=2;
let a=3;
console.log(a)}//报错
{let a=2;
console.log(a);
let a=3;}//报错
上面的最后一个例子可以看出当再次声明该变量之前调用的变量都会炸掉
我们可以看到let声明的变量可以引用块级作用域外面的函数
let a=f();
function f(){
return 1
}
console.log(a)//
{let a=f();
console.log(a)//
function f(){
return 1
}
const声明的变量为永恒变量,不能更改,而且声明以后必须初始化
const a;//报错
const b=1;
b=2//报错
const的作用域与let命令相同:只在声明所在的块级作用域内有效。
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const声明的常量,也与let一样不可重复声明。
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。
const foo={};
foo.prop=123;
console.log(foo.prop)//
常量a是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错。
const a=[];
a.push(1);
console.log(a)//[1]
console.log(a.length)//
a=[]//报错
再来验证以下引用
var a=1;
b=a;
console.log(b);//
a=2;
console.log(b)//
b=3;
console.log(a)//
可以看出var定义的变量,b=a时候,是直接复制了一份a,并不是a的引用
let a=1;
b=a;
console.log(b);//
a=2;
console.log(b);//
b=3;
console.log(a);//
console.log(b);//
var b=4;
console.log(b)//
可以看出let也一样
const也是复制一份
const a=1;
b=a;
console.log(b);//
b=3;
console.log(a);//
console.log(b);//
var b=4;
console.log(b)//
ES6中let和const详解的更多相关文章
- JS ES6中export和import详解
1.Export 模块是独立的文件,该文件内部的所有的变量外部都无法获取.如果希望获取某个变量,必须通过export输出, // profile.js export var firstName = ' ...
- linux-2.6.26内核中ARM中断实现详解(转)
转载:http://www.cnblogs.com/leaven/archive/2010/08/06/1794293.html 更多文档参见:http://pan.baidu.com/s/1dDvJ ...
- 关于 redux-saga 中 take 使用方法详解
本文介绍了关于redux-saga中take使用方法详解,分享给大家,具体如下: 带来一个自己研究好久的API使用方法. redux-saga中effect中take这个API使用方式,用的多的是ca ...
- Postman中的Pre-request Scrip详解
Postman中的Pre-request Scrip详解 一.Pre-request Scrip的简介 1.Pre-request Script是在请求发送之前需要执行的代码片段: 2.请求参数中包含 ...
- C#中string.format用法详解
C#中string.format用法详解 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Form ...
- c++中vector的用法详解
c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...
- 011-Scala中的apply实战详解
011-Scala中的apply实战详解 object中的apply方法 class中的apply方法 使用方法 apply方法可以应用在类或者Object对象中 class类 必须要创建实例化的类对 ...
- C# WinForm 中 MessageBox的使用详解
1.C# WinForm 中 MessageBox的使用详解:http://www.cnblogs.com/bq-blog/archive/2012/07/27/2611810.html
- JScript中的条件注释详解(转载自网络)
JScript中的条件注释详解-转载 这篇文章主要介绍了JScript中的条件注释详解,本文讲解了@cc_on.@if.@set.@_win32.@_win16.@_mac等条件注释语句及可用于条件编 ...
随机推荐
- STOMP协议规范【转】
STOMP协议规范英文原文:http://stomp.github.io/stomp-specification-1.2.html STOMP协议规范译文原文:http://simlegate.com ...
- MongoDB开启安全认证
MongoDB开启安全认证 注意 对MongoDB部署启用访问控制会强制执行身份验证,要求用户识别自己.当访问启用了访问控制的MongoDB部署时,用户只能执行由其角色确定的操作. 启用访问控制后,请 ...
- HDU 4828 逆元+catalan数
Grids Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Subm ...
- UVA-10917 Walk Through the Forest (dijkstra+DP)
题目大意:n个点,m条边的无向图.一个人从起点到终点按照下面的走法:从A走向B当A到终点的最小距离比B到终点的最小距离大时.问从起点到终点有多少路径方案. 题目分析:先用dijkstra预处理出终点到 ...
- SPOJ 694 && SPOJ 705 (不重复子串个数:后缀数组)
题意 给定一个字符串,求它的所有不重复子串的个数 思路 一个字符串的子串都必然是它的某个后缀的前缀.对于每一个sa[i]后缀,它的起始位置sa[i],那么它最多能得到该后缀长度个子串(n-sa[i]个 ...
- IOS-UIButton的文本与图片的布局
UIButton内部文本和图片的布局是我们日常代码中,不可缺少的部分,按钮默认左边图片右边文本,那要实现左边文本,右边图片,我们该怎么解决呢,上面图片,下面文本又该怎么办呢 其实很简单,今天总结下,目 ...
- BZOJ2259 [Oibh]新型计算机
话说hzwer你在坑爹?... 我按照你的建图交了上去,发现WA. 开始检查= =...过了好久,突然觉得画风不对...hzwer您建图错了啊!!! 后来看了看zky的终于知道了怎么回事>_&l ...
- 014——数组(十四)array_reduce array_slice array_splice array_sum
<?php /** */ //array_reduce()递归的用回调函数递归的对数组元素进行处理,返回处理后的值 /*$arr=array(1,2,3,4,5); function func( ...
- hdu 6040 Hints of sd0061(stl: nth_element(arr,arr+k,arr+n))
Hints of sd0061 Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- zoj 2966 Build The Electric System(最小生成树)
Build The Electric System Time Limit: 2 Seconds Memory Limit: 65536 KB In last winter, there wa ...