总结归纳
ES 新增运算符的实例:
-
可选链运算符(Optional Chaining Operator):
const person = { name: 'John', age: 30 }; const address = person?.address?.street; // 不会报错,返回undefined
-
空值合并运算符(Nullish Coalescing Operator):
const name = null; const defaultName = 'Unknown'; const result = name ?? defaultName; // 返回 'Unknown'
-
大于等于和小于等于的合并运算符(Greater/Less Than or Equal To Operator):
const x = 1; const y = 2; const result = x <=> y; // 返回 -1
-
指数运算符(Exponentiation Operator):
const x = 2; const result = x ** 3; // 返回 8
-
展开语法(Spread Syntax):
const arr = [1, 2, 3]; const newArr = [...arr, 4, 5, 6]; // [1, 2, 3, 4, 5, 6]
-
Object.assign()
方法:const obj1 = { a: 1 }; const obj2 = { b: 2 }; const obj3 = { c: 3 }; const newObj = Object.assign({}, obj1, obj2, obj3); // { a: 1, b: 2, c: 3 }
对数组的操作
操作类型 | 方法名 | 描述 |
---|---|---|
栈操作(先进后出) | push() | 向数组末尾添加一个或更多元素,并返回数组长度 |
pop() | 删除返回数组最后一个元素 | |
队列操作(先进先出) | unshift() | 向数组的开头添加一个或更多元素,并返回数组长度 |
shift() | 删除返回数组第一个元素 | |
排序方法 | soft((a-b)=>return a-b) | 按照字符串顺序对数组进行排序 |
reverse() | 反转数组 | |
concat() | 把参数拼接到当前数组 | |
操作方法 | slice() | 从当前数组截取出一个新数组,不影响原数组 |
splice() | 删除或替换当前数组的某些项目,参数start、del、options(要替换的项) | |
arr=[ ] | 清空数组 ; | |
位置方法 | indexof() | 搜索数组中的元素,并返回位置,没找到返回-1 |
lastindexof() | 搜索数组中的元素,并返回最后出现的位置,没找到返回-1 | |
array[index] | 数组索引对应的数组值 | |
过滤 | for(i=0;i<*.length;i++){} | 最原始的for,i为遍历的次数,初始值任意 |
for…in | 遍历出index索引,类似for…i,但不可设置初始值 | |
for…of | 遍历出每一个子项具体value | |
every() | 检测数值元素的每个元素是否都符合条件,返回bool | |
filter((item,value)=>{ }) | 过滤,检测数组元素,并返回符合条件元素的数组 | |
foreach((item,index)=>{}) | 数组每个元素都执行一次回调函数,功能为for…in+for…of | |
map() | 通过制定函数处理数组每个元素,并返回处理后的数组 | |
some() | 检测数组元素中的是否有符合指定条件,有一个就跳出循环了 | |
new Set( ) | 数组去重 | |
join() | 把数组的所有元素连接到一个字符串中 |
1.Set
let s = new Set()//集合 不重复唯一 只有键
//元素个数
console.log(s.size)
//添加新元素
s.add("aaa")
//删除元素
s.delete("aaa")
//检测元素
s.has("aaa")
//清空
s.clear()
//集合有迭代器的接口,所以可以用for...of遍历
for(let i of s){
console.log(i)
}
1.1集合实践
let arr = [1,2,2,3,4,6]
//1.数组去重
//先将其变为 集合 去重
//将 集合 转为 数组
//let s = [...new Set(arr)]
//console.log(s)
//2.交集
let arr2 = [4,5,6,5,6]
/* let result = [...new Set(arr)].filter(items=>{
let s2 = new Set(arr2)//4 5 6 集合
if(s2.has(items)){
return true
}else{
return false
}
}) */
//简化写法
//let result = [...new Set(arr)].filter(items=>new Set(arr2).has(items))
//console.log(result)
//3.并集
//let union = [...new Set([...arr2,...arr])]
//console.log(union)
//4.差集
let diff = [...new Set(arr)].filter(items=>!(new Set(arr2).has(items)))
console.log(diff)
2.Map
键值对的集合,其“键”不限于字符串,可以是各种类型,Map也实现了iterator接口和扩展运算符,升级版对象,其属性可以是其他类型不只字符串
let m = new Map()
//添加元素
m.set("a",1)
m.set("fn",function(){
console.log("b")
})
let key = {
name:"let"
}
m.set(key,["a","b","c"])
//size获取元素个数
//delete删除元素
//get获取元素
//clear清空
//for...of遍历 [键,值]
ES6
var/let/const
-
var的缺点:
- var关键字 定义的变量 没有 块作用域,只有函数作用域
- var定义全局变量会自动添加全局 window对象属性
- var 定义的变量 会提前 装载。
-
var 和 let 区别 ,面试题
- var 可以被重复定义, let 不行
- var 会声明提升, let 不会
- var 声明的 全局变量会成为window上面的一个属性。而let 不会
- var 是 函数级作用域,let 是 块级作用域!!!
-
const:
- 常量必须 附上初始值!!!
- 常量 也有 块级作用域!!
- 数组 也可以被定义成 常量
- 数组可以根据下标更改值
-
var,let,const区别
- var 级别作用域 存在变量提升 值可以更改
- let 块级作用域 不存在变量提升 值可以更改
- const 块级作用域 不存在变量提升 值不可以更改
解构赋值
ES6中允许按照一定模式从数组和对象中提取值。对变量进行赋值,相当于破坏其原有结构,直接将值赋给新变量,下次直接用新变量就行
//1.数组解构
const arr = ['A','B','C']
let [a,b,c] = arr
console.log(a)//A
console.log(b)//B
console.log(c)//C
//2.对象解构
const obj = {
name:'lei',
age:23,
city: function(){
console.log("重庆")
}
}
//属性名和变量名要一样!
let {name,age,city} = obj
console.log(name)//lei
console.log(age)//23
console.log(city)//function
city()//重庆
//3.在获取网络请求数据时
this.$axios({
url:"www.baidu.com",
method:"get",
success:(data)=>{
const {data:res}=response
//效果 => const res=response.data,看不出简便,但是up主们都喜欢这样写
}
})
模板字符串
let str = [`字符串`]
//1.可以有HTML标签
//2.变量拼接
let str ='ssss'
let str1 = 'aaaa'
let str2 = `${str}${str1}`
简化对象写法
ES6允许在大括号里面,直接写入变量和函数,前提要声明赋值,作为对象的属性和方法
let name = 'a'
let change = function(){
console.log("b")
}
const sss = {
name,
change,
//improve:function(){
//console.log("b")
//} 方法简写
improve(){
console.log("b")
}
}
箭头函数
let fn = (a,b) => {// =>相当于function
return a+b
}
fn(1,2)//3
//1.this静态,this 总是指向 函数定义时 所在 作用域 下的this值!任何方式均不能改变指向
function getName() {
console.log(tihs.name)
}
let getName2 = () => {
console.log(tihs.name)
}
const city = {
name:'重庆'
}
window.name = '成都'
//直接调用,均为成都
//call
getName.call(city)//重庆
getName2.call(city)//成都
//2.不能作为构造函数去实例化对象
//3.不能使用arguments变量
//4.箭头函数简写
//1)省略(),当形参有且只有一个
let add = n =>{
return n+n
}
//2)省略{},当代码体只有一条语句,此时return省略,且执行结果就是函数返回值
let add = n => n+n
console.log(add(3))//6
//箭头函数适合与 this无关 的回调,如计时器,数组方法回调
参数默认值设置
//1.形参默认值,有默认值的一般靠后
function add(a,b=2){
return a + b
}
let c = add(1)
console.log(c)//3
//2.与解构赋值结合
function con({v1,v2,v3='c'}){
console.log(v1)
console.log(v2)
console.log(v3)
}
//调用con函数相当于 {v1,v2} = {v1:'a',v2:'b'} //解构赋值
con({
v1:'a',
v2:'b'
})//a b c
rest参数
获取函数的实参,代替arguments
//ES5获取实参的方式
function data(){
console.log(arguments)
}
data('a','b','c')//返回的对象
//rest参数,必须放到参数的最后!
function data(A,...args){
console.log(A,args)
}
data('a','b','c')//a ['b','c']
…扩展运算符
将数组转换为逗号分隔的参数序列,化整为散/化散为整
const name = ['a','b','c']
function fn(){
console.log(arguments)//返回的是object类型
}
// fn(['a','b','c'])
fn(name)//{['a','b','c']}
// 使用扩展运算符后 => fn('a','b','c')
fn(...name)//{'a','b','c'}
//1.数组合并
const a1 = ['1','2']
const a2 = ['3','4']
const a3 = [...a1,...a2]
console.log(a3)//['1','2','3','4']
//2.数组克隆
const b1 = [5,6,7]
const b2 = [...b1]
console.log(b2)//[5,6,7] 浅拷贝 有引用数据类型也是 拷贝其地址值
//3.伪数组转真数组
const divs = documentquerySelectorAll('div')
const divArr = [...divs]
Symbol
ES6新引入的原始数据类型,表示独一无二的值,类似于字符串的数据类型,第一次看不懂正常,等过段时间在回过头看就可以理解了
使用场景:
- 一些值不能重复的地方(例如:下面讲的es6的生成器)
特点:
- 值是唯一的,用来解决命名冲突的问题
- 值不能与其他数据进行运算
- 其定义的对象属性不能使用for…in循环遍历,但可以使用Reflect.ownKeys来获取对象的所有键名
let s = Symbol()//Symbol不是一个 构造 函数,所以s不是实例对象
console.log(s,typeof s)//Symbol() "symbol"
let s1 = Symbol('描述字符串')
let s2 = Symbol('描述字符串')
console.log(s1 === s2)//false 描述可以相同,但其id不同有点类似不同对象的地址值
//Symbol.for 创建 Symbol为函数对象
let s3 = Symbol.for('a')
let s4 = Symbol.for('a')
console.log(s3 === s4)//true
//不能与其他数据进行运算(任何)
//向对象添加属性和方法
let game = {}
//再声明一个对象
let methods = {
up:Symbol("向上"),
down:Symbol("向下")
}//注意这两个相同,可以理解为俩个地址值
//添加
game[methods.up] = function(){
console.log("上")
}
game[methods.down] = function(){
console.log("下")
}
//尽管原对象内有up或者down的方法也不影响,相当于加的Symbol("向上")和Symbol("向下"),独立的
let game ={
name:'lol',
[Symbol('hero')]:function(){//Symbol('hero')动态的并不跟name一样固定所以加[]
console.log('yasuo')
}
}
console.log(game)//要调用Symbol则在外部声明变量存储,属性名改为变量,再对象.方法调用
复制代码
Symbol内置属性
//自定义类型检测
class Person{
static [Symbol.hasInstance](param){
console.log(param)
}
}
let o = {}
console.log(o instanceof Person)
//决定数组是否展开
const arr = [1,2,3]
const arr1 = [2,2,3]
arr1[Symbol.isConcatSpreadable] = false//Symbol属性再作为对象属性的扩展
console.log(arr.concat(arr1))//[1, 2, 3, Array(3)]
复制代码
迭代器
一种接口,部署Iterator接口(对象里的一个属性,Symbol.iterator),完成遍历
- ES6创造了一种新的遍历命令 for…of循环,由Iterator操作
- 能具备iterator接口的数据
- Arry
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
const arr = ['a','b','b']
for(let a in arr){//in 是索引
console.log(a)//0,1,2
}
//迭代器
for(let a of arr){//of 是键值
console.log(a)//'a','b','b'
}
-
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,直到最后一个成员
- 每调用next方法返回一个包含value和done属性的对象
【注意】需要自定义遍历数据时,要想到使用迭代器
const name = ['a','b','c']
//创建指针对象
let iterator = name[Symbol.iterator]()
//调用对象的next方法
console.log(iterator.next())//{value: 'a', done: false}
console.log(iterator.next())//{value: 'b', done: false}
console.log(iterator.next())//{value: 'c', done: false}
console.log(iterator.next())//{value: undefined, done: true}
//迭代器应用
//声明一个对象
const ban = {
name:'a',
stu:[
'x',
'y',
'z'
],
[Symbol.iterator](){
//索引变量
let index = 0
let _this = this
return {
next:function(){
if(index < _this.stu.length){
const res = {value:_this.stu[index],done:false}
//下标自增
index++
//返回结果
return res
}else{
return {value:undefined,done:true}
}
}
}
}
}
//针对性遍历这个对象
for(let i of ban){
console.log(i)
}
复制代码
Generator函数( 生成器 yeild)
ES6提供的一种异步编程解决方案,一种特殊的函数
function * gen (){// * 生成器函数
console.log('a')
yield 'lllll'// yield函数代码分隔符 类型matlab间隔符执行
console.log('b')
}
let ietrator = gen ()//迭代器对象
ietrator.next()//a 是一个迭代器 ,需要next()才能输出,跟传统函数有出入
ietrator.next()//b
/* ******* */
function * gen (){// * 生成器函数
yield 'lllll'// yield函数代码分隔符 类型matlab间隔符执行
yield 'aaaaaa'
yield 'vbbbbb'
}
let ietrator = gen ()//迭代器对象
console.log(ietrator.next())//{value: 'lllll', done: false}
console.log(ietrator.next())//{value: 'aaaaaa', done: false}
console.log(ietrator.next())//{value: 'vbbbbb', done: false}
console.log(ietrator.next())//{value: undefined, done: true}
for(let i of gen()){
console.log(i)
}//lllll aaaaaa vbbbbb
复制代码
生成器函数参数
{
// 传统函数
function foo() {
return 'hello world'
}
foo() // 'hello world',一旦调用立即执行
// Generator函数
function* generator() {
yield 'status one' // yield 表达式是暂停执行的标记
return 'hello world'
}
let iterator = generator() // 调用 Generator函数,函数并没有执行,返回的是一个Iterator对象
iterator.next() // {value: "status one", done: false},value 表示返回值,done 表示遍历还没有结束
iterator.next() // {value: "hello world", done: true},value 表示返回值,done 表示遍历结束
}
生成器函数实例
//异步编程 文件操作 网络操作(ajax,request)数据库操作
//1s后 控制台输出 111 2s后输出222 3s后输出333
//回调地狱 不停回调 一直嵌套
setTimeout(() => {
console.log(111)
setTimeout(() => {
console.log(222)
setTimeout(() => {
console.log(333)
}, 3000);
}, 2000);
}, 1000);
//生成器函数解决回调地狱
function one(){
setTimeout(() => {
console.log(111)
iterator.next()//调用执行yield two()
}, 1000);
}
function two(){
setTimeout(() => {
console.log(222)
iterator.next()//调用执行yield three()
}, 2000);
}
function three(){
setTimeout(() => {
console.log(333)
iterator.next()//调用执行.......可以解决回调地狱
}, 3000);
}
function * gen(){//依次迭代调用
yield one()
yield two()
yield three()
}
//调用生成器函数
let iterator = gen()
iterator.next()//每调用一次执行一次
//生成器函数依次获取用户数据 订单数据 商品数据
function users(){
setTimeout(() => {
let data = 'user'
ite.next(data)//第二次调用执行yield orders() 并将data作为参数传入users
}, 1000);
}
function orders(){
setTimeout(() => {
let data = 'orders'
ite.next(data)//调用执行yield goods() 参数传入orders
}, 1000);
}
function goods(){
setTimeout(() => {
let data = 'goods'
ite.next(data)//第四次调用,参数传入goods
}, 1000);
}
function * gen(){//依次迭代调用
let users1 = yield users()
console.log(users1)
let orders1 = yield orders()
console.log(orders1)
let goods1 = yield goods()
console.log(goods1)
}
let ite = gen()
ite.next()//第一次调用 yield users()
*Promise
ES6引入的异步编程新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
- Promise 构造函数:Promise(excutor){}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
//实例化Promise对象
const p = new Promise(function(resolve,reject){
setTimeout(() => {
/* let data = 'data'
resolve(data)//执行resolve表明调用成功 */
let data = 'error'
reject(data)//执行reject表明调用失败,执行.then中的第二个回调函数
}, 1000);
})
//调用promise对象的then方法
p.then(function(value){
console.log(value)//执行resolve后
},function(reson){
console.log(reson)//执行reject后
})
//Promise封装AJAX请求
//接口地址:https://api.apiopen.top/getJoke
const p =new Promise((resolve,reject) => {
//1.创建对象
const xhr = new XMLHttpRequest()
//2.初始化
xhr.open("GET","https://api.apiopen.top/getJoke")
//3.发送
xhr.send()
//4.绑定事件
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status>=200&&xhr.status<300){
//请求成功
resolve(xhr.response)
}else{
//请求失败
reject(xhr.response)
}
}
}
})
//把请求结果提取出来,在外面进一步处理,不用在内部处理
p.then(function(value){
console.log(value)
},function(reason){
console.error(reason)
})
复制代码
//创建promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('data')
//reject('error')
}, 1000);
})
//then 方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定
//1.如果回调函数中返回的结果是 非Promise类型的属性(数值、字符串、不返回undefined等),状态为成功,返回值为对象的成功的值
//2.如果返回结果是promise对象,则该该promise对象的状态类型是什么返回的就是什么
//3.若抛出错误,则promise的返回rejected,且其值是抛出的值
const result = p.then(value => {
//1.非promise类型的属性
return 123//执行则其状态为成功其result的成功值为123
//2.是promise对象
return new Promise((resolve,reject)=>{
resolve('OK')
})
//3.抛出错误
throw new Error("出错")
},reason => {
console.warn(reason)
})
//4.链式调用 嵌套异步任务
p.then(value=>{
},reason=>{
}).then(value=>{
},reason=>{
})
console.log(result)
复制代码
Promise实践
//引入fs模块
const { rejects } = require("assert")
const fs = require("fs")
const { resolve } = require("path/win32")
/* fs.readFile('文件.md',(err,data1)=>{
fs.readFile("文件2.md",(err,data2)=>{
fs.readFile("文件3.md",(err,data3)=>{
let result = data1+'\r\n'+data2+'\r\n'+data3
console.log(result)
})
})
}) *///传统方法实现易造成回调地狱
//使用Promise实现
const p = new Promise((resolve,reject)=>{
fs.readFile('文件.md',(err,data)=>{//第一个异步任务
resolve(data)
})
})
p.then(value=>{//value第一个文件内容
//为避免回调地狱,再次搞一个promis对象,将其提出,再次.then
return new Promise((resolve,reject)=>{//第二个异步任务
fs.readFile('文件2.md',(err,data)=>{//data第二个文件内容
resolve([value,data])//成功,返回也是成功
})
})
}).then(value=>{//一个包含文件和文件2内容的数组
return new Promise((resolve,reject)=>{//第三个异步
fs.readFile('文件3.md',(err,data)=>{//data第三个文件内容
value.push(data)//数组压入
resolve(value)//成功 返回也成功
})
})
}).then(value=>{//所有文件的数组
console.log(value.join('\r\n'))
})
复制代码
Pormise对象catch方法
const p = new Promise((value,reject)=>{
setTimeout(() => {
reject("出错!")
}, 1000);
})
/* p.then(value=>{},reason=>{
console.error(reason)
}) */
//then方法不指定第一个参数,即catch
p.catch(reason=>{
console.warn(reason)
})
Set
let s = new Set()//集合 不重复唯一 只有键
//元素个数
console.log(s.size)
//添加新元素
s.add("aaa")
//删除元素
s.delete("aaa")
//检测元素
s.has("aaa")
//清空
s.clear()
//集合有迭代器的接口,所以可以用for...of遍历
for(let i of s){
console.log(i)
}
集合实践
let arr = [1,2,2,3,4,6]
//1.数组去重
//先将其变为 集合 去重
//将 集合 转为 数组
//let s = [...new Set(arr)]
//console.log(s)
//2.交集
let arr2 = [4,5,6,5,6]
/* let result = [...new Set(arr)].filter(items=>{
let s2 = new Set(arr2)//4 5 6 集合
if(s2.has(items)){
return true
}else{
return false
}
}) */
//简化写法
//let result = [...new Set(arr)].filter(items=>new Set(arr2).has(items))
//console.log(result)
//3.并集
//let union = [...new Set([...arr2,...arr])]
//console.log(union)
//4.差集
let diff = [...new Set(arr)].filter(items=>!(new Set(arr2).has(items)))
console.log(diff)
Map
键值对的集合,其“键”不限于字符串,可以是各种类型,Map也实现了iterator接口和扩展运算符,升级版对象,其属性可以是其他类型不只字符串
let m = new Map()
//添加元素
m.set("a",1)
m.set("fn",function(){
console.log("b")
})
let key = {
name:"let"
}
m.set(key,["a","b","c"])
//size获取元素个数
//delete删除元素
//get获取元素
//clear清空
//for...of遍历 [键,值]
Class类
对象的模板,可以看作一个语法糖
//手机
/* function Phone(brand,price){
this.brand = brand
this.price = price
}
//添加方法
Phone.prototype.call = function(){
console.log("打电话")
}
//实例化对象
let xiaomi = new Phone("小米",2000)
xiaomi.call()
console.log(xiaomi) */
//class
class Phone{
//构造函数 名字不能修改
constructor(brand,price){
this.brand = brand
this.price = price
}
//方法必须使用该语法,不能使用ES5的对象完整形式即a:funciton(){}
call(){
console.log("打电话!")
}
}
let oppo = new Phone("a",2000)
console.log(oppo)
复制代码
类的静态成员
class Phone{
//静态属性
static name = '手机'
static change(){
console.log("a")
}
}
let n = new Phone()//实例对象的属性与构造函数的属性并不相同,两个不同对象其在堆内存位置都不同
console.log(n.name)//undefined
console.log(Phone.name)//手机
复制代码
类继承
//ES5
function Phone(brand,price){//父类型
this.brand = brand
this.price = price
}
Phone.prototype.call = function(){
console.log("打电话")
}
//智能手机 子类型
function SmartPhone(brand,price,color,size){
Phone.call(this,brand,price)//改变this指向,指向SmartPhone的new的实例对象
this.color = color//this指向该构造函数new的对象
this.size = size
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone() //为了调用父类方法,但改变了constrcutor指向
//console.log(SmartPhone.prototype.constructor)//指向Phnoe,意思是Phone是其构造函数,很明显该是SmartPhone
SmartPhone.prototype.constructor = SmartPhone
//声明子类的方法
SmartPhone.prototype.phtot = function(){
console.log("拍照")
}
const iPhone = new SmartPhone("a",2500,'b',5)
console.log(iPhone)
//class
//可以明显看出通过class的类继承简洁很多,不需要设置子集构造函数的原型和constructor
class Phone{//构建父类
constructor(brand,price){
this.brand = brand
this.price = price
}
call(){
console.log("打电话")
}
}
//子类
class SmartPhone extends Phone {
constructor(brand,price,size){
super(brand,price)//Phone.call(this,brand,price)
this.size = size
}
photo(){
console.log("拍照")
}
//对父类方法的重写 ,对于调用父类的方法若子类自身含有重名则必定调用自己的而不是父类,super()也不行
call(){
console.log("视频通话")
}
}
const xiaomi = new SmartPhone('小米',"800","大")
console.log(xiaomi)
xiaomi.call()
复制代码
get和set
class Phone {
get price () {//调用属性就执行内部的函数,类似动态监控
console.log("属性被调用")
return "true"
}
set price(newVal){//监控更新数据
console.log("被赋新值")
}
}
const obj = new Phone()
console.log(obj.price)
obj.price = "100"
复制代码
Number方法扩展
//0.Number.EPSILON 是 JS 表示的最小精度 其值接近2.22E-16
console.log(0.1+0.2 === 0.3)//false
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))//true
//1.二进制和八进制
let b = 0b1010//2进制
let o = 0o777//8进制
let d = 100
let x = 0xff//16进制
//2.检测一个数值是否为有限数 Number.isFinite
console.log(Number.isFinite(01))//true
console.log(Number.isFinite(100/0))//false
console.log(Number.isFinite(Infinity))//false
//3.检测一个数值是否为 NaN Number.isNaN
//4.Number.parseInt Number.parseFloat 将字符串转为整数或浮点数(只返回数值部分,过滤字符部分)
console.log(Number.parseInt('11是1啊s'))//11
console.log(Number.parseFloat('5884588啊s'))//5884588
//5.Number.isInteger 判断一个数是否为整数
//6.Math.trunc 抹去小数部分
//7.Math.sign 判断一个数是正数 负数 还是 零
console.log(Math.sign(100))//1
console.log(Math.sign(0))//0
console.log(Math.sign(-5))//-1
复制代码
Object方法扩展
//1.Object.is 判断两个值是否完全相等
console.log(Object.is(120,120))//true
console.log(Object.is(NaN,NaN))//true
console.log(NaN === NaN)//false
//2.Object.assign 对象合并
const p1 = {
a:"1",
b:"2",
c:"3"
}
const p2 = {
a:"A",
b:"B"
}
//p1为基础模板,p2若有其对于属性则覆盖没有则不覆盖
console.log(Object.assign(p1,p2))//{a: 'A', b: 'B', c: '3'}
//还可以用...拓展运算符合并(ES9)
console.log({...p1,...p2})
//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeOf获取原型对象
const s1 = {
name:"a"
}
const s2 = {
city:"b"
}
Object.setPrototypeOf(s1,s2)//对s1对象的原型上设置
console.log(Object.getPrototypeOf(s1))
//ES8
//Object.values Object.entries
//1.Object.values()返回一个给定对象的 所有 可枚举属性的 数组
//2.Object.entries()返回一个给定对象 自身 可遍历属性[key,value]的 数组 可以创建Map
const m = new Map(Object.entries(s))
//对象属性的描述对象
Object.getOwnPropertyDescriptors()
复制代码
模块化
将一个大的程序文件**,拆分**成许多小的文件,然后将小文件组合起来
好处:
- 防止命名冲突
- 代码复用(各部分独立互不干预)
- 高维护性
语法
模块化功能主要由两个命令构成:export和import
- export命令用于规定模块的对外接口(这样就不需要导入整个文件而是其中一些数据比如一个最终结果)
- import命令用于输入其他模块提供的功能
//分别暴露
export let s = "a"
export function fn(){
console.log("bbbbb")
}
//统一暴露
let s = "a"
function fn(){
console.log("bbbbb")
}
export {s,fn}
import * as module from "./module.js"
console.log(module)//Symbol
//默认暴露
export default{
a:"1",
fn:function(){
console.log("ssss")
}
}
//调用
import * as module from "./module.js"
module.default.fn()
复制代码
模块引入方式
//1.通用导入方式
//引入 module.js
import * as module from "./module3.js"
console.log(module.default.a)
//2.结构赋值形式
import {s,fn} from "./module1.js"//分别暴露
import {s as s1,fn as fn1} from "./module2.js"//统一暴露
import {defualt as m3} from "./module3.js"//默认暴露 default要有别名
//3.简便形式 针对默认暴露
import m3 from"./module3.js"
ES7
-
Array.prototype.includes
检测数组中是否包含某个元素,返回布尔类型值
-
指数操作符
**,用来实现幂运算,功能与Math.pow结果相同
ES8
async和await两种语法可以让异步代码像同步代码一样
async
-
async函数的返回值为promise对象
-
promise对象的结果由async函数执行的返回值决定
//async函数 async function fn(){ return "aaaa" } console.log(fn())//promise对象 成功 复制代码
【注】返回的不是promise类型的对象都是成功的promise,但若抛出错误则返回失败的promise对象,返回的是一个promise对象,根据该promise成功与否决定返回的promise对象的值,即一一对应
await
- 必须写在async函数内
- await右侧的表达式一般为promise对象
- await返回的是promise成功的值
- await的promise失败,则会抛出异常,需要通过try…catch捕获处理
//await 要处于 async中,单向依赖
const p = new Promise((resolve,reject)=>{
//resolve("a")
reject("warn")
})
async function fn(){
try{//resolve
let result = await p
console.log(result)
}catch(e){//reject
console.log(e)
}
}
fn()
//1.引入fs模块
const { rejects } = require("assert")
const fs = require("fs")
const { resolve } = require("path/posix")
//读取文件
function read1(){
return new Promise((resolve,reject)=>{
fs.readFile("文件.md",(err,data)=>{
if(err) reject(err)
resolve(data)
})
})
}
function read2(){
return new Promise((resolve,reject)=>{
fs.readFile("文件2.md",(err,data)=>{
if(err) reject(err)
resolve(data)
})
})
}
function read3(){
return new Promise((resolve,reject)=>{
fs.readFile("文件3.md",(err,data)=>{
if(err) reject(err)
resolve(data)
})
})
}
//声明async函数
async function main(){
//获取文件内容
let a1 = await read1()
let a2 = await read2()
let a3 = await read3()
console.log(a1.toString())
console.log(a2.toString())
console.log(a3.toString())
}
main()
async和await封装ajax请求
function sendAJAX(url) {
return new Promise((resolve,reject)=>{
//1.创建对象
const x = new XMLHttpRequest()
//2.初始化
x.open('GET',url)
//3.发送
x.send()
//4.事件绑定
x.onreadystatechange = function () {
if(x.readyState === 4){
if(x.status>=200&&x.status<300){
resolve(x.response)//返回给promise对象
}else{
reject(x.response)
}
}
}
})
}
//promise then 测试
/* const a = sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
console.log(value)
},reason=>{})
console.log(a) */
//async await 测试 axios
async function fn(url) {
const b = await sendAJAX(url)//返回一个成功的promise对象且其值为成功值
console.log(b)
}
let url = "https://api.apiopen.top/getJoke"
fn(url)
ES9
对象展开
//在ES6中的rest参数只针对数组
//ES9中为 对象 提供了像数组一样的rest 参数和扩展运算符
function connect({host,port,...a}) {//...a 对象{user:'b',pass:22222}
console.log(host)
console.log(port)
console.log(a)
}
connect({
host:'a',
port:1020,
user:'b',
pass:22222
}).
正则命名扩展
//一般捕获
let str = "<a href='aaaaaaaaaaa'>bbbb</a>"
const reg = /<a href='(.*)'>(.*)<\/a>/
const result = reg.exec(str)
console.log(result[1])
console.log(result[2])
//捕获分组(对象)
let str = "<a href='aaaaaaaaaaa'>bbbb</a>"
const reg = /<a href='(?<url>.*)'>(?<text>.*)<\/a>/ //url和text是分组属性名
const result = reg.exec(str)
console.log(result.groups.url)
反向断言
//正向断言
let str = 'asdasdasda你你你77零零零零'
const reg = /\d+(?=零)/
const result = reg.exec(str)//77
//反向断言
let str = 'asdasdasda你你你77零零零零'
const reg = /(?<=你)\d+/
const result = reg.exec(str)//77
dotAll模式
一般针对HTML结构的换行处理/.*?/s
ES10
Object.fromEntries
//二维数组或者Map
//转为对象
复制代码
Object.entries
//将对象转为数组,且为[key,value]形式
复制代码
trimStart&trimEnd
//str.trimStart() 左边空白
//str.trimEnd() 右边空白
复制代码
Array.prototype.flat&Array.prototype.flatMap
//flat 平
//多维转低维
arr.flat(n)//n是深度
//flatMap
//map返回结果若是多维数组再经过flat降维
arr.flatMap
复制代码
ES11
私有属性
class Person{//私有属性除非自身输出,不然外部是调用不了的
//共有属性
name
//私有属性
#age
constructor(name,age){
this.name = name
this.#age = age
}
infor(){
console.log(this.name)
console.log(this.#age)
}
}
const p = new Person('aa',21)
p.infor()
promise.allSettled
const p1 = new Promise((resolve,reject)=>{
setTimeout(() => {
resolve("1111")
}, 1000);
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(() => {
reject("2222")
}, 1000);
})
//调用allSettled方法
//const result = Promise.allSettled([p1,p2])//返回一个promise对象,且都是成功状态,其结果值是一个数组,数组内是对象,对象中为返回结果状态信息和具体值
const res = Promise.all([p1,p2])//所有promise对象有一个失败就是失败得到失败的值,只有全部成功才返回所有成功的promise值
console.log(res)
Srting.prototype.matchAll
//正则批量匹配
let str = `<ul>
<li>
<a>啊</a>
<p>对对对</p>
</li>
<li>
<a>哇</a>
<p>水水水</p>
</li>
</ul>`
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<P>(.*?)<\/p>/sg
//调用方法
const result = str.matchAll(reg)//返回 可迭代对象 for...of
const arr = [...result]
console.log(arr)
可选链操作符
function main(config) {
//const dbHost = config && config.db &&config.db.host
const dbHost = config?.db?.host
console.log(dbHost)
}
main({//没有也不报错,返undefined
db:{
host:'aaa'
}
})
复制代码
动态import加载
const btn =document.getElementById('btn')
btn.onclick = function () {//动态导入的模块为promise对象,其.then的返回值为js文件中export的代码
import('./module.js').then(module=>{
module.fn()
})
}
Bigint
//大整形
let n = 520n
//函数
console.log(Bigint(123))//123n 浮点型不行
//大数值运算 Bigint不能直接与一般数值进行运算,需要对一般数值进行Bigint转换
复制代码