ES6的let和const命令
刚开始学习es6,心里有点方,因为看了前言,感觉要用什么bebal来翻译成es5的代码,才能在各个平台上兼容运行,还有node各种运行环境。
不过自己也去百度了一些,发现还是有一丢丢的困难。
言归正传吧!开始来了解es6的神奇之处有哪些吧!
一.let命令
let这个命令,是es6新增的,用来声明变量的,和var用法类似,但是要注意的是,用这个声明的变量只有在let命令所在的代码块有效。
代码块
var a = [];
for(let i = 0;i < 10;i++){
a[i] = function(){
console.log(i);
}
}

var a = [];
for(var i = 0;i < 10;i++){
a[i] = function(){
console.log(i);
}
}

var和let命令对比而言,var声明的a是全局变量,在全局范围内都有效,而循环内的被赋值给数组a的function在运行时,都会通过闭包读到这同一个变量,导致最后输出的是最后一轮的值,也就是10。
而let命令声明的变量只在块级作用域中有效,所以输出的值是6.
上面代码中,i是let声明的,所以只在本轮循环中有效,所以每一次循环的i都是一个全新的变量,还有javascript引擎内部会记住上一轮循环的值,在初始化本轮i的值时,是在上一轮的值上面计算的。
for循环还有一个特别之处就是:循环语句部分是一个父级作用域,而在循环体内部是一个子作用域。
for(let i = 0; i < 3 ;i++){
let i = 'abc';
console.log(i);
}
//abc
//abc
//abc
1.不存在变量提升
var命令总是会发生“变量提升”的现象,即变量可以在声明之前使用,值为undefined,但是let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
2.暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再接受外部的影响。
var tmp = 123;
if(true){
tmp = 'abc';
let tmp;
}
上面的代码,存在全局变量tmp,但在块级作用域中又声明了局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
ES6明确规定,如果区块中存在let和const命令,这个区块会对这些命令声明的变量,从一开始就形成了封闭作用域,凡事在声明之前就使用这些变量,会报错的。
还有在没有let之前,typeof运算符是百分之百安全,永远不会报错。
注意,隐蔽的死区
function(x=y,y=2){
return [x,y];
}
bar();//报错
上面的代码报错,是因为y并没有声明,然后就被赋值给x。
let x = x;这一句在var里面就不会出错,但是用let声明就会报错,因为在使用let声明变量时,只要变量还没有声明完成前就使用,就会报错。
3.不允许重复说明
let不允许在相同作用域内,重复声明同一个变量。
//报错
function(){
let a = 10;
var a = 1;
}
//报错
function(){
let a = 10;
let a = 1;
}
function func(arg){
let arg;//报错
}
function func(arg){
{
let arg;//不报错
}
}
二、块级作用域
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景:内层变量可能会覆盖外层变量
在ES6之前,js没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域,变量提升即将变量提升到它所在作用域的最开始的地方。
a.变量声明
javascript会自动将变量声明“提升”到代码块的头部
if(!o){
var o = {};
}
//等同于
var o;
if(!o){
o = {};
}
//还有尽量将
for(var i ...){...}
//写成
var i;
for(i...){...}
规则:所有变量声明都放在函数的头部,所有函数都在使用之前定义
b.用来计数的循环变量泄露为全局变量
var s = "hello";
for(var i=0;i<s.length;i++){
console.log(s[i]);
}
console.log(i);//5
变量i只用来控制循环,但是循环结束之后,它并没有消失,泄露成了全局变量
c.ES6的块级作用域的一些规则
(1)es6允许块级作用域的任意嵌套
{{{{{let insane = 'hello world'}}}}};
上面代码使用了一个五层的块级作用域,外层作用域无法读取内层作用域的变量,但是内层作用域可以定义外层作用域的同名变量。
(2)块级作用域的出现,实际上使得获得了广泛应用的立即执行函数表达式(IIFE)不再需要了。
//IIFE写法
(
function(){
var tmp = ...;
}()
);
// 块级作用域的写法
{
let tmp = ...;
}
d.块级作用域与函数声明
(1)ES5规定:函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域中声明(但是浏览器没有遵守规定,为了兼容之前的旧代码)
(2)ES6:引入块级作用域,明确允许在块级作用域之中声明函数
(3)块级作用域中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
注意:浏览器的实现可以不遵守上面的规定,有自己的行为方式
-允许在块级作用域内声明函数
-函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
-同时,函数声明还会提升到所在的块级作用域的头部
上面三条规则只对ES6的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当做let处理。
在浏览器的ES6环境中,块级作用域声明的函数行为类似于var声明的变量,考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数,如果确实需要,也应该写成函数表达式,而不是函数声明语句
ES6的块级作用域允许声明函数的规则,只在使用大括号{}的情况下成立,如果没有使用大括号,就会报错。
e.do表达式
本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。
使用do:在块级作用域之前加上do,使它成为do表达式
{
let t = f();
t = t * t + 1;
}
//加上do,使它成为do表达式
{
let x = do{
let t = f();
t*t+1;
}
}
f.块级作用域外部无法调用块级作用域内部定义的函数,如果确实需要调用,则像下面这样处理:
let f;
{
let a = 'secret';
f = function(){
return a;
}
}
f();//"secret"
需要注意的是,如果在严格模式下,函数只能在顶层作用域和函数内声明,其他情况(比如if代码块、循环代码块)下声明都会报错。
2.const命令
(1)const声明一个只读变量,一旦声明,常量的值就不能改变
(2)const一旦声明变量,就必须立即初始化,不能留到最后赋值。
(3)const的作用域与let命令相同:只在声明所在的块级作用域内有效
(4)const命令声明的变量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用
(5)const声明的变量,与let一样不可重复声明
const本质上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动,对于对象和数组,变量保存的是一个内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就不能控制了。
const foo ={};
foo.prop = 123;
foo={};//这里会报错
//foo存储的是一个地址,这个地址指向一个对象,不可变的是这个地址,即不能把foo指向另一个地址,但对象本身还是可变的,所以依然可以为其添加属性
3.ES6声明变量方法(6种)
ES5只有两种:var ,function
ES6:var ,function ,let,const,import,class
4.顶层对象的属性
顶层对象,在浏览器环境指的是window对象,在node指的是global对象,ES5之中,顶层对象的属性和全局变量是等价的。
上述问题的现象:
(1)没法在编译时报出变量未声明的错误,只有在运行时才能知道
(2)不知不觉在创建全局变量
(3)顶层对象的属性到处可以读写,这非常不利于模块化编程
(4)window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。
ES6:var,function声明的是全局变量,依旧是顶层对象的属性
但是let,const,class声明的全局变量,不再是顶层对象的属性。
var a = 1;
window.a;//1
let b = 1;
window.b;//undefined
5.global对象
(1)ES5的顶层对象,本身也是一个问题,因为它在各种实现不统一
(2)现在有一个提案,在语言标准的层面,引入global作为顶层对象,也就是说,在所有环境下,global都是存在的,都可以从它拿到顶层对象。
ES6的let和const命令的更多相关文章
- ES6 之 let和const命令 Symbol Promise对象
ECMAScript 6入门 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了. (2016年6月,发布了小幅修订的<ECMASc ...
- es6之let和const命令的一些笔记
let和const命令 let命令 基本用法 let命令用来声明变量,声明的变量只在命令所在的代码块内有效.for循环中很适合使用let命令. 有必要理解的例子: var a = []; for (v ...
- ES6中let与const命令详解
阮一峰ES6入门 let 作用域 let命令用来声明变量,但声明的变量只在let命令所在的代码块内有效. { let a = 10; var b = 1; } a // ReferenceError: ...
- ES6入门——let和const命令
let和const命令 1.let命令 用法:类似于var,用来声明一个变量,区别是所声明的变量只在let命令所在的代码块内有效. let命令很适合用在for循环的计数器中,因为let声明的变量仅在作 ...
- 2. ES6基础-let和const命令
目录 1. let命令 1.1 用法 1. 2 不存在变量提升 1.3 区域绑定 1.4 不允许重复声明 2. const命令 2.1 用法 2.2 与let类似的特性 2.3 const本质 2.4 ...
- ES6的let和const命令(一)
2019独角兽企业重金招聘Python工程师标准>>> ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变 量,只在let命令所在的代码块内有效. let ...
- ES6 let和const命令(3)
const 用来声明常量.一旦声明,就不能改变. const在声明必须初始化,只声明不赋值会出错 const的作用域与let一样,只在声明的块级作用域有效. const命令声明的常量也不提升,同样存在 ...
- ES6简介之let和const命令解说
一.var申明变量 学习过JavaScript的同学都应该知道,ES5中申明变量使用var,ES5中的var可以说是无所不能的,所有类型的变量都是由var来申明,但往往很多使用者不知道var申明的变量 ...
- ES6之新增const命令使用方法
hi,我又回来了,今天学习一下const命令. 声明一个常量 const声明一个只读常量,一旦声明,常量的值便不可改变. 例子如下: const food = 12; food = 23; // Un ...
随机推荐
- FAN54015 充電電流 軟硬體設定
Ex1: Vrsense 選 37.4 mV --- 在第二張圖 Rsense 選 50 mΩ --- 在第三張圖 37.4 / 50 = 748 mA Ex2: Vrsense 選 44.2 mV ...
- 2017多校第7场 HDU 6121 Build a tree K叉树,思维
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:一个n个点的完全k叉树,求每个节点的size的异或和. 解法:容易发现,考虑根的所有孩子, ...
- c语言实现CRC校验和
最近在摄像头采集的数据清晰度上需要加强,则在每一帧传输的数据包后边加了CRC校验和.CRC校验和有16位的,也有32位的.至于CRC校验和算法原理,我是在百度上学习的,其实网上有很多这种资料.简单的说 ...
- Leetcode 之Anagrams(35)
回文构词法,将字母顺序打乱.可将字母重新排序,若它们相等,则属于同一组anagrams. 可通过hashmap来做,将排序后的字母作为key.注意后面取hashmap值时的做法. vector< ...
- powershell常用操作
创建文件 New-Item -path $file_path -itemtype file 创建目录 New-Item -path $dir_path -type directory 删除目录 Rem ...
- DEADBEEF
“DEADBEEF”是什么?可能很多人都没有听说过.DEADBEEF不是“死牛肉”的意思,而是一个十六进制数字,即0xDEADBEEF.最初使用它的是IBM的RS/6000系统.在该系统中,已分配但还 ...
- hdu 2448(KM算法+SPFA)
Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- eclipse+opencv
https://docs.opencv.org/2.4/doc/tutorials/introduction/linux_eclipse/linux_eclipse.html
- Git----创建远程分支,并将文件上传到创建的远程分支上
1.首先创建一个远程仓库 2.将远程仓库克隆到本地 (1)本地新建文件夹,命令行进入文件夹,执行clone操作 (2) git clone git@github.com:Lucky-Syw/lucky ...
- es6 map数据类型,要比set还很多
首先它支持多数据存储,具有增删查功能 set()设置 get()获取; has()查找; delete('obj')删除指定:clear()全部删除 size长度 let json={ name:&q ...