ES6新特性
目录
[TOC]
let 声明变量
不能重复声明,块级作用域(if else for while) ,不存在变量提升,不影响作用域链
//不能重复声明,
// let start = 1
// let start = 2
// 块级作用域
// {
// let age = 18
// }
// console.log(age);
// 不存在变量提升
// console.log(a);
// let a = 1
// 不影响作用域链
// {
// let age = 18
// function fn() {
// console.log(age);
// }
// fn()
// }
const声明常量
必须有初始值,常量的值不能修改,块级作用域,操作空间地址不算重新赋值
// 必须有初始值
// const age = 18
// 常量的值不能修改
// age = 8
// 块级作用域
// {
// const age = 18
// }
// console.log(age);
// 操作空间地址不算重新赋值
// const arr = [1, 2, 3]
// arr.push(4)
解构赋值
允许按照一定格式从数组和对象中提取值,对变量进行赋值
// 数组的解构
// let f4 = ['小沈阳', '刘能', '赵四', '宋小宝']
// let [x, l, z, s] = f4
// console.log(x, l, z, s);
// 对象解构
// let zhao = {
// name: '赵本山',
// age: '60',
// xiaopin: function () {
// console.log('我可以演小品');
// }
// }
// let { xiaopin } = zhao
// xiaopin()
模板字符串
可以识别换行符,拼接变量
let age = 18
let str = `我今年${age}了`
console.log(str);
对象的简化写法
kv 一致省略v 函数可以不写function
let age = 18
let name = 'jyc'
let obj = {
name,
age,
fn() {
console.log(obj.age);
}
}
obj.fn()
箭头函数
- 没有自己的this,this指向函数声明时所在作用域下this的值
- 不能作为构造函数
- 不能使用arguments
- 形参就一个值可以省略小括号,执行语句就一个值可以省略花括号和return
// var age = 18
// let obj = {
// age: 22
// }
// function getAge() {
// console.log(this.age);
// }
// let getAge1 = () => {
// console.log(this.age);
// }
// getAge()
// getAge1()
// getAge.call(obj)
// getAge1.call(obj)
// let fn = a => a + a
// console.log(fn(1));
函数参数的默认值设置
允许函数参数赋初始值
function add(a, b, c = 10) {
return a + b + c
}
// console.log(add(1, 2));
//与解构赋值结合
function reqire({ host, userName, password, port = 8080 }) {
console.log(host);
console.log(userName);
console.log(password);
console.log(port);
}
reqire({
host: ' 172.168.0.0.1',
userName: 'root',
password: 'root',
})
rest参数
用于获取函数实参代替arguments
// arguments es5伪数组
// function data() {
// console.log(arguments);
// }
// rest参数必须要放到最后得到数组
function data(a, b, ...args) {
console.log(args);
}
data('小白', '小明', '小李', 1, 2, 3)//(4) ['小李', 1, 2, 3]
扩展运算符
合并 浅克隆 伪数组转数组
//合并
let a = [1, 2, 3]
let b = [4, 5, 6]
let arr = [...a, ...b]
console.log(arr);
//浅克隆
let arr2 = [...arr]
console.log(arr2);
// 伪数组转数组
function fn() {
console.log([...arguments]);
}
fn('小白', '小明', '小李')
symbol
es6引入了一种新的原始值类型symbol,表示独一无二的值,
symbol是唯一的,用来解决命名冲突的问题,不能参与运算,不能使用for in 使用refice,ownkeys
主要用于给对象添加属性和方法
创建使用
let game = {
name: '俄罗斯方块',
up: () => { },
down: () => { }
}
let methods = {
up: Symbol(),
down: Symbol(),
}
game[methods.up] = function () {
console.log('我可以改变形状');
}
game[methods.down] = function () {
console.log('我可以下降');
}
console.log(game);
Symbol.hasInstance
当其对象用 instanceof,判断是否为该对象的实例时会调用这个方法
class Person {
static [Symbol.hasInstance]() {
console.log('我被用来检测类型');
return true
}
}
let o = {}
console.log(o instanceof Person); //true
Symbol.isConcatSpreadable
等于的是一个布尔值,表示Array.prototype.content()时是否可以展开
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
arr1[Symbol.isConcatSpreadable] = false
let arr = arr1.concat(arr2)
console.log(arr);//(4) [Array(3), 4, 5, 6]
迭代器 iterator
迭代器是一种接口 ,为各种不同的数据结构,提供统一的访问机制,任何数据结构只要部署了iterator接口就可以完成遍历操作
es6创造了一种新的遍历命令 for...of.. iterator接口主要提供 for...of..消费
具备iterator接口的数据 array ,arguments,set map string typeArray NodeList
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置,
- 第一次调用对象的.next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用.next方法,指针一直往后移动,直到指向最后一个成员
- 每次调用next方法,返回一个包含value和done属性的对象
let arr = [10, 20, 30]
let iterator = arr[Symbol.iterator]()//一个函数 得到一个对象
console.log(iterator);//得到一个对象 ,有一个next方法(指针)
console.log(iterator.next());//包含一个value 和done属性的对象
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())// {value: undefined, done: true}done表示完成状态
自定义遍历数据
const banji = {
name: '终极一班',
stus: [
'zs',
'ls',
'ww',
'xm'
],
[Symbol.iterator]() {
let index = 0
let self = this
return {
next: function () {
if (index < self.stus.length) {
const result = { value: self.stus[index], done: false }
index++
return result
} else {
return { value: undefined, done: true }
}
}
}
}
}
for (const val of banji) {
console.log(val);
}
生成器 generator
生成器其实是一个特殊的函数 可以解决异步编程
可以使用 yield 语句 函数代码的分割符
创建和使用
function* gen() {
console.log(11);
yield '一只没有耳朵'
console.log(22);
yield '一只没有尾巴'
console.log(33);
yield '真奇怪'
console.log(44);
}
let iterator = gen()
console.log(iterator);// 返回迭代器对象
iterator.next()//控制生成器函数执行
iterator.next()
iterator.next()
iterator.next()
参数的传递
next函数传递的参数当做上一次 yield 的语句的返回结果
function* gen(args) {
console.log(args);
let one = yield 11
console.log(one);
let two = yield 22
console.log(two);
let three = yield 33
console.log(three);
}
let iterator = gen('aa')
iterator.next('bb')
iterator.next('cc')
iterator.next('dd')
iterator.next()
案例
模拟获取 用户数据 订单数据 商品数据
function getUsers() {
setTimeout(() => {
let data = '用户数据'
//第二次调用next的 将数据传入 当做第一个yield的语句的返回结果
iterator.next(data)
}, 1000);
}
function getOrders() {
setTimeout(() => {
let data = '订单数据'
iterator.next(data)
}, 1000);
}
function getGoods() {
setTimeout(() => {
let data = '商品数据'
iterator.next(data)
}, 1000);
}
function* gen() {
let user = yield getUsers()
console.log(user);
let Orders = yield getOrders()
console.log(Orders);
let Goods = yield getGoods()
console.log(Goods);
}
let iterator = gen()
iterator.next()
promise
promise是一个构造函数用来封装异步操作,并可以获取成功或者失败的结果
promise构造函数 promise(excutor)
promise.prototype.then promise.prototype.catach
基本使用
let p = new Promise(function (resolve, reject) {
setTimeout(() => {
// let data = '用户数据'
// resolve(data)
reject(new Error('失败'))
}, 1000);
})
p.then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
})
then方法
- 调用then方法返回的是promise 状态由回调函数执行结果决定,
- 如果回调函数是非promise类型的属性,转态是成功,返回值是为成功值
- 是一个promise promise状态决定了.then的状态
- 抛出错误为失败的promise
let p = new Promise(function (resolve, reject) {
setTimeout(() => {
let data = '用户数据'
resolve(data)
// reject(new Error('失败'))
}, 1000);
})
let result = p.then((res) => {
console.log(res);
return new Promise((resolve, reject) => {
resolve('ok')
})
}, err => {
console.log(err);
})
//调用then方法返回的是promise 状态由回调函数执行结果决定,
// 如果回调函数是非promise类型的属性,转态是成功,返回值是为成功值
// 是一个promise promise状态决定了.then的状态
//抛出错误为失败的promise
console.log(result);
result.then((res) => {
console.log(res);
})
// 链式调用
p.then(res => {
}).then(res => {
})
catch
捕捉失败的promise
let p = new Promise(function (resolve, reject) {
setTimeout(() => {
reject(new Error('失败'))
}, 1000);
})
p.catch(err => {
console.log(err);
})
set
set数据结构,他类似于数组,但成员的值是唯一的,集合实现了iterator接口,所以可以使用扩展运算符和for..of遍历结合的属性和方法
- size 返回集合元素的个数
- add 增加一个元素返回当前集合
- delete 删除元素,返回布尔值
- has 检测集合中包含某个元素,返回布尔值、
- clear 清空集合
let s = new Set([1, '1'])
// 元素的个数
console.log(s.size)
// 添加元素
s.add(2)
console.log(s);
//删除元素
s.delete(2)
console.log(s);
// 检测
console.log(s.has(1));
// 清空
// s.clear()
// console.log(s);
for (const val of s) {
console.log(val);
}
应用
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]
// 去重
// let result = [...new Set(arr)]
// console.log(result);
//交集
let arr2 = [4, 5, 6]
// let result = [...new Set(arr)].filter(item => new Set(arr2).has(item))
// console.log(result);
// 并集
// let result = [...new Set([...arr, ...arr2])]
// console.log(result);
//差集
let result = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)))
console.log(result);
map
他类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值(包括对偶)都可以作为键 也实现了iterator接口 可以使用for..of 和扩展运算符
- size返回map元素个数
- set 增加一个新元素 返回放前map
- ger 返回健名对象的键值,
- has 检测集合中包含某个元素,返回布尔值、
- clear 清空集合
let map = new Map()
// 添加元素
map.set('name', 'zs')
map.set('change', function () {
console.log(111);
})
let key = {
love: '爱好'
}
map.set(key, ['唱', '跳', 'rap'])
console.log(map);
// 个数
console.log(map.size);
// 删除
// map.delete('name')
// console.log(map);
// 获取
// console.log(map.get('change')());
// 清空
// map.clear()
// console.log(map);
//遍历
for (const v of map) {
console.log(v);
}
class
- class声明类
- constructor定义构造函数初始化
- exends继承父类
- super调用父级构造方法
- static定义静态方法和属性
es5
function Phone(brand, price) {
// 实例属性
this.brand = brand
this.price = price
}
// 静态属性方法
Phone.name = '手机'
Phone.change = function () {
console.log('我可以改变事件');
}
//实例方法
Phone.prototype.call = function () {
console.log('我可以打电话');
}
//子类属性继承(改变this指向)
function SmartPhone(brand, price, color, size) {
Phone.call(this, brand, price)
this.color = color
this.size = size
}
// 修改子类原型继承父类方法
SmartPhone.prototype = new Phone
// constructor 指回子类
SmartPhone.prototype.constructor = SmartPhone
SmartPhone.prototype.playGame = function () {
console.log('我可以打游戏');
}
let huawei = new SmartPhone('华为', 2999, '白色', 5)
huawei.call()
console.log(huawei);
es6
class Phone1 {
constructor(brand, price) {
// 实例属性
this.brand = brand
this.price = price
}
// //实例方法
call() {
console.log('我可以打电话');
}
// 静态属性属性方法
static name = '手机'
static change() {
console.log('我可以改变事件');
}
}
//extends 继承
class SmartPhone1 extends Phone1 {
constructor(brand, price, color, size) {
//调用父类的构造器完成属性继承
super(brand, price)
this.color = color
this.size = size
}
playGame() {
console.log('我可以打游戏');
}
//重写父类方法
call() {
console.log('我可以视频通话');
}
// 获取劫持
get say() {
console.log('我被读取了');
return 11
}
//设置劫持
set say(newVal) {
console.log('我被修改了' + newVal);
}
}
let huawei = new SmartPhone1('华为', 2999, '黑色', 5)
huawei.call()
console.log(huawei);
huawei.say = 99
console.log(huawei.say);
数值扩展
- Number.EPSILON 最小精度
- 二进制 八进制
- Number.isFinite 检测一个值是否为有限小数
- Number.isNaN 是否为NaN
- Number.parseInt parseFloat 字符串转整数
- Number.isInteger 判断是否为整数
- Math.trunc 将小数部分抹除掉
- Math.sign 判读一个数字为正数负数还是0
// Number.EPSILON 最小精度
function equal(a, b) {
if (Math.abs(a - b) < Number.EPSILON) {
return true
} else {
return false
}
console.log(equal(0.1 + 0.2, 0.3));
}
// 二进制 八进制
let b = 0b1010
console.log(b);
// Number.isFinite 检测一个值是否为有限小数
console.log(Number.isFinite(100 / 0));
// Number.isNaN 是否为NaN
console.log(Number.isNaN('99'));
// Number.parseInt 字符串转整数
console.log(Number.parseInt('255efqxx'));
console.log(Number.parseFloat('3.14efwefw'));
// Number.isInteger 判断是否为整数
console.log(Number.isInteger(44.4));
// Math.trunc 将小数部分抹除掉
console.log(Math.trunc(23.14));
// Math.sign 判读一个数字为正数负数还是0
console.log(Math.sign(-99));
对象扩展方法
- // Object.is 判断两个值是否完全相等
- // Object.assign 对象的合并
- // Object.setPrototypeOf 设置原型对象
- // Object.getPrototypeOf 获取原型对象
// Object.is 判断两个值是否完全相等
console.log(Object.is(NaN, NaN));
console.log(Object.is(120, 121));
// Object.assign 对象的合并
let statu = {
name: 'zs',
age: 18
}
let statu2 = {
name: 'ls',
age: 22,
sex: '男'
}
let res = Object.assign(statu, statu2)
console.log(res);
// Object.setPrototypeOf 设置原型对象
// Object.getPrototypeOf 获取原型对象
let arr = [11]
let obj = {
a: 10
}
console.log(Object.setPrototypeOf(obj, arr));
console.log(Object.getPrototypeOf(obj));
模块化
模块化是一个大的程序文件,拆分成许多个小的文件 然后把小文件合起来
防止命名冲突,代码复用,高维护性
- CommonJS----》nodejs
- Amd---》requireJS
- cmd--》seaJS
ES6模块化语法
export 用于规定模块的对外接口
import 用于输入其他模块提供的功能
暴露
export 分别暴露
export{} 统一暴露
export defult{} 默认暴露
导入
通用导入方式
import * as from ‘xxx’
解构赋值
import{a,b}from 'xxx' 如果是默认暴露import {defult as data}from‘xxx’(因为默认暴露的是一个对象 使用别名的形式)
针对默认暴露的简便写法
import data from‘xxx’
es7新特性
includes 数组方法 是否含有某一项 返回布尔值
**运算等同于 Math.pow
let arr = [1, 2, 3]
let res = arr.includes(4)
console.log(res);
//**
console.log(2 ** 10);
async await
解决异步编程
async
- async返回一个promise对象
- promis对象的结果有async函数执行的返回值决定
- (返回的不是一个promise对象,返回的成功的promise,抛出异常返回失败的promise)(如果返回的是一个promise 由这个promise的状态决定)
async function fn() {
// return 1
// new Error('失败')
return new Promise((reslove, reject) => {
// return reslove(11)
reject('失败')
})
}
let res = fn()
res.then((result) => {
console.log(result);
}).catch((err) => {
console.warn(err);
});
await
- await必须写在async函数里
- await右边表达式一般为promise
- await返回的是promise成功的值
- await的promise失败了,需要通过try catch捕获
let p = new Promise((reslove, reject) => {
return reslove(11)
// reject('失败')
})
async function fn() {
try {
let result = await p
console.log(result);
} catch (e) {
console.warn(e);
}
}
fn()
es8对象扩展方法
Object.keys(obj) 获取对象的所有键
(Object.values(obj) 获取对象的所有值
Object.entries(obj) 方法返回一个给定对象自身可枚举属性的键值对数组。快速创建map结构
Object.getOwnPropertyDescriptors(obj1)获取对象的描述对象(是否可写,枚举,删除)
let obj = {
name: 'zs',
age: 18
}
//args:原型对象 描述对象
let obj1 = Object.create(null, {
name: {
value: 'zs',
writable: true,
configurable: true,
enumerable: true
}
})
//获取对象的所有键
console.log(Object.keys(obj));
// 获取对象的所有值
console.log(Object.values(obj));
// 方法返回一个给定对象自身可枚举属性的键值对数组。快速创建map结构
console.log(new Map(Object.entries(obj)));
//获取对象的描述对象(是否可写,枚举,删除)
console.log(Object.getOwnPropertyDescriptors(obj1));
es9扩展运算符&&rest参数对对象的操作
function fn({ age, sex, ...user }) {
console.log(age);
console.log(sex);
console.log(user);
}
fn({
age: 18,
sex: '男',
name: 'zs',
job: '前端'
})
let age = { age: 18 }
let sex = { sex: '男', }
let name = { name: 'zs' }
let job = { job: '前端' }
let user = { ...age, ...sex, ...job, ...name }
console.log(user);
es10对象扩展方法fromEntries
fromEntries:将二维数组,map转为对象
Object.entries对象转为二维数组
const result = Object.fromEntries([
['name', 'lise'],
['job', '前端']
])
const map = new Map()
map.set('name', 'zs')
const res = Object.fromEntries(map)
console.log(result);
console.log(res);
let data = Object.entries({
name: 'ww'
})
console.log(data);
es10字符串扩展方法
trimStart左侧空格
trimEnd右侧空格
let str = ' love '
console.log(str);
console.log(str.trimStart());
console.log(str.trimEnd());
es10数组扩展方法
flat数组将维
flatMap数组循环将维
let arr = [1, 2, 3, [4, 5, 6]]
let res = arr.flat()
console.log(res);
let result = res.flatMap(item => [item * 10])
console.log(result);
description获取Symbol字符串
let w = Symbol('ls')
console.log(w.description);
Promise.公有方法
Promise.allSettled promise 的状态始终是成功 保存着每一个promise的状态
Promise.all 有一个失败promise的状态就为失败
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功')
}, 1000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败')
}, 1000);
})
let res = Promise.allSettled([p1, p2])
let result = Promise.all([p1, p2])
console.log(res);
console.log(result);
可选链操作符
function fn(args) {
const res = args?.obj?.a
console.log(res);
}
fn({
b: 10,
// obj: {
// a: 1
// }
})
BigInt大整数
let max = Number.MAX_SAFE_INTEGER
console.log(max);
console.log(max + 1);
console.log(max + 2);
console.log(max + 8);
console.log(BigInt(max) + BigInt(10));