let和const命令
let命令
- 不存在变量提升
在变量声明之前使用会报错 - 暂时性死区
当代码块存在let或者const命令时,那么在该代码块中,这些命令声明的变量,凡是在声明之前使用都会报错.(不论父作用域中有没有声明同名变量) - let不允许在相同的作用域内重复声明一个变量
块级作用域
- let为javascript新增了块级作用域
ES6允许块级作用域的任意嵌套;块级作用域让广泛应用的立即执行函数表达式没必要存在 - 块级作用域于函数声明
ES5规定函数只能在顶层作用域和函数作用域中声明,不能再块级作用域声明.但是浏览器没有遵守这个规定.ES6引进了块级作用域,明确允许块级作用域中可以声明函数;ES6规定,块级作用域中,函数声明语句的行为类似于let.
但是,如果真的在ES6浏览器中,实现规则并不是这样;如果改变了块级作用域内声明的函数的处理规则,会对老代码产生很大影响.为了减轻因此产生的不兼容问题,ES6规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式:- 允许在块级作用域内声明函数
- 函数声明类似于var,存在变量提升
- 函数声明还会提升到所在块级作用域的头部
attention
ES6的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错.(注意一些可以省略大括号的情况)
const命令
const声明一个只读的常量,不能改变常量的值.特性同let命令声明的变量.
const实际保证的并不是变量的值不得改动,而是变量指向的内存地址不得改动.对于复杂数据类型,保存的知识一个指针,const只能保证这个指针是固定的,至于指向的数据结构是不是可以改变的则完全不能控制.
顶层对象
在ES5中,顶层对象的属性与全局变量是等价的.
ES6中,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let,const,class命令声明的全局变量,不属于顶层对象的属性.
ES5的顶层对象在各种实现里面不统一.
解构赋值
数组的解构赋值
基本用法
模式匹配,如果两边模式相同,那些左边的变量就会被赋予对应的值.如果解构不成功,变量的值就等于undefined
;另外一种不完全解构,及等号左边的模式只匹配一部分等号右边的数组,依然可以解构成功.
如果等号右边的值转化为对象之后不具备Iterator
接口或者本身就不具备Iterator接口会报错.
- 默认值
解构赋值允许指定默认值
ES6内部使用严格相等运算符,判断一个位置是否有值.所以只有当一个数组成员严格等于undefined
,默认值才会生效.
let [x,y = 0] = [1,undefined] //x=1,y=0
如果默认值是一个表达式,那么这个表达式
是惰性求值的,即只有在用到的时候才会求值.
对象的解构赋值
对象的属性没有次序,变量必须与属性同名.如果没有对应的同名属性,导致取不到值,最后等于undefined
.
真正赋值的是键值对等号的后边,而不是左边.左边是匹配的模式.
数组和对象解构赋值都可以用于嵌套结构的对象.如果嵌套结构的对象需要每一层都赋值的话,那么需用逗号隔开,层层解构:
const node = {
loc: {
start: {
line: 1,
column: 5
}
}
};
let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc // Object {start: Object}
start // Object {line: 1, column: 5}
- 默认值
默认值生效的条件是,对象的属性值严格等于undefined
如果解构失败,变量的值等于undefined
如果将一个已经声明的变量用于解构赋值,须注意避免JavaScript
引擎将已声明的变量理解成为一个代码块,从而发生语法错误.(不将大括号写在行首即可避免)
字符串的解构赋值
字符串被转换成一个类似数组的对象,类似数组的对象都有一个length属性.
数值和布尔值的解构赋值
解构赋值时,如果等号右边的值不是对象或者数组,就先将其转化为对象,由于undefined
和null
无法转换为对象,所以对它们进行解构赋值都会报错.
圆括号问题
ES6的规则是,只要是有可能导致解构的歧义,就不得使用圆括号.
不能使用圆括号的情况:
- 变量声明语句
- 函数参数
- 赋值语句的模式
可以使用圆括号的情况:
- 赋值语句的非模式部分
用途
- 交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
- 从函数返回多个值
函数如果需要返回多个值只能返回一个数组或者对象,用解构赋值可以轻松取出. - 函数参数的定义
可以方便的将一组参数与变量名对应起来 - 提取JSON数据
- 函数参数的默认值
- 遍历
map
结构
任何部署了Iterator
接口的对象,都可以使用for...of
循环遍历,获取键名和键值非常方便
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// first is hello
// second is world
- 输入模块的指定方法