ES6
let
let声明的变量不能重复声明,只在当前作用域有效,不存在变量提升,虽然let声明的是块级作用域,但是并不影响作用域链
const
const声明一般必须要赋值,声明后常量就不可更改,声明也是块级作用域,const对于声明数组和对象的变量,修改数组和对象不算对常量的更改
解构赋值
按照一定模式从数组和对象中提取值,对变量进行赋值
数组解构
解构赋值都是一一对应的,按照顺序
const F4=['小沈阳','刘能','孙红雷','宋小宝'] let [xiao,liu,sun,song]=F4 console.log(xiao,liu,zhao,song)
也可以取某一个项的值(结构必须一致)
const F4=['小沈阳','刘能','孙红雷','宋小宝'] let [,,sun,]=F4 console.log(sun)//孙红雷
还可以使用扩展运算符提取(只能写在最后)
const F4=['小沈阳','刘能','孙红雷','宋小宝'] let [xiao,liu,...all]=F4 console.log(all)//['孙红雷','宋小宝'] 返回一个包含最后所有内容的数组
如果提取长度小于数组长度,则提取按照前后顺序进行
const F4=['小沈阳','刘能','孙红雷','宋小宝'] let [xiao,liu]=F4 console.log(xiao,liu)//小沈阳 刘能
如果提取长度大于数组长度,则提取的最后结果是undefined
const arr=[100,200] let [a,b,c]=arr console.log(c)//undefined
对象解构
对象解构和数组结构类似,不过对象解构是根据对象的属性名来进行取值的
const obj={ name:'小明', age:30, say(){ console.log(name+'今年'+age+'岁了') } } let {name,say}=obj console.log(name)//小明 say()//小明今年30岁了
如果解构出来的变量名与外边的变量名重复,就需要重新命名
const name='小花' const sya=function(){console.log('我饿了')} const obj={ name:'小明', age:30, say(){ console.log(name+'今年'+age+'岁了') } } let {name:nameObj,age,sayXiao}=obj console.log(nameObj)//小明 sayXiao()//小明今年30岁了
模板字符串
模板字符串:``
可以作为正常引号去使用
let str=`我是模板字符串`
可以在内容区出现换行,输出也会换行(正常引号不允许换行)
let str2=` <ul> <li>沈腾</li> <li>艾伦</li> </ul>`;//如果是单引号或双引号就需要使用+来拼接
变量拼接
let love='希儿' let love_most=`${love}我最喜欢` console.log(love_most)//希儿我最喜欢
对象的简写
let name='新东方' let change=function(){ console.log('新东方厨师') } const school={ name,//相当于name:name 就是将上面的name属性变成school对象的属性 change,//同理,change:change,将上面的change方法变成school的方法 improve(){//完整写法:improve:function(){} console.log('我们可以提高你的技能') } }
箭头函数
箭头函数是ES6非常重要的一个点,它的this是静态的,始终指向函数声明所在作用域下的this的值(无法改变),即函数本身所处的环境,默认指向父级对象
箭头函数适用于与this无关的回调:定时器,数组的方法回调
不适于与this有关的回调,事件回调,对象的方法
function getName(){ console.log(this.name) } let getName2=()=>{ console.log(this.name) } const name='新东方' const school={name:'蓝翔'} getName();//输出新东方 getName2();//输出新东方 getName.call(school);//输出蓝翔 getName2.call(school);//输出依旧是新东方,无法改变this指向
同时箭头函数无法作为构造函数实例化对象
const Person=(name,age)={ this.name=name this.age=age } const jakc=new Person('jack',23)//错误,无法实例化
箭头函数无法使用argument变量
argument变量:函数调用传入的实参形成的伪数组
let fn2=()=>{ console.log(argument) } fn2(1,2,3)//报错
箭头函数简写
省略小括号,当形参有且只有一个时
let add=n=>{ return n+n } console.log(add(9))
省略大括号,但代码语句只有一条时,此时return必须省略
let pow=n=>n*n console.log(pow(9))
箭头函数的作用域
const cd={ name:'新东方', getName2:function(){ console.log(this); } } cd.getName2();//输出为window
这里一般函数的this就是cd对象,箭头函数的this指向当前函数所处的作用域,按理来说也是cd对象,但是cd只是一个对象,没有作用域,所以箭头函数会继续向外寻找,最后就找到的是window
rest参数
arguments
用于获取函数实参
function date(){ console.log(arguments) } date('柏芝','希子')//输出柏芝,希子
rest
同样用于获取函数参数,用于取代arguments
function fn(...args){//...是写法,args是名称 console.log(args) } fn('阿娇','四惠')
如果有多个参数,rest参数必须放在最后
function fn(a,b,...c){ console.log(a)//输出1 console.log(b)//输出2 console.log(c)//输出3 4 5 6 } fn(1,2,3,4,5,6)
扩展运算符
样式:[...],扩展运算符可以将数组作为,分隔的参数序列
const tfboys=['易烊千玺','王俊凯','王源'] function chun(){ console.log(arguments) } chun(...tfboys)//这样就将tfboys数组转为了三个参数序列传入
还可以进行数组合并
const k=['曾毅','玲花'] const f=['王太利','肖央'] const unite=[...k,...f]//这样数组就合并完成了 console.log(unite)//输出['曾毅','玲花','王太利','肖央'] //如果采用老方法就需要 const unite=k.concat(f)
还可以进行数组克隆
const a=['E','G','M'] const b=[...a]//数组克隆完毕 console.log(b)//输出['E','G','M']
还可以将伪数组变成真正的数组
const divs=document.querySelectorAll('div') const divArr=[...div]//此时divArr就是一个真数组了
也可以将字符串变成数组
let str='hello word' console.log([...str])//(10)['h','e','l','l','o','','w','o','r','d']
还可以拆分数组
const a=['E','G','M'] console.log(...a)//输出 E G M
Symbol
Symbol是一种新增的基本数据类型,表示独一无二的值
Symbol的值是唯一的,用来解决命名冲突的问题
Symbol值不能与其他数据进行运算
Symbol定义的对象属性不能使用for..in进行循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
通过Symbol()创建Symbol类型
let s=Symbol() console.log(s,typeof s)//输出Symbol() 'symbol'
可以在Symbol()的括号内写入一个标识,用来描述这个Symbol类型
let s1=Symbol('新东方') let s2=Symbol('新东方') console.log(s1===s2)//返回false,虽然两个Symbol描述相同,但不是同一个
使用Symbol.for()创建
let s1=Symbol.for('新东方') let s2=Symbol.for('新东方') console.log(s1===s2)//返回true //通过Symbol.for创建的Symbol会在Symbol注册表寻找是否有相同描述的Symbol,如果有就返回这个,没有就新建
向对象中添加SSymbol类型方法
向对象中添加Symbol类型的属性或方法时,Symbol外边必须加上[]
方法一
let game={ name:'俄罗斯方块', up:function(){} } let method={ up:Symbol() down:Symbol() } game[method.up]=function(){//向game中添加method中的up属性,并为该属性添加一个方法 console.log('我可以快速上升') } //适用场景:当我们需要向一个复杂对象添加属性方法时,我们并不清楚该对象内部有哪些属性/方法,那么我们在添加过程中就难免会出现重名的错误,那么我们就可以使用Symbol来添加从而避免这种情况 game[method.up]()//调用Symbol定义的方法
方法二
直接在对象中添加
let game={ name:'狼人杀', [Symbol.for('say')]:function(){ console.log('我可以发言') }, [Symbol('boom')](){ console.log('我可以自爆') } } let say=Symbol.for('say') game[say]()//调用对象内部的Symbol方法
Symbol的一些内置属性
Symbol.hasInstance 当对其他对象使用Instance运算符时,判断是否为该对象的实例时,会调用这个方法
Symbol.isConcatSpreadable 对象的该属性对于是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开
Symbol.unscopables 该对象指定了使用with关键字时,哪些属性会被with环境排除
Symbol.match 当执行str.match(myObject)时,如果该属性存在,会调用他,返回该方法的返回值
Symbol.replace 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值
Symbol.search 当该对象被str.seach(myObject)方法调用时,会返回该方法的返回值
Symbol.split 当该对象被str.split(myObject)方法调用时,会返回该方法的返回值
Symbol.iterator 对象进行foe...of循环时会调用Symbol.iterator方法,返回该对象的默认遍历器
Symbol.toPrimitive 该对象被转为原始类型的值时,会调用这个方法返回该对象对应的原始类型值
Symbol.toStringTag 在该对象上调用toString方法时,返回该方法的返回值
Symbol 创建衍生对象时,会调用该属性
迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据经济只要部署Iterator接口,就可以完成遍历操作
ES6创建了一种新的遍历命令for...of循环,Iterator接口主要提供for...of消费,原生具备Iterator接口的数据(可以使用for...of)
Array,Arguments,Set,Map,String,TypedArray,NodeList这些数据类型都具有迭代器
const weth=['唐僧','孙悟空','猪八戒','沙悟净'] for(let v of weth){//使用迭代器的for..of遍历 console.log(v) }
对象不具有迭代器特性,但是如果要求使用迭代器去遍历,那么我们可以自己写一个迭代器
//自定义遍历数据 const banji={ name:"一班", stus:[ '小明', '小虎' ], [Symbol.iterator](){//迭代器 let index=0; let _this=this; return{ next:function(){ if(index<_this.stus.length){ const result={value:_this.stus[index],done:false} index++;//下标自增 return result; }else{ return{value:undefined,done:true}; } } } } } for(let v of banji){ console.log(v); }
生成器
生成器其实就是一个特色的函数,是用于解决异步编程,通过function *来定义
function * gen(){ console.log(111) yield '一只没有耳朵'//这里yield是函数的分隔符,函数运行到这就会停止,()里面的是表达式 console.log(222) yield '一只没有尾巴' console.log(333) yield '真奇怪' } //生成器函数调用需要使用next(),每一次调用就向下运行一步,相当于一个迭代器对象 //调用一次next()就执行一次,遇到yield就停止运行,返回yield的表达式,value是yield的描述,done表示当前函数是否执行完毕 let iter=gen() console.log(iter.next())//输出{value: '一只没有耳朵', done: false} console.log(iter.next())//{value: '一只没有尾巴', done: false} console.log(iter.next())//{value: '真奇怪', done: false} console.log(iter.next())//{value: undefined, done: true} //既然是迭代器,那么也可以是for...of遍历 for(let v of gen()){ console.log(v)//输出一只没有耳朵 一只没有尾巴 真奇怪 //返回的都是yield表达式 }
生成器的参数传递
由于生成器的调用方式不同,我们可以向生成器中传入多个参数赋值
function * gen(arg){ console.log(arg) let one=yield 111 console.log(one) let two=yield 222 console.log(two) } let iter=gen('AAA') console.log(iter.next()) //next()方法可以传入参数 console.log(iter.next('BBB'))//第二次调用传入的实参作为第一个yield的返回结果,即one的值为AAA console.log(iter.next('CCC'))//第三次调用传入的实参作为第一个yield的返回结果,即two的值为BBB /*执行结果为 AAA {value:111,done:false} BBB {value:222,done:false} CCC {value:undefined,done:true} */
生成器函数实例
js是单线程异步的,文件操作,网络操作,数据库操作都是异步编程
需求:1s后控制后台输出111,2s后输出222,3s后输出333
//纯用定时器也能实现,共耗时6s //但是如果回调操作多了,就会形成回调地狱 setTimeout(()=>{ console.log(111) setTimeout(()=>{ console.log(222) setTimeout(()=>{ console.log(333) },3000) },2000) },1000) //使用生成器 function one(){ setTimeout(()=>{ console.log(111) iter.next();//定时器是异步操作,此时let iter=gen()已经执行完毕,所以定时器内可以使用iter.next() },1000) } function two(){ setTimeout(()=>{ console.log(111) iter.next(); },1000) } function three(){ setTimeout(()=>{ console.log(111) iter.next(); },1000) } function * gen(){ yield one() yield two() yield three() } let iter=gen() iter.next()
需求:模拟获取 用户数据 订单数据 商品数据,先获取用户数据,在获取商品数据,最后获取订单数据
function getUsers(){ setTimeout(()=>{ let data='用户数据'; iterator.next(data);//继续调用next,并传入数据,这样在生成器函数就可以获取数据 },1000) } function getOrders(){ setTimeout(()=>{ let data='订单数据'; iterator.next(data); },1000) } function getGoods(){ setTimeout(()=>{ let data='商品数据'; iterator.next(data); },1000) } function * gen(){ let users=yield getUsers() console.log(users) let orders=yield getOrders() console.log(orders) let goods=yield getUserGoods() console.log(goods) } let iterator=gen() iterator.next()
Promise
Promise也是用于解决异步编程的,语法上是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
//实例化Promise对象 const p=new Promise(function(resolve,reject){//resolve和reject这两个参数是Promise的两个方法,可以自己取 setTimeout(function(){ let data='数据库中的数据'; resolve(data); let err='数据读取失败'; reject(err); },1000) }); //调用promise的then方法 p.then(function(value){//数据读取成功调用第一个回调 console.log(value); },function(reason){//数据没有读取成功就调用第二个调用 console.error(reason); })
promise封装读取文件
//引入fs模块 const fs=require('fs'); //调用方法读取文件 fs.readFile('./resources/为学.md',(err,data)=>{ //如果失败,抛出错误 if(err) throw err; //如果没有出错,输出内容 console.log(data.toString()); }); //使用Promise封装 const p=new Promise(function(resolve,reject){ fs.readFile('./resources/为学.md',(err,data)=>{ //如果失败 if(err) reject(err); //如果成功 resolve(data); }) }); p.then(function(value){ console.log(value.toString()); },function(reason){ console.log("读取失败"); })
对于Promise,返回的是非Promise类型,那么状态为成功,返回值为对象的成功值,返回的是Promise类型,Promise的状态就是回调函数的状态,返回的是异常,回调函数的返回值就是抛出的异常
Promise的catch方法
用于设置promise对象失败的一个回调
const p=new Promise((res,rej)=>{ rej('失败') }) p.catch(function(res){ console.log(res) })
集合
集合也是用于存储数据,具有迭代器,可以使用for..of遍历
集合具有唯一性,会自动去掉内部重复项
//声明集合 let s=new Set() let s1=new Set([1,2,3,4]) //集合元素个数 console.log(s1.size)//4 //向集合中添加(添加到最后位置) s1.add('5') //删除集合中元素 s1.delete(5) //检测集合是否包含某元素 console.log(s1.has(2)) //清空集合 s1.clear() //使用for of遍历 for(v of s1){ console.log(v) }
集合的使用
利用集合的唯一性,我们可以进行数组去重
let arr=[12,3,4,4,5,6,6] let res=[...new Set(arr)]//使用扩展运算符将集合变成数组 console.log(res)
利用集合求交集
let arr1=[12,3,4,6,3,4] let arr2=[12,4,7,3,4,5,6] let result=[... new Set(arr1)].filter(item=>{ let res=new Set(arr2) if(res.has(item)){ return true }else{ return false } }) console.log(result)
利用集合求并集
let arr1=[12,3,4,6,3,4] let arr2=[12,4,7,3,4,5] let result=[... new Set([...arr1,...arr2])] console.log(result)
利用集合求差集(即两个集合相比,只存在于一个集合的元素)
let arr1=[12,3,4,6,3,23,56] let arr2=[12,4,7,3,4,5,6] let result=[... new Set(arr1)].filter(item=>{ let res=new Set(arr2) if(res.has(item)){ return false }else{ return true } }) console.log(result)
MAP
Map类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值(包括对象)都可以当作键
Map也实现了iterator接口,所有可以使用扩展运算符和for...of进行遍历。
Map的属性和方法
size 返回Map的元素个数
set 增加一个元素,返回当前Map
get 返回键名对象的键值
has 检测Map中是否有某个元素,返回boolean
clear 清空集合,返回undefiend
//声明MAP let m=new Map() m.set('name','新东方') m.set('change',function(){ console.log('我们可以改变你') }) let key={ school:'ATGUIGN', } m.set(key,['北京','上海','深圳'])//通过key对象向m中添加元素 console.log(m) console.log(m.size)//3 //删除,通过键名进行删除 m.delete('name') //读取,通过键名进行读取 m.get('change') //读取,通过对象读取 m.get(key) //遍历,遍历结果为三个数组 for(let v of m){ console.log(v) } //清空 m.clear()
Class类
class类基于已有的对象系统,提供了更简洁和强大的方式来创建和组织对象
class Phone{ //constructor是类的构造函数,一般用于初始化对象状态 constructor(brand,price){//名称固定,实例化时自动执行 this.brand=brand this.price=price } call(){//语法固定,不能使用call:function(){}语法 console.log('我正在打电话') } } let onePlus=new Phone('华为',1999) console.log(onePlus) onePlue.call()
class的静态成员
使用static修饰的属性/方法称为静态属性/方法
静态成员只属于class类,不属于创建的实例对象,因此无法使用实例对象调用静态成员
class Phone{ static name='手机' static change(){ console.log('换手机') } } let phone=new Phone() console.log(use.name)//无法调用,name不属于phone,属于Phone console.log(Phone.name)//可以调用
class的继承
class类的继承需要使用extends关键字
class Phone{ constructor(brand,price){ this.brand=brand this.price=price } call(){ console.log('我在打电话') } } //进行继承 class SmartPhone extends Phone{ constructor(brand,price,color,size){ super(brand,price)//继承父类的实例属性 this.color=color this.size=size } photo(){ console.log('我可以拍照') } game(){ console.log('我可以打游戏') } call(){//通过重写父类的call方法,可以覆盖掉父类的该方法 console.log('我在打视频电话') } }
get与set
get将对象属性与函数进行绑定,属性被访问时,函数立即执行 set将对象属性与函数进行绑定,属性被赋值时,函数立即执行
class Phone{ constructor(pric){ this.pric=pric } get price(){ console.log("价格已经传入"); return this.pric; } set price(Val){ this.pric=Val console.log("价格已经改变"); } } let s=new Phone(1200); console.log(s.price);//访问s的price方法,get price立即执行 console.log(s.price=1000);//赋值,set price立即执行,赋值作为set函数的返回值
数值扩展
js表示的最小精度为Number.EPSILON,无限趋向于2.22E-16,js认为两个数之间的差值小于EPSILON就是相等的
console.log(0.1+0.2===0.3)//这里输出为false,原因是因为底层的二进制导致的 //解决 function equal(a,b){ if(Math.abs(a-b)<Number.EPSILON){//Mtah.abs()取绝对值 return true }else{ return false } } console.log(equal(0.1+0.2,0.3))//这里输出就为true
表示进制
let b = 0b1010;//二进制:0b+二进制 let o = 0o777;//八进制:0o+八进制 let d = 100;//十进制 let x = 0xfff;//十六进制:0x+十六进制 console.log(x)//输出会自动转为十进制
数值扩展方法
//Number.isFinite 检测一个数是否是有限数 console.log(Number.isFinite(100));//true console.log(Number.isFinite(100 / 0));//false //Number.isNaN 检测一个数值是否是NaN console.log(Number.isNaN(123));//false //Number.parseInt 截取字符串中数字为整型,无法截取小数点后面,遇到非数字停止截取 //Number.parseFloat 截取字符串中数字为浮点型,能截取小数点后面(只认第一个小数点),遇到非数字停止截取,e除外,会被当成数学符号 //两种方式没有截取到均返回NAN,均可以将其他进制转为十进制 console.log(Number.parseInt('11223love'));//11223 console.log(Number.parseFloat('2.12113s生器'));//2.12113 //Number.isInteger 判断一个数是否为整数 console.log(Number.isInteger(12));//true //Math.trunc 将整数的小数部分抹掉 console.log(Math.trunc(3.89));//输出3 //Number.sign判断一个数是正数还是负数还是零 console.log(Math.sign(100));//正数返回1 console.log(Math.sign(-100));//负数返回-1 console.log(Math.sign(0));//零返回0
对象方法扩展
//1.Object.is 判断两个值是否完全相等,与===基本类型 console.log(Object.is(120,120));//返回true //和全等号===的区别 console.log(Object.is(NaN,NaN));//返回true console.log(NaN===NaN);//返回false console.log(Object.is(+0,-0));//返回false console.log(+0===-0);//返回true //2.Object.assign 对象合并 const config1={ host:'localhost', post:3306, }; const config2={ host:'http://atguigu.com', name:'atguigu.com', } console.log(Object.assign(config1,config2)); //如果有重名的,则config2覆盖consig1,即后面的覆盖前面的 //3.Object.setPrototypeOf 设置原型对象 //3.Object.getPrototypeOf 获取原型对象 const school={ name:'新东方' } const cities={ xiaoqu:['北京','上海'] } Object.setPrototypeOf(school,cities);//将cities对象设置为school的原型 console.log(school); console.log(Object.getPrototypeOf(school));//获取school的原型
模块化
模块的暴露方式
//分别暴露 export let school='新东方' export function b(){} //统一暴露 let school='新东方' function b(){} export (school,b) //默认暴露(暴露对象,但是没有对象名) export default{ school:’新东方 b(){} }
模块化导入方式
//通用方式 *表示导入全部 as取别名 import * as m1 from '../main.js' //解构赋值形式,对于默认暴露,如果暴露的是对象,也需要使用别名,因为默认暴露没有对象名 import {school as m2} from '../main.js' //简便形式(只能用于默认暴露的模块) import m3 from '../main.js'
在实际中并不是所有浏览器都兼容所有的导入方式,所有我们在项目中经常使用babel进行转换,可以将es比较新的语法转为浏览器可以识别的语法
安装工具 babel-cli(命令行工具) babel-praset-env(预设包,转换代码) browserify(打包工具,项目中一般使用webpack)
1.终端输入npm init -yes(初始化)
2.安装(需要先安装Node.js),输入npm i babel-cli babel-preset-env browserify -D
3.转换 npx babel 源文件目录 -d 保存到的目录 --presets=babel-preset-env
npx babel ES\模块 -d dist\转换 --presets=babel-preset-env
4.打包 npx browserify 文件目录 -o 输出位置
npx browserify dist/转换/19-4模块化4.js -o dist/bundle4.js
ES7
includes
includes用来判断数组是否包含某个元素,返回布尔值
const zhu=['西游记','红楼梦','三国演义','水浒传'] console.log(zhu.includes('西游记'))//返回true
另一个indexOf返回的下标,没有返回-1
幂运算
使用**来实现幂运算
console.log(2**2)//输出4 //等价于 console.log(Math.pow(2,2))
ES8
async与await
async和await语法结合可以让异步代码和同步代码一样
async函数返回值是promise对象
promise对象的结果由async函数执行的返回值决定
async function fn(){ return '新东方'//返回的不是promise对象,结果为成功 return new Promise((resolve,reject)=>{ resolve('成功')//返回为成功的promise reject('失败')//返回的为失败promise }) }
awiat函数必须写在async函数中,await返回的是promise的值,await的promise失败了,就会抛出异常,可以通过try...catch捕获
const p=new Promise((resolve,reject)=>{ //reject('失败') resolve('成功') }) async function main(){ try{ let result=await p }catch(e){ console.log(e) } }
对象方法扩展
const school={ name:'新东方', cities:['北京','上海','深圳'], } //Object.keys 获取对象所有的键名(数组形式) console.log(Object.keys(school)) //Object.values 获取对象所有的值(数组形式) console.log(Object.values(school)) //Object.entries 返回一个将键名和键值组合起来的数组 console.log(Object.entries(school)) //Object.entries 可以用来创建MAP const m=new Map(Object.entries(school)) console.log(m.get('name')) //Object.getOwnPropertyDescriptors 返回对象属性的描述对象 console.log(Object.getOwnPropertyDescriptors(school)) //属性描述对象 writable,configurable,enumerable等,可以用于深层次的对象克隆
ES9
扩展运算符
function connect({host,...user}){//...user将剩下的对象存入 console.log(host) console.log(user) } connect({ host:'127.0.0.1', uaername:'root', password:123 }) //对对象的合并 const SkillOne={q:'金钟罩'} const SkillTwo={w:'金钟罩'} const mangsen={...SkillOne,...SkillTwo}//合并对象
正则表达式
边界符
//:匹配有其中内容的
^$:匹配有其中的内容开头且结尾的
let reg1=/123///匹配含有123的字符 console.log(reg1.test('ww123df'))//返回true let reg2=/^abc$/ //匹配以abc开头的字符 console.log(reg2.test('abc'))//返回true console.log(reg2.test('1abc1'))//返回false
字符
[] 匹配其中任意一个字符
let reg1=/[abc]///只要包含a或b或c就为true console.log(reg1.test('wes'))//返回false console.log(reg1.test('wbs'))//返回true let reg2=/^[abc]$///匹配只以a或b或c开头结尾的,即只能是a或b或c console.log(reg2.test('ab'))//返回false console.log(reg2.test('c'))//返回true let reg3=/^[a-z]$///匹配以英文字母表a-z开头结尾的,即只能输入a-z中的一个 console.log(reg3.test('f'))//返回true let reg4=/^[^-_]$///[]内部的^表示取反,这里表示匹配非下划线 console.log(reg4.test('_'))//返回false console.log(reg4.test('f'))//返回true let reg5=/^[a-zA-Z0-9_]$///匹配大小写字母,数字0-9及下划线 console.log(reg5.test('A'))//返回true console.log(reg5.test('9'))//返回true console.log(reg5.test('$'))//返回false
量词符
* 表示可以出现任意次
+ 表示可以出现1次及以上
? 表示只能出现0次或1次
{2} 表示连续出现2次
let reg1=/a*/ //a可以出现任意次 console.log(reg1.tset('123'))//返回true console.log(reg1.tset('aa'))//返回false let reg2=/a+/ //a可以出现一次及以上 console.log(reg2.test('123')) console.log(reg2.test('a')) let reg3=/a?/ //a只能出现0次或1次 console.log(reg3.test('a')) console.log(reg3.test('aaa')) let reg4=/a{3}/ //a连续出现3次 console.log(reg4.tset('dsdaaaqw')) let reg6=/a{3,}/ //a连续出现大于等于3次 let reg7=/a{3,5}/ //a连续出现次数范围在3-5之间,左闭右开 let reg8=/^(ab){2}/ //连续出现两次ab,且为开头结尾 let reg9=/^[a-zA-Z0-9_-/{5,10}$/ //限制输入只能为大小写字母,数字,下划线,中线,且长度为5-10
ES10
对象扩展方法
//Object.fromEntries用于创建一个对象,参数是一个二维数组或Map,即将二维数组或Map转为对象 //二维数组 const res=Object.fromEntries([ ['name':'尚硅谷'], ['project':'Java,前端'] ]) console.log(res) //Map const m=new Map() m.set('name','ATGUIGU') const result=Object.fromEntries(m) console.log(result)
字符串扩展方法
//trim() 用于清除字符串两边的空白字符 //trimStart()(清除左边空白字符)和trimEnd()(清除右边空白字符) let str=' iloveyou ' console.log(str.trim()) console.log(str.trimStart()) console.log(str.trimEnd())
数组扩展方法
//flat()将数组维度降低 const arr1=[1,2,3,4,[5,6,7]] console.log(arr1.flat(1))//参数为数字,表示降几层,默认1,此时为[1,2,3,4,5,6,7] //flatMap()对数组内容进行批量操作 const arr2=[1,2,3,4] const res=arr2.flatMap(item=>[item*10]) console.log(res)//输出为[10,20,30,40]
提取Symbol描述
let s=Symbol('尚硅谷') console.log(s.description)//输出为尚硅谷
ES11
类的私有属性
class Person{ name;//公有属性 #age;//私有属性 constructor(name,age){ this.name=name this.#age=age } intro(){ console.log(this.name) console.log(this.#age) } } const girl=new Person('小哥',11) console.log(girl.#age)//实例对象无法访问 console.log(Person.#age)//类也无法访问 girl.intro()//可以访问 输出 小哥 11
Promise.allSettled
Promise.allSettled接收一个Promise数组,返回一个Peomise对象,返回永远成功,值为某一个Promise的状态结果
const p1=new Promise((resolve,reject)=>{ setTimeout(() => { resolve('商品数据-1'); }, (1000)) }); const p2=new Promise((resolve,reject)=>{ setTimeout(() => { //resolve('商品数据-2'); reject('失败了'); }, (1000)); }); const result=Promise.allSettled([p1,p2]) console.log(result) //result的结果永远成功,如果传入的promise中有失败的,会在result中体现出来 //比如这里的值就是 //[[PromiseResult]] //Array(2) //0: {status: 'fulfilled', value: '商品数据-1'} //1: {status: 'rejected', reason: '失败了'}
Promise.all
Promise.all接收一个Promise数组,数组内所有promise对象成功才返回成功,否则就失败
const result=Promise.all([p1,p2])
字符串扩展matchAll
//用来得到正则批量匹配的结果 let str=` <ul <li> <a>肖申克的救赎</a> <p>上映日期:1994-09-10</p> </li> <li> <a>阿甘正传</a> <p>上映日期:1994-07-06</p> </li> </ul>`; //声明正则 const reg=/<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg //调用正则 const result1=str.matchAll(reg); console.log(result1);//可以发现结果有next方法,所有可以使用for...of进行遍历 for(let v of result1){ console.log(v); } //使用扩展运算符展开 const arr=[...result1]; console.log(arr);
可选链
可选链操作符: ?. 前面为真才执行下一步操作
当我们应对对象类型层级比较深,而我们需要取进行判断时可以使用
function main(config){ //这里就是在先判断config参数是否传入,传入就继续判断下一个,最终返回最后判断的结果,即前面为真才执行下一步 const dbhost=config?.db?.host console.log(dbhost) } main({ db:{host:'127.1.1.1'} cache:{} })
动态导入模块
//实际开发中,我们一般会在一个js中导入许多模块,但是其中有一些我们可能不需要,就不能实现按需加载 //静态导入,不论你现在用不用,反正先导入 import * as m1 from './hello.js' //动态导入,实现按需加载 btn.oncilck=function(){ import('./hello.js').then(m1=>{//import返回是一个promise对象 m1.hello() }) }
BigInt类型
BigInt:大整型 一般用于大数字计算
let num=521n //n就表示大整型 console.log(n,typeof(n)) //将其他类型变为大整型,不能使用浮点型 let m=123 console.log(BigInt(m)) //用于大数字计算 let max=Number.MAX_SAFE_INTEGER//这是js的最大安全数值 console.log(max+1)//无法继续增大 console.log(BigInt(max)+BigInt(3))//可以继续增大
绝对全局变量
globlThis:字面意思,无论执行文件,始终指向window
想操作全局变量时,就可以使用globThis直接操作从而忽略当前环境