最近复习了es6 ,写写博客整理一下相关知识
let 和 const 关键字
let
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
使用 let 声明的变量有以下几个特点:
- 不允许重复声明;
- 块儿级作用域(局部变量);
- 不存在变量提升;
- 不影响作用域链;
- 暂时性死区
//使用let 关键字声明的变量不允许重复声明
//var 声明变量可以重复声明
let a
let a = 12 // a已经声明,此处为错误用法!
// var 可以在代码块之外读取变量
//使用let关键字声明的变量具有块级作用域,声明的变量只在所处于的块级有效
{
let fruit='apple'
}
console.log(fruit) //error
//let 不存在变量提升,var 存在变量提升
console.log(a); //a is not defined
let a = 20;
//不影响作用域链就是:上级代码块中的局部变量下级可用
{
let p=1
function fn(){
console.log(p) // 这里是可以使用的
}
fn()
}
//从作用域链的结构可以看出,函数在执行的过程中,先从自己内部寻找变量,如果找不到,再从创建当前函数所在的作用域去找,从此往上,也就是向上一级找
//暂时性死区
var tmp = 10;
if (true) {
console.log(tmp); //tmp is not defined
let tmp = 20;
}
/*
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值或者使用都会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
*/
let 声明的变量存在块级作用域,由于这个特性,let可以用来防止循环变量变成全局变量
for(var i = 0; i<5;i++){
setTimeout(()=>console.log(i),0) // 5 5 5 5 5
}
在for循环中使用var,因为var是全局变量,所以循环结束后值会被覆盖掉,setTimeout 是一个异步,所以它拿到的是循环结束后的i的值,因此会打印出五个5。
for(let i = 0; i<5;i++){
setTimeout(()=>console.log(i),0)//0 1 2 3 4
}
//在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次。
//你也可以当成是声明了五个let块级作用域
{let i = 0}
{let i = 1}
{let i = 2}
{let i = 3}
{let i = 4}
const
const 关键字用来声明常量,const 声明有以下特点:
- 声明必须赋初始值,赋值之后不允许修改;
- 标识符一般为大写(习惯);
- 不允许重复声明;
- 块儿级作用域(局部变量);
// const声明常量,一经声明,则不允许修改
//const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const fruit // 未赋值,报错
//标识符一般为大写(习惯)
const FRUIT = "apple"
console.log(FRUIT) // "apple"
//const的作用域与let命令相同:只在声明所在的块级作用域内有效。
if (true) {
const MAX = 5;
}
MAX // Uncaught ReferenceError: MAX is not defined
//const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
if (true) {
console.log(MAX); // ReferenceError
const MAX = 5;
}
解构赋值
数组的解构赋值
const BOOKS = ['三体', '海子的诗', '西游记']
let [san, hai, xi] = BOOKS
console.log(san) // '三体'
console.log(hai) // '海子的诗'
console.log(xi) // '西游记'
let [h, m] = BOOKS
console.log(h); // '三体'
console.log(m); // '海子的诗'
对象的解构赋值
const ZHANGSAN = {
name: '张三',
age: 23,
gender: '男',
speak: function () {
console.log("Hello,I'm ZhangSan!")
}
}
let {name,age,gender,speak} = ZHANGSAN;
console.log(name) // '张三'
console.log(age) // 23
console.log(gender) // '男'
console.log(speak) // function(){...}
speak() // "Hello,I'm ZhangSan!"
//如果不使用方法的结构赋值,每次调用方法都要写
ZHANGSAN.speak()
console.log('只进行对象里面的方法解构赋值');
let {
speak
} = ZHANGSAN;
console.log(speak) //[Function: speak]
//解构赋值的时候,变量名要与对象里面的属性名字相同
let {
aaa
} = ZHANGSAN;
console.log(aaa); //undefined
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let {name,age,gender,speak} 这种解构其实是一种简写,所以在进行对象的解构赋值的时候,要注意变量名必须是对象里面存在的属性名
具体参考这篇文章
https://es6.ruanyifeng.com/#docs/destructuring
字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length : len} = 'hello';
len // 5
函数参数的解构赋值
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
上面代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x和y。对于函数内部的代码来说,它们能感受到的参数就是x和y。
函数参数的解构也可以使用默认值:
function func({x,y=5}){
console.log(x,y);
}
func({}); //undefined,5
func({x:1}) // 1,5
func({x:1,y:2}) //1,2
foo() // TypeError:Cannot read property 'x' of undefined
函数参数的默认值一般位置要靠后
上面的写法是为x,y 变量指定默认值,所以当没有给y 传递实参的时候,打印的y 就是5
下面的问一种写法是为函数的实参指定默认值
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
当调用move 方法,却没有传递实参的时候,默认给它传递一个参数为{ x: 0, y: 0 },所以move() 的打印结果为[0, 0];
并没有给x,y 变量指定默认值,所以第二种和第三种会打印出undefined
扩展运算符
扩展运算符… ,能将数组转换为逗号分隔的参数序列;
扩展运算符放在实参的位置,就是调用函数的时候去使用;
const arr = [1, 2, 3, 4, 5]
function fun() {
console.log(arguments);
}
fun(arr) //[Arguments] { '0': [ 1, 2, 3, 4, 5 ] }
fun(...arr); //[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
应用
//扩展运算符可以用来拷贝数组,不过要注意的是这是一个浅拷贝。
const arr1 = [1, 2, 3]
const arr2 = [...arr1]
console.log(arr2);
//数组合并
const arr3 = [1, 2, 3];
const arr4 = [4, 5, 6];
//早期间我们可以使用concat方法
//const arr5=arr3.concat(arr4)
const arr5 = [...arr3, ...arr4];
console.log(arr5); // [ 1, 2, 3, 4, 5, 6 ]
模板字符串
使用一对反引号 声明的字符串,特性如下:
- 里面可以直接使用换行
let str = `<ul>
<li>111</li>
<li>222</li>
<li>333</li>
</ul>`
2.变量拼接(替换/插入)
使用${变量名}定位插入的元素位置
let a = 20;
let str = `${a}的值为20`