ECMAScript简称ES,可以把它看成是一套标准,JavaScript是实施了这套标准的一门语言
ES6是于2015年6月正式发布,全称为ECMAScript 2015
ES7、ES8等新增特性都可以称之为ES6新语法
本篇介绍一些常用的ES6语法和特性
1、let & const
let和const是es6新增的关键字,用于声明变量和常量
var、let、const区别
1、是否允许重复定义(var允许,let、const不允许)
2、是否有块级作用域(var不存在,let、const存在)
3、是否具有变量提升(var具有,let、const不具有)4、const在声明时必须赋值,且不允许再次赋值
2、模板字符串
反引号``就是模板字符串,和引号使用方法相同
但是反引号支持换行,并且可以使用${}解析表达式
let name = '张三';
console.log(`我叫${name},
今年十岁了`)
/*
我叫张三,
今年十岁了
*/
3、解构赋值
解构赋值:ES6中可以直接从数组或对象中提取值,并赋值给其他变量
数组解构
左侧使用中括号包裹,变量与数组元素一一对应即可
let [a,b,c] = [1,2,3]
console.log(a, b, c) // 1 2 3
变量可以省略,取指定的数据
let [,b] = [1,2,3]
console.log(b) // 2
利用数组解构交换两个变量的值
let a = 1;
let b = 2;
[a,b] = [b,a]
console.log(a,b) // 2 1
可以直接使用存储数组的变量或常量进行赋值
let arr = [1,2,3]
let [a,b,c] = arr
console.log(a,b,c) // 1 2 3
多余的变量被赋值为undefined
let [a,b] = [1]
console.log(a,b) // 1 undefined
对象解构
可以不一一对应,没有顺序要求
let {b: n1, a: n2} = {a: 1, b: 2}
console.log(n1, n2) // 2 1
变量名和右侧的属性名相同时,可以省略属性名不写
let {a, b} = {a: 1, b: 2}
console.log(a, b) // 1 2
在函数传参中也可以使用,但名称必须相同
let obj = {a:1}
function fun({a}){
console.log(a) // 1
}
fun(obj)
4、展开运算符
展开运算符是 ... ,他也是剩余运算符
展开运算符
展开运算符可以将数组和对象展开,用于赋值号右边
console.log(...[1,2,3]) // 1 2 3
// 当用作对象时,必须赋值给另一个对象
let obj = {...{a: 1}, b: 2}
console.log(obj) // {a: 1, b: 2}
展开运算符也可以用于传入函数的实参中
function fun(a,b){
consoel.log(a,b) // 1 2
}
fun(...[1,2])
剩余运算符
剩余运算符与展开运算符功能相反,用于赋值号左边
剩余运算符可以在解构赋值中,将右边多余的元素组合成一个新的数组或对象
let [a,...b] = [1,2,3]
console.log(a,b) // 1 [2, 3]
let [a,...b] = [1,2]
console.log(a,b) // 1 [2]
let {a,...b} = {a:1,b:2,c:3}
console.log(a,b) // 1 {b: 2, c: 3}
let {a,...b} = {a:1,b:2}
console.log(a,b) // 1 {b: 2}
剩余运算符也可以用于函数的形参上
function fun(...obj){
console.log(obj) // [1, 2, 3]
}
fun(1, 2, 3)
5、参数默认值
函数的形参可以给定一个默认值,如果调用函数时该参数未传值,则使用默认值
function fun(a = 10){
console.log(a) // 10
}
fun()
function fun(a, b = 10){
console.log(a, b) // 5 10
}
fun(5)
6、对象的写法变化
当对象的属性值为一个变量,且与属性名相同时,可以省略属性名
let a = 1;
// let obj = {a: a}
let obj = {a}
对象中定义的函数可以省略function
// let obj = {
// fn: function(){}
// )
let obj = {
fn(){}
}
7、新增方法
对象新增方法
Object.assign() | 浅拷贝 |
Object.create() | 创建一个对象,并重定向__proto__ |
Object.is() | 判断两个值是否全等 |
Object.keys() | 遍历对象,获取所有的属性 |
Object.values() | 遍历对象,获取所有的属性值 |
Object.assign()
浅拷贝,等同于复制,如果拷贝目标中含有引用数据类型,则拷贝的是地址
const obj1 = {arr: [1, 2]}
const obj2 = Object.create(obj1)
console.log(obj2) // {arr: [1, 2]}
// arr为引用数据类型,所以拷贝的是地址
obj2.arr.push(3)
console.log(obj1) // {arr: [1, 2, 3]}
cossole.log(obj2) // {arr: [1, 2, 3]}
Object.create()
基于一个对象作为原型创建一个新对象
const obj1 = {a: 1}
const obj2 = Object.create(obj1)
console.log(obj2.__proto__) // {a: 1}
Object.is()
判断两个值是否全等,可以用来判断NaN
console.log(Object.is(NaN,NaN)) // true
console.log(Object.is({},{}) // false
// 因为对象是引用类型,所以并不相等
Object.keys()
遍历对象,获取对象中所有的属性,返回一个数组
const obj = {a: 1, b: 2}
console.log(Object.keys(obj)) // ['a', 'b']
Object.values()
遍历对象,获取对象中所有的属性值,返回一个数组
const obj = {a: 1, b: 2}
console.log(Object.values(obj)) // [1, 2]
数组新增方法
Array.from() | 将伪数组转为数组 |
Array.of() | 创建一个数组 |
at() | 获取数组指定下标的值 |
flat() | 将数组扁平化 |
fill() | 填充数组元素 |
includes | 检测数组中是否存在某个元素 |
find | 查找并返回满足条件的元素 |
findIndex | 查找并返回满足条件的元素的下标 |
Array.from()
将伪数组转为数组
伪数组:可以使用下标获取元素,但不能调用数组的方法
像document.querySelectorAll()得到的数组、arguments都是属于伪数组
// <li></li>
let li = document.querySelectorAll('li')
li.push(1) // 报错(lis.push不是一个函数)
li = Array.from(li) // 使用Array.from转为数组
li.push(1) // 正常
console.log(li) // [li, 1]
Array.of()
和new Array()类似,都是创建数组
但在参数有且只有一个数字时,new Array()用来表示数组长度
const arr1 = Array.of(3)
const arr2 = new Array(3)
console.log(arr1) // [3]
console.log(arr2) // [空 *3]
at()
传入下标,获取数组中对应的值,可以传入负数,表示倒数
当参数的绝对值大于数组长度时,返回undefined
const arr = ['a', 'b', 'c']
console.log(arr.at(0)) // 'a'
console.log(arr.at(-1)) // 'c'
console.log(arr.at(-5)) // undefined
flat()
将数组扁平化处理,参数默认为1,表示扁平化的深度
扁平化:将多维数组转为一维数组
const arr = [1, [2, [3, [4, 5]]]]
console.log(arr.flot()) // [1, 2, [3, [4, 5]]]
console.log(arr.flot(2)) // [1, 2, 3, [4, 5]]
// 参数为Infinity时,转为一维数组
console.log(arr.flot(Infinity) // [1, 2, 3, 4, 5]
fill()
填充数组元素,等同于替换指定元素
参数1:用来填充的值;参数2:开始填充的位置的下标;参数3:结束填充的位置的下标
const arr = [1, 2, 3, 4];
// 从下标2开始,到下标4结束,填充数字0
console.log(arr.fill(0, 2, 4)) // [1, 2, 0, 0]
// 没有参数3时,表示填充到末尾
console.log(arr.fill(5, 1)) // [1, 5, 5, 5]
// 只有一个参数时,表示全部填充
console.log(arr.fill(6)) // [6, 6, 6, 6]
includes()
检测数组中是否存在指定的元素,返回布尔值
const arr = [1, 2, 3, NaN]
console.log(arr.includes(1)) // true
console.log(arr.includes(4)) // false
// 可以用来检测 NaN
console.log(arr.includes(NaN) // true
find()
find会遍历数组,查找满足条件的元素,返回第一个满足条件的元素
他的参数为一个回调函数,该回调函数可以有三个形参
形参1:当前遍历的元素;形参2:当前遍历的元素下标;形参3:数组本身
const arr = ['a', 'b']
arr.find(function(item, index, array){
console.log(item, index, array)
// 'a' 0 ['a', 'b']
// 'b' 1 ['a', 'b']
}
在回调函数中,可以return一个表达式,当表达式为true时,find视为当前遍历的元素满足条件,find就会返回该元素,并且结束遍历操作,如果直到结束没有满足条件的元素,则返回undefined
const arr = [1, 2]
const num = arr.find(function(item){
return item > 0
}
console.log(num) // 1
findIndex与find用法相同,唯一不同的是findIndex返回的是下标,find返回的是元素本身
字符串新增方法
startsWith() | 判断当前字符串是否以指定字符串开头,返回一个布尔值 |
endsWith() | 判断当前字符串是否以指定字符串结束,返回一个布尔值 |
repeat() | 返回一个新字符串,包含指定数量的所调用的字符串 |
match() | 返回与正则匹配的内容,找不到则返回null |
search() | 返回与正则匹配的内容的开始下标,找不到则返回-1 |
startWith()
判断当前字符串是否以指定字符串开头,返回一个布尔值
let str = 'abcd'
console.log(str.startsWith('a')) // true
console.log(str.startsWith('b')) // false
endsWith()
判断当前字符串是否以指定字符串结束,返回一个布尔值
let str = 'abcd'
console.log(str.endsWith('d')) // true
console.log(str.endsWith('b')) // false
repeat()
将原字符串复制指定次数,拼接成一个新字符串并返回
let str = 'abcd';
console.log(str.repeat(2)) // 'abcdabcd'
match()
找到第一个与正则匹配的字符(串),返回一个数组,包含其信息;找不到则返回null
let str = 'abcd';
let reg = /b/;
console.log(str.match(reg))
// ['b', index: 1, input: 'abcd', groups: undefined]
search()
找到第一个与正则匹配的字符(串),返回其下标;找不到则返回-1
与indexOf方法相同,只不过search匹配的是正则表达式
let str = 'abcd';
let reg = /b/;
console.log(str.search(reg)) // 1
8、集合
集合与数组对象类似,都是存放多个数据的引用数据类型
但集合的本身是构造函数,需要使用new实例化创建而不能使用字面量的方式创建
Set
存储多个数据,但不会有重复的数据
// 创建Set集合
let set = new Set()
console.log(set) // Set(0) {size: 0}
// 添加数据
set.add(5)
console.log(set) // Set(1) {5}
// 获取集合长度
console.log(set.size) // 1
// 删除元素(成功返回true,失败返回false)
set.delete(1)
// 判断集合中是否含有某个元素
console.log(set.has(2)) // false
// 移除所有元素
set.clear()
// Set集合并不能直接获取到元素,但是可以使用forEach、for of等方法进行遍历
set.forEach(item => {
console.log(item)
})
// new Set可以传入一个数组
let set = new Set([1,2,3])
console.log(set) // Set(3) {1, 2, 3}
Map
以键值对的形式存储多组数据,不会有重复的键存在
// 创建Map集合
let map = new Map()
console.log(map) // Map(0) {size: 0}
// 添加数据
map.set(1,2)
console.log(map) // Map(1) {1 => 2}
// 通过键名获取值
console.log(map.get(1)) // 2
// 删除元素
map.delete(1)
// 判断map中有没有某个键
console.log(map.has(1)) // false
// 清空map
map.clear()
// Map的键可以是任何类型,甚至是一个对象
let obj = {a:1}
map.set(obj,{b:2})
console.log(map.get(obj)) // {b:2}
// Map同样可以使用forEach等方法
map.forEach((value,key) => {
console.log(value,key) // {b:2} {a:1}
})
// new Map可以传入一个二维数组
let map = new Map([[1,2], [3,4]]
console.log(map) // Map(2) {1 => 2, 3 => 4}
WeakSet
WeakSet与Set类似,是弱引用Set类型
WeakSet没有size属性,没有clear方法,也不能使用循环进行遍历
WeakSet只能存储对象类型的数据,也不会存储重复的数据
弱引用类型中存储的数据,并不会在垃圾回收机制中对该数据进行标记或引用计数
换言之,不影响该数据被垃圾回收
let obj = {}
// 创建 WeakSet 集合
let set = new WeakSet()
// 添加成员
let set.add(obj)
// 判断是否含有某个成员
set.has(obj) // true
// 删除成员
set.delete(obj)
WeakMap
WeakMap的键为弱引用,值为强引用
WeakMap没有clear方法,也不能使用循环进行遍历
存储的键和值都必须是对象类型,也不会存储重复的键
let obj = {a:1}
// 创建 WeakMap 集合
let map = new WeakMap()
// 添加成员
map.set(obj,{b:2})
// 获取成员的值
amp.get(obj) // {b:2}
// 判断是否含有某个成员
map.has(obj) // true
// 删除成员
map.delete(obj)
WeakSet和WeakMap因为弱引用的特性,主要用来防止内存泄漏
9、Symbol
产生一个独一无二的值
let s1 = Symbol()
let s2 = Symbol()
console.log(s1 == s2) // false
在向对象中添加数据时可以防止命名冲突,如果想取出,使用一个变量名来接收symbol即可
const obj = {a:1}
const s1 = Symbol()
obj[s1] = 10
console.log(obj) // {a: 1, Symbol(): 10}
console.log(obj[s1]) // 10
10、生成器与迭代器
Generator(生成器)是一个特殊的函数,执行它会返回一个Iterator(迭代器)对象
function 后面加 * 就是生成器函数,使用yield关键字来控制代码执行流程
function* go(){
console.log(1);
yield;
console.log(2);
yield;
}
执行生成器函数,返回迭代器对象
const it = go();
console.log(it); // go {<suspended>}
调用生成器不会运行函数,而是返回一个迭代器,需要调用.next()才会执行函数
执行过程中遇到yield函数便会停止,需要再次调用.next()
it.next(); // 打印 1
it.next(); // 打印 2
next方法可以有参数,参数将传给上一个yield,如果yield没有接收到值,则为undefined
yield右侧的值不参与赋值运算,右侧的值会作为返回值
next方法的返回值为一个对象,对象有两个属性:value、done
yield右侧的值作为返回值中的value,done表示函数是否结束
function* go(){
console.log(1);
const a = yield 10;
console.log(2);
const b = yield a;
}
const it = go();
console.log(it.next(1)); // {value:10,done:false}
console.log(it.next(2)); // {value:2,done:false}