#### 五.ES10新特性
##### 1. Object.fromEntries
> Object.fromEntries()方法允许你轻松地将键值对列表转换为对象
```js
const arr = [["name", "kerwin"], ["age", 100]];
console.log(Object.fromEntries(arr))//{name: 'kerwin', age: 100}
const m = new Map()
m.set("name","tiechui")
m.set("age",18)
console.log(Object.fromEntries(m))
```
**用处**
```js
let str ="name=kerwin&age=100"
let searchParams = new URLSearchParams(str)
console.log(Object.fromEntries(searchParams))//{name: 'kerwin', age: '100'}
```
##### 2. trimStart() and trimEnd()
> trimStart()和trimEnd()方法在实现与trimLeft()和trimRight()相同。
```js
let str = " kerwin "
console.log("|"+str.trimStart(str)+"|")
console.log("|"+str.trimEnd(str)+"|")
console.log("|"+str.trimLeft(str)+"|")
console.log("|"+str.trimRight(str)+"|")
```
##### 3. Symbol 对象的 description 属性
> 为Symbol对象添加了只读属性 description ,该对象返回包含Symbol描述的字符串。
```js
let s = Symbol("kerwin")
console.log(s.description) //kerwin
```
##### 4. 可选的 catch
```js
let pro1 = new Promise(function (resolve, reject) {
//执行器函数
setTimeout(() => {
resolve("成功的结果")
}, 30000)
})
let pro2 = new Promise(function (resolve, reject) {
//执行器函数
setTimeout(() => {
reject()
}, 2000)
})
async function test() {
try {
await Promise.race([pro1, pro2])
} catch {
console.log("不关心错误结果,网络超时")
}
}
test()
```
#### 六. ES11新特性
##### 1. Promise.allSettled
> Promise.allSettled() 方法返回一个在所有给定的 promise 都已经 fulfilled 或 rejected 后的 promise ,并带有一个对象数组,每个对象表示对应的 promise 结果。
```js
const promises = [ ajax('/200接口'), ajax('/401接口') ];
Promise.allSettled(promises).then(results=>{
// 过滤出成功的请求
results.filter(item =>item.status === 'fulfilled');
过滤出失败的请求
results.filter(item=> item.status === 'rejected');
})
```
##### 2.module新增
###### 2-1 动态导入 import()
> 标准用法的 import 导入的模块是静态的,会使所有被导入的模块,在加载时就被编译(无法做到按需编译,降低首页加载速度)。有些场景中,你可能希望根据条件导入模块或者按需导入模块,这时你可以使用动态导入代替静态导入。
```js
<body>
<button>login</button>
<script type="module">
let role1 = "管理员"
let role2 = "普通用户"
function login(){
return "普通用户"
}
async function render(role){
if(role===role1){
let res1 = await import("./1.js")
console.log(res1.default)
}else{
let res2 = await import("./2.js")
console.log(res2.default)
}
}
let obtn = document.querySelector("button")
obtn.onclick = function(){
let role = login()
render(role)
}
</script>
</body>
```
###### 2-2 import.meta
import.meta 会返回一个对象,有一个 url 属性,返回当前模块的url路径,只能在模块内部使用。
```js
<script type="module">
import obj from './1.js'
</script>
//1.js
console.log(import.meta)
export default {
}
```
###### 2-3 export * as obj from 'module'
```js
//1.js
export default {
name:'111111'
}
export function test1(){
}
//2.js
export default {
name:"22222"
}
export function test2(){
}
export * as obj1 from './1.js'
//html
<script type="module">
import * as obj from './2.js'
console.log(obj)
</script>
```
<img src="%E7%AC%94%E8%AE%B0.assets/image-20220922111416681.png" alt="image-20220922111416681" style="zoom:67%;float:left;" />
##### 3.字符串的matchAll方法
> matchAll() 方法返回一个包含所有匹配正则表达式的结果的迭代器。可以使用 for...of 遍历,或者使用 展开运算符(...) 或者 Array.from 转换为数组.
```js
let str = `
<ul>
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
</ul>
`
let reg = /<li>(.*)<\/li>/g
console.log(str.match(reg))
//'<li>1111</li>', '<li>2222</li>', '<li>3333</li>', '<li>4444</li>'
```
```js
let str = `
<ul>
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
</ul>
`
let reg = /<li>(.*)<\/li>/g
let match = null;
while(match = reg.exec(str)){
console.log(match[0])
console.log(match[1])
}
```
```js
let str = `
<ul>
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
</ul>
`
let reg = /<li>(.*)<\/li>/g
for(let i of str.matchAll(reg)){
console.log(i)
}
```
##### 4. BigInt
> JavaScript 能够准确表示的整数范围在-2^53到2^53之间(不含两个端点),超过这个范围,无法精确表示这个值,这使得 JavaScript 不适合进行科学和金融方面的精确计算。
```js
9007199254740992 //9007199254740992
9007199254740993 //9007199254740992
Math.pow(2,53) === Math.pow(2,53)+1
```
为了与 Number 类型区别,BigInt 类型的数据必须添加后缀`n`。
```js
1234 // 普通整数
1234n // BigInt
// BigInt 的运算
1n + 2n // 3n
```
##### 5. globalThis
> globalThis 提供了一个标准的方式来获取不同环境下的全局 this 对象(也就是全局对象自身)。不像 window 或者 self这些属性,它确保可以在有无窗口的各种环境下正常工作。所以,你可以安心的使用 globalThis,不必担心它的运行环境。为便于记忆,你只需要记住,全局作用域中的 this 就是 globalThis。
>
```js
//es6-shim
var getGlobal = function () {
// the only reliable means to get the global object is
// Function('return this')()
// However, this causes CSP violations in Chrome apps.
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
var globals = getGlobal();
if (!globals.Reflect) {
defineProperty(globals, ‘Reflect’, {}, true);
}
```
```js
//以前
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
let globals = getGlobal()
if (globals.document) {
console.log("进行dom操作相关")
} else {
console.log("不能进行dom操作")
}
//现在
if (globalThis.document) {
console.log("进行dom操作相关")
} else {
console.log("不能进行dom操作")
}
```
##### 6.空值合并运算符
> **空值合并运算符(*??*)**是一个逻辑运算符。当左侧操作数为 null 或 undefined 时,其返回右侧的操作数。否则返回左侧的操作数。
```js
let obj = {
name:"kerwin",
introduction:0
}
console.log(obj.introduction || "这个人很懒")
console.log(obj.introduction ?? "这个人很懒")
```
**??和 || 的区别是什么呢?**
他们两个最大的区别就是 ’ '和 0,??的左侧 为 ’ '或者为 0 的时候,依然会返回左侧的值;
|| 会对左侧的数据进行boolean类型转换,所以’ '和 0 会被转换成false,返回右侧的值
##### 7.可选链操作符
> 可选链前面的值如果是null或undefined,则不再执行后面的,之前返回可选链前面的值
```js
let obj = {
name:"kerwin",
introduction:0,
// location:{
// city:"dalian"
// }
}
console.log(obj && obj.location && obj.location.city)
console.log(obj?.location?.city)
```
#### 七. ES12新特性
##### 1. 逻辑赋值操作符
逻辑赋值操作符 ??=、&&=、 ||=
```js
let a = true
let b = false
//a &&= b //false
a ||= b ; //true
console.log(a)
let obj = {
name:"kerwin",
}
obj.introduction = obj.introduction??"很懒"
obj.introduction??="很懒"
```
##### 2.数字分隔符
这个新特性是为了方便程序员看代码而出现的,如果数字比较大,那么看起来就不是那么一目了然
```js
const num= 123456789;
```
分隔符不仅可以分割十进制,也可以分割二净值或者十六净值的数据,非常好用。
```javascript
const number = 1_000_000_000_000;
const binary = 0b1010_0101_1111_1101;
const hex = 0xA1_B2_C3;
```
##### 3. replaceAll
> 所有匹配都会被替代项替换。模式可以是字符串或正则表达式,而替换项可以是字符串或针对每次匹配执行的函数。并返回一个全新的字符串
```js
const str =
"I wish to wish the wish you wish to wish, but if you wish the wish the witch wishes, I won't wish the wish you wish to wish. ";
const newStr = str.replaceAll("wish", "kerwin");
console.log(newStr);
```
##### 4.Promise.any
只要参数实例有一个变成`fulfilled`状态,包装实例就会变成`fulfilled`状态;如果所有参数实例都变成`rejected`状态,包装实例就会变成`rejected`状态。
> `Promise.any()`跟`Promise.race()`方法很像,只有一点不同,就是`Promise.any()`不会因为某个 Promise 变成`rejected`状态而结束,必须等到所有参数 Promise 变成`rejected`状态才会结束。
##### 5. WeakRef
> 在一般情况下,对象的引用是强引用的,这意味着只要持有对象的引用,它就不会被垃圾回收。只有当该对象没有任何的强引用时,垃圾回收才会销毁该对象并且回收该对象所占的内存空间。
>
> 而 `WeakRef` 允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被垃圾回收。
```js
let target = {};
let wr = new WeakRef(target);
```
WeakRef 实例对象有一个`deref()`方法,如果原始对象存在,该方法返回原始对象;如果原始对象已经被垃圾回收机制清除,该方法返回`undefined`。
```js
let target = {};
let wr = new WeakRef(target);
let obj = wr.deref();
if (obj) { // target 未被垃圾回收机制清除
// ...
}
```
```js
let like = new WeakRef(document.getElementById("like"))
let mymap = new WeakMap()
mymap.set(like.deref(), {
click: 0
})
like.deref().onclick = function () {
let times = mymap.get(like.deref())
times.click++
}
setTimeout(() => {
document.body.removeChild(like.deref())
}, 2000)
```
##### 6. FinalizationRegistry
> 清理器注册表功能 FinalizationRegistry,用来指定目标对象被垃圾回收机制清除以后,所要执行的回调函数。
首先,新建一个注册表实例。
```javascript
const registry = new FinalizationRegistry(data => {
// ....
});
```
```javascript
registry.register(obj, "some value");
registry.unregister(obj);
```
```js
let like = new WeakRef(document.getElementById("like"))
let mymap = new WeakMap()
mymap.set(like.deref(), {
click: 0
})
like.deref().onclick = function () {
let times = mymap.get(like.deref())
times.click++
}
setTimeout(() => {
// registry.register(document.getElementById("like"), mymap.get(like.deref()));
registry.register(like.deref(), mymap.get(like.deref()));
document.body.removeChild(like.deref())
}, 2000)
const registry = new FinalizationRegistry(data => {
// ....
console.log("被销毁了", data)
});
```
#### 八.ES13新特性
##### 1. 私有属性和方法
```js
class Cache{
#obj ={}
get(key){
return this.#obj[key]
}
set(key,value){
this.#obj[key] =value
}
}
let cache = new Cache()
cache.set("name","kerwin")
```
##### 2.静态成员的私有属性和方法
> 我们还可以给类定义静态成员和静态私有函数。类的静态方法可以使用`this`关键字访问其他的私有或者公有静态成员,
```js
class Cache{
static #count = 0;
static getCount(){
return this.#count
}
#obj ={}
get(key){
return this.#obj[key]
}
set(key,value){
this.#obj[key] =value
}
}
let cache = new Cache()
cache.set("name","kerwin")
console.log(Cache.getCount())
```
##### 3.静态代码块
> ES13允许在类中通过`static`关键字定义一系列静态代码块,这些代码块只会在类被创造的时候**执行一次**。这其实有点像一些其他的如C#和Java等面向对象的编程语言的静态构造函数的用法。
一个类可以定义任意多的静态代码块,这些代码块会和穿插在它们之间的静态成员变量一起按照定义的顺序在类初始化的时候执行一次。我们还可以使用`super`关键字来访问父类的属性。
```js
class Cache{
static obj = new Map()
static {
this.obj.set("name","kerwin")
this.obj.set("age",100)
}
static{
console.log(this.obj)
}
}
console.log(Cache.obj)
```
##### 4. 使用in来判断某个对象是否拥有某个私有属性
```js
class Cache {
#obj = {}
get(key) {
return this.#obj[key]
}
set(key, value) {
this.#obj[key] = value
}
hasObj(){
return #obj in this
}
}
let cache = new Cache()
console.log(cache.hasObj())
```
##### 5.支持在最外层写await
> 顶层`await`只能用在 ES6 模块,不能用在 CommonJS 模块。这是因为 CommonJS 模块的`require()`是同步加载,如果有顶层`await`,就没法处理加载了。
```js
<script type="module">
function ajax() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("data-1111");
}, 1000);
})
}
let res = await ajax();
console.log(res)
</script>
```
##### 6. at函数来索引元素
```js
let arr = ["kerwin","tiechui","gangdan","xiaoming"]
console.log(arr[1])
console.log(arr[arr.length-1]) //变丑了
console.log(arr[arr.length-2]) //变丑了
console.log(arr.at(1))
console.log(arr.at(-1))
console.log(arr.at(-2))
```
##### 7. 正则匹配的开始和结束索引
```js
let str = "今天是2022-11-10"
let reg = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/d
//exec
let res = reg.exec(str)
console.log(res)
```
![image-20220927105243515](%E7%AC%94%E8%AE%B0.assets/image-20220927105243515.png)
##### 8.findLast()和findLastIndex()函数
```js
let arr = [11,12,13,14,15]
// let res = arr.find(function(value){
// return value % 2 === 0
// })
// let res = arr.findIndex(function(value){
// return value % 2 === 0
// })
// let res = arr.findLast(function(value){
// return value % 2 === 0
// })
let res = arr.findLastIndex(function(value){
return value % 2 === 0
})
console.log(res)
```
##### 9.Error对象的Cause属性
> Error对象多了一个`cause`属性来指明错误出现的原因。这个属性可以帮助我们为错误添加更多的上下文信息,从而帮助使用者们更好地定位错误。
```js
function getData(){
try{
console.log(kerwin)
}
catch(e){
throw new Error('New error 1111111',{cause:"这是因为,,,,,,,,,"});
}
}
try{
getData()
}catch(e){
console.log(e.cause)
}
```