es6(2016)
模块化
模块化就是将一些具有相同功能的代码提出出来写在一个js文件中,其的数据和实现功能是私有的,只向外提供一个公共的访问接口(变量/函数等)
模块化的进程
将功能封装成一个个方法(容易造成变量命名污染)>>将功能写成一个个对象(对象不安全,会被随意调用功能)>>匿名闭包,通过window向外暴露功能(请求多,依赖多,维护起来麻烦)>>es6模块化(解决命名冲突,对外导出变量和对象,便于维护)
es模块化
export关键词:表示向外暴露的接口(变量/函数/对象)。默认暴露 export default
const num = 12
const fun = function () { console.log("模块化导出");}
const obj = {name:"xiaozhi"}
export {num,fun,obj}
export default function () {
console.log("默认暴露模块化");
}
import 关键词:用于引入导出的模块
import moduleName from 'module'
import modelD from './model/model'
import { num, fun, obj } from './model/model2'
modelD()
console.log(num, obj);
fun()
由于使用模块化需要使用label便于成es6,所以在浏览器中是无法验证的。
namespce
模块命名空间,通过对象调用功能,一般挂载到window或者使用es6模块化导出
var NameSpace = window.NameSpace || {};
NameSpace.Hello = new function() {
var self = this;
var name = 'world';
self.sayHello = function(_name) {
return 'Hello ' + (_name || name);
};
};
NameSpace.Hello.sayHello();
let和const
let和const都是用于声明变量的关键词
let
特点:可以不赋值(underfined),不能重复声明,块级作用域生效,不能变量提升,不影响作用域。
const
特点:一定要赋值;为常量,不可重复赋值;块级作用域生效;不能变量提升;不影响作用域。
const一般用来定义常量
变量结构赋值
结构赋值是,定义变量的时候,可以将对象内的同名变量赋值给该同名变量,该同名变量需要使用“{}”包起来
let obj ={
name:"xiaozhi",
age:18
}
let {name,age}=obj
模板字符串
模板字符串多用在字符串拼接的时候获取变量。
模板格式:
`..${变量}..` 反单引号
let a="12"
let str=`今天小米${a}岁了 `
console.log(str);
对象简写
es6运行对象直接写变量
let name='小米'
let fn=function(){
console.log("你好");
}
const obj={
name,
fn
}
obj.fn()
console.log(obj.name,);
对象内部定义方法不需要function关键词
const obj={ show(){console.log("showshouw",this.name);} } obj.show()
箭头函数
语法:
([params])=>{....}
箭头函数的this
箭头函数本身没有this,它的this指向其作用域的this,如果其所在作用域没有this,将会向上查找,最终知道window。
let fn=() => onsole.log(this);}
let obj={fn}
obj.fn()//this指向window
function Person(){
name:12,
(()=>{
console.log(this);//this直线Person
})()
let p=new Person()
箭头函数不能作为构造函数进行实例化
let Person=()=>{}
let p =new Person()
箭头函数没有arguments
形参默认值
es6可以指定形参的默认值,如果不入参,则该参数的值为设置的默认值
function fn(a=100,b=12){
console.log(a,b);
}
fn()
可以通过对象结构实现传参
function func({a=23,b=23}){
console.log(a,b);
}
let obj={
a:12,
b:13,
c:14
}
func(obj)
reset参数
reast参数用来代替arguments,主要是因为arguments是一个类数组,而reast参数是一个数组
<script>
function fn(...args){
console.log(args);
}
fn('q','w','e')
</script>
reast参数不是唯一的,但必须放在最后面,用于接收剩余的参数
<script>
function fn(a,b,...args){
console.log(args);
console.log(a,b);
}
fn('q','w','e',1,2)
</script>
注意:args是自定义的
扩展运算符
扩展运算符用于对有序对象展开
格式:
... 就是三个点
let arr=[12,23,34]
console.log(...arr);
必须有序,例如普通对象是无法使用的。
Symbol
Symbol是es6引入的一个新的基本数据类型,表示的是独一无二的变量
创建Symbol
方式一:创建独一无二的Symbol变量
let a =Symbol([args])
传入参数打印结构为其本身,表示的是这个Symbol变量的标志,该标志相同的时候,Symbol变量也是不同的变量。
<script>
let a=Symbol("12")
let b = Symbol("12")
a='13'
console.log(a===b);//false
</script>
方式二:创建标志相同且为相同的Symbol变量
let a =Symbol.for([args])
<script>
let c =Symbol.for("13")
let d= Symbol.for("13")
console.log(c===d);//true
</script>
Symbol的特点:值是唯一的;值不能参加运算;使用Symbol变量的对象不能进行for...in循环,但是可以使用Reflect.ownKeys()来获取对象所有的键名。
实例:向对象添加同名方法
let obj={
name:"xiaozhi",
up(){
console.log("你好,不是symbol");
}
}
let methods={
up:Symbol()
}
obj[methods.up]=function(){
console.log("你好,我是symbol");
}
onsole.log(obj);
symbole的内置属性
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol
迭代器
迭代器是JavaScript为不同数据类型提供统一的访问机制。任何数据类型只要实现了iterator接口,就可以实现遍历操作。
es6提供了新的变量方式for...of用于遍历对象的值,而iterator就是为了提供for...of消费
工作原理
首先会创建一个指针对象指向当前数据结构的起始位置。
调用next方法,指针指向数据结构的第一个成员。
再次调用next方法,指针自动指向下一个成员,直到直线最后一个成员
每次调用next方法会返回一个对象{value,done},done为true表示没有成员。
自定义迭代器
和工作原理一样:
首先添加一个迭代器,每次调用都会返回一个next方法。
<script>
let obj ={
name:'hh',
age:12
}
obj[Symbol.iterator]=function(){
let _this=this
let index=0
let objKeys=Object.keys(this)
return {
next:function(){
if(index<objKeys.length){
let res={
value: _this[objKeys[index]],
done:false
}
index++
return res
}else{
return{
value:undefined,
done:true
}
}
}
}
}
for(let a of obj){
console.log(a);
}
</script>
生成器
原理
生成器是es6提供的一种新的解决异步调用的思路,生成器本身是一个函数,定义的时候在函数名之前有一个星号,函数内部使用yield用于将函数内部代码分割成一个个成员,yield的值作为next方法返回值对象value的值。生成器的返回值是一个具有iterator迭代器的对象。
<script>
//定义生成器
function * gone(){
console.log("成员一业务代码");
yield "成员一";
console.log("成员二业务代码");
yield "成员二";
console.log("成员三业务代码");
yield "成员三";
}
let itera=gone()
//itera.next()
for(let v of itera){
//console.log(v);
itera.next()
}
</script>
生成器next方法的参数
生成器的next()方法传入的参数会作为上一个yield的返回值
<script>
//定义生成器
function * gone(aa){
console.log(aa);
let a=yield "成员一";
console.log(a);
let b=yield "成员二";
console.log(b);
let c=yield "成员三";
console.log(c);
}
let itera=gone("aabbcc")
itera.next("1")//没有上一个,不打印
itera.next("2")
itera.next("3")
itera.next("4")
</script>
es6新增集合
set
set集合是用于存贮不可重复的值得集合
四个方法:size,add,delete,has。
map
五个方法:size,set,get,has,clear。
类
具体可看typescript中,对类的讲解
https://www.cnblogs.com/waywordcode/p/15476502.html
es7(2017)
es7主要新增两个功能
Array.prototype.includes:检查数组是否含有有个元素
**:幂运算符,效果和Math.pow一样
本来还有一个,用来回调promise的,es8增强了,es7没必要看了。
es8(2018)
async&await
异步代码同步化,可以让同步代码执行起来如同异步代码一样
缺点:如果请求过多,容易阻塞,导致加载时间过长
async函数
如果返回的不是一个promise对象,则返回结果是一个状态为已完成的promise对象,其值为promise的value
如果返回值是一个promise对象,返回结果是一个状态和返回的promise对象状态一样的一个promise对象。
<script>
async function fn(){
return "你好"
}
async function func() {
return new Promise((res,rej)=>{
res('OK')
})
}
let b=fn()
let c=func()
console.log(b);
console.log(c);
</script>
<script>
let p = new Promise((res, rej) => {
let ok = "ok"
res(ok)
}).then(res => {
console.log(res);
})
</script>
await:将异步代码同步会,当代码执行到await处,会等待异步代码执行完成后才能执行下面的代码。
使用await修饰的异步代码的返回值,是promise的成功的result值。如果是失败的状态使用try...catch进行捕捉。
<script>
async function fun(){
try {
let d=await new Promise((res, rej) => {
let ok = "no"
rej(ok)
})
} catch (e) {
console.log(e);
}
}
fun()
</script>
对象扩展
getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor(obj, prop)
方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
Object.valus && Object.entries()
es9(2018)
reast参数和扩展运算符增强
es6只是针对数组,到se9之后增加到对对象的使用
正则
正则命名分组
格式:?<ItemName>
<script>
let str='<a href="www.baidu.com">你好</a>'
let p=/<a href="(.*)">(.*)<\/a>/
let a=p.exec(str)
console.log(a);
//分组
let c = /<a href="(?<url>.*)">(?<name>.*)<\/a>/
let s = c.exec(str)
console.log(s);
</script>
正则反向断言
通过需要匹配的字符串的前面的字符进行判断
<script>
let str ='js1232hh哈哈555妮妮'
//通过哈子来判断需要截取的部分
let ep=/(?<=哈)\d+/
//表示之前必须要有‘哈’
let a=ep.exec(str)
console.log(a);
</script>
es10(2019)
Object.fromEntries()
将二维数组转对象
String.trimStart()&&String.trimEnd()
清除前面/后面的空字符
Array.flat()和Array.flatMap()
Array.flat():数组偏平化,参数为一个整数,表示的是偏平化到第几层,为Infinity表示无论多少层,都偏平化数组。
Array.flatMap():将map()方法的返回值为一个数组,返回值应该是一个二维数组,flatMap循环遍历会使其变成一维数组
Symbol.prototype.description
description是一个只读属性,它会返回 Symbol对象的可选描述的字符串。
es11 (2020)
私有属性
修饰符:# 和private类似
class Person{
name='12'
#name="123"
}
let p=new Person()
console.log(p.name);
console.log(p.#name);
Promise.allSettled
Promise.allSettled([p1,p2,....]):获取全部promise系列的结果
Promise.all([p1,p2,....]):表示全部promise系列状态都为已完成的结果
可选链操作符
修饰符:?.
和&&符号有点类似,表示签名的字符有了才会读取后面的字符
<script>
function fn(conf){
//表示先判断conf是否存在,存在,在执行conf.con,再次判断conf.con是否存在,存在获取,不存在为undefined,下面再次判断
let b= conf?.con?.a
console.log(b);
}
fn({
con:{
a:100
}
})
</script>
动态import
格式:import (url).then(model=>{....})
model:含有暴露出来的接口,直接通过model调用
BigInt:大数值
let i=BigInt(num)
全局this
globalThis
es12(2021)
replaceAll
字符串全部替换
let targetString = "123wer" let newString= targetString.replaceAll("1","qqqq") console.log("newString", newString);
Promise.any
参数为数组,数组元素为promise,其中数组元素的promise任何一个promise为resolve时,都会触发Promise.any的resolve,否则触发reject而且抛出一个AggregateError错误。
//任意为resolve
let promiseA=new Promise((resolve, reject) => {
resolve("ok")
})
let promiseB = new Promise((resolve, reject) => {
reject("NO")
})
Promise.any([promiseA, promiseB]).then(res=>{
console.log(res);
}).catch(e=>{
console.log(e);
})//打印 ok
//全部为reject
let promiseA=new Promise((resolve, reject) => {
reject("ok")
})
let promiseB = new Promise((resolve, reject) => {
reject("NO")
})
Promise.any([promiseA, promiseB]).then(res=>{
console.log(res);
}).catch(e=>{
console.log(e);
})
//打印 AggregateError: All promises were rejected
WeakRefs
保护对象不被垃圾回收器自动回收,使用deref()取出对象,改方法返回的对象的强引用
function Foo() {} const x = new Foo(); const xWeak = new WeakRef(x); const xFromWeak = xWeak.deref();
&&=
前面的为true,将后面的值赋值给前面的值
x &&= y 等效于:x && (x = y)
||=
x ||= y; 等效于:x || (x = y)
??=
x ??= y;等效于:x ?? (x = y);
Numeric Separators
有助于提高代码的可读性。目前,当在 var/let/const 变量中存储长数时,它可能不可读。
正常情况
const oneMillion = 1000000;
使用新的 ES12 语法,可以使用 _ 字符在数字之间创建分隔
const oneMillion = 1_000_000;
其效果是等效的
//打印 ok
let a=100000000
let b= 100_000_000
console.log(a===b);
//打印true
let c = 100000000
let d = 1_0000_0000
console.log(c === d);
//打印true
es13(2022)
顶层 await
以前async需要和await连用,es13则不需要了
//以前
const request = async () => {
await axios.get('');
};
// 现在使用,可以直接在顶层使用
const fun = (timeout) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
};
await fun(3000);
at
获取数组或者字符串索引处的元素或者字符
let arrA=[1,2,3,4]
let str='1234'
console.log(arrA.at(1),str.at(1));
//打印:2 '2'
Object.hasOwn
用来代替替代 Object.prototype.hasOwnProperty 的方案
es14(2023)
新的数组方法
reverse,splice、sort会修改原数组,es14提供一下方法用来获取到对应的新的数组,而不改变原数组
toReversed() toSpliced() toSorted()
数组新增查找最后一个数组元素的方法,和find和findIndex相反
findLast:查找最后一个元素 findLastIndex:查找最后一个的索引
with:运行修改数组某个下标的值并生成新的数组
const arr4 = ["I", "am", "the", "Walrus"];
// 用 "Ape Man" 替换字符串 "Walrus"。
const newArr4 = arr4.with(3, "Ape Man");
console.log(newArr4);
Hashbang语法
ES14 使 JS 引擎能够处理脚本文件开头的 hashbang 注释 (#!)。以前,操作系统在将脚本传递给 JS 引擎之前会剥离这些注释。通过此更新,JS 引擎将直接处理这些注释。
#!/usr/bin/env node
console.log("123");
//打印 123
管道运算符:|>
它允许我们以更易读的方式将多个函数链接在一起。管道运算符没有被所有浏览器支持,但预计在不久的将来会得到广泛支持。例如一个数组处理,首先过滤数字数组以仅包含偶数。然后,将每个数字映射到它的双精度数。最后,将数组减少到其总和。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers
|> filter(number => number % 2 === 0)
|> map(number => number * 2)
|> reduce((accumulator, number) => accumulator + number, 0);
console.log(sum);
//打印12