Приближается ES11, почему бы вам не зайти и не посмотреть?

JavaScript

предисловие

ES2020 (ES11) — это версия ECMAScript 2020 года. В этом выпуске не так много новых функций, как в ES6 (ES2015). Но также добавлено много интересных и полезных функций. В этой статье представлены новые функции ES2020 с простыми примерами кода. Таким образом, вы можете быстро понять эти новые функции без необходимости сложных объяснений, ну и без лишних слов, давайте перейдем к основному тексту 🔛

частная переменная

Одна из основных ролей классов — содержать наш код в повторно используемых модулях. Следовательно, один и тот же класс будет использоваться во многих разных местах, но некоторые атрибуты в другом классе, для безопасности или других целей, не хотят, чтобы другие классы обращались к нему, модифицировали его, только он может использовать его сам, для некоторых Для учащихся кто изучал c#, java и другие языки, понять проще, т.е.PrivateМодификатор доступа, так что же нам делать в нашем js,

Не волнуйтесь, у них есть и наши js, а в ES11 они также предоставляют намчастная переменная, добавив перед переменной или функцией символ решетки#, вы можете сделать их частными свойствами, доступными только внутри класса.

Это наш обычный класс

class Money{
  constructor(money){
    this.money=money;
  }
}
let RMB=new Money(999);
RMB.money=999999;//这还了得,怎么可以随便改钱的金额呢
console.log(RMB.money);//可以通过对象的形式去访问

Из-за безопасности мы не можем позволить другим классам изменять значение свойств в нашем классе, мы можем использоватьчастная собственность, доступен только внутри класса

class Money{
      #money=0;//声明这个属性是私有属性
      constructor(money){
        this.#money=money;
      }
    }
    let RMB=new Money(999);
    //RMB.#money=999999;//Uncaught SyntaxError: Private field '#money' must be declared in an enclosing class,
    console.log(RMB.#money);//Uncaught SyntaxError: Private field '#money' must be declared in an enclosing class

Приведенный выше код сообщает об ошибке, плачетimg, я не могу получить стоимость частной собственности, что мне делать? ?

Мне нужно использовать деньги в моем классе, как мне их получитьimg

Мы можем написать два метода в классе, взять данные, записать данные и изменить их, но вы не можете изменить его произвольно, вы должны изменить его через мой метод, мы можем посмотреть на следующий код

class Money{
  #money=0;//声明这个属性是私有属性
  constructor(money){
    this.#money=money;
  }
  getMoney(){//获取值
    return this.#money;
  }
  setMoney(money){//写入值
    this.#money+=money;
  }
}
let RMB=new Money(999);
RMB.setMoney(8848)
console.log(RMB.getMoney());

Что ж, частные переменные (атрибуты), на этом мы закончили, давайте взглянем на оператор объединения с нулевым значением!

Нулевой оператор объединения

В нашей обычной работе при взятии атрибута в объекте, если этот атрибут не имеет значения, мы присвоим ему значение по умолчанию, подобное этому

let user={
  name:'Symbol卢',
  age:18
}
console.log(user.name,"name")//Symbol卢 name
console.log(user.like,"like")//undefined "like"
//对象里面没有这个属性的时候,他一个默认值
console.log(user.like || '写代码',"like2")//写代码 like2 

//ES2020 的?? 空值合并操作符
console.log(user.sex??'男',"sex");  //男 sex
  //不存在这个sex属性,就会走后面的默认值,如果存在这个sex属性,就不会走后面的默认值

** нулевой оператор объединения (??)** — логический оператор. Когда левый операнд равен нулю или не определен, он возвращает правый операнд. В противном случае возвращает левый операнд.

В чем разница между ?? и || ???

Самая большая разница между ними — это ' ' и 0. Когда левая часть ?? равна ' ' или 0, она все равно вернет значение слева;

|| выполнит преобразование логического типа для данных слева, поэтому ' ' и 0 будут преобразованы в false и вернут значение справа

дополнительная цепочкаоператор

Уменьшить проблему оценки существования атрибутов при доступе к глубоким объектам.

const a = {};

console.log(a.b.c); // 这里会报Err, 无法从undefined中得到c

console.log(person?.profile?.name); // ""
console.log(person?.hobby?.work); // undefined

console.log(person?.hobby?.work ?? "no Work"); // no Work

в дополнительной цепочке?Указывает, что если выражение слева от вопросительного знака имеет значение, поле после вопросительного знака будет по-прежнему запрашиваться. Как видно из вышеизложенного, использование необязательного связывания может значительно упростить аналогичные утомительные операции предварительной проверки и является более безопасным.

Уведомление:?.Нельзя использовать для задания.

назначение, мы обычно используем可选链操作符а также空值合并运算符использовать в сочетании

let user={
  name:'Symbol卢',
  age:18,
  skill:{
    Web:{
      html:'50%',
      css:'60%',
      js:'80%'
    },
    Server:{
      node:'80%',
      php:'50%',
      net:'60%'
    }
  }
}
console.log(user.name,"name")//Symbol卢 name
console.log(user.like,"like")//undefined "like"
//我们平常的工作中,会这样使用,当我们的对象里面没有这个属性的时候,这样给他一个默认值
console.log(user.like || '写代码',"like2")//写代码 like2 

//ES2020 的??

console.log(user.sex??'男',"sex");  //不存在这个sex属性,就会走后面的默认值,如果存在这个sex属性,就不会走后面的默认值

console.log(user.skill.Web.js,"js")//80% js
//console.log(user.skill.Database.MySql,"MySql")//Uncaught TypeError: Cannot read property 'MySql' of undefined
//空值合并运算符  与 可选链 相结合,可以很轻松处理多级查询并赋予默认值问题
console.log(user?.skill?.Database?.MySql ?? '88%',"MySql")

BigInt

Проблема точности с числами с плавающей запятой в js, наиболее типичная из них0.1+0.2!= 0.3

console.log(0.1+0.2,'0.1+0.2')//0.30000000000000004 "0.1+0.2"
console.log(0.1+0.2==0.3,"0.1+0.2==0.3")//false "0.1+0.2==0.3"

Наибольшее число, которое может обработать JavaScript, — 2^53, его можно узнать с помощью MAX_SAFE_INTEGER:

в JavaScriptNumberТипы могут быть представлены только безопасно-(2^53 -1)к2^53 -1значение диапазона, т.е.Number.MIN_SAFE_INTEGERкNumber.MAX_SAFE_INTEGER, целочисленные вычисления или представления за пределами этого диапазона потеряют точность.

let maxNum=Number.MAX_SAFE_INTEGER;
console.log(maxNum)//9007199254740991

let num1=Number.MAX_SAFE_INTEGER+1;
let num2=Number.MAX_SAFE_INTEGER+2;
console.log(num1==num2,"num1==num2")//true  超过这个范围,就精度丢失了

Для решения этой проблемы ES2020 предоставляет новый тип данных:BigInt. использоватьBigIntЕсть два способа:

  1. добавить после целочисленного литералаn.
let bigIntNum1=9007199254740999n;
console.log(typeof bigIntNum1)//bigint
  1. использоватьBigIntфункция.
let bigIntNum2=BigInt(90071992547409999);
console.log(typeof bigIntNum2)//bigint

Далее давайте оценим двузначное число:

console.log(bigIntNum1==bigIntNum2)//false
//已经解决了之前超过这个精度不能进行计算的问题

мы проходимBigInt, мы можем безопасно выполнять вычисления с большими целыми числами.

let BigNum=bigIntNum1+bigIntNum2;
console.log(BigNum.toString())//99079191802150999

Уведомление:

  1. BigIntНовый примитивный (примитивный) тип данных. Обратите внимание, что стандартные номера иBigIntЧисла нельзя смешивать.
typeof 9007199254740993n; // -> 'bigint'
  1. По возможности избегайте вызова функцийBigIntспособ создания очень больших целых чисел. Поскольку литералы параметров на самом делеNumberОдин экземпляр типа, число за пределами безопасного диапазона, может привести к потере точности.

динамический импорт

В проекте некоторые функции могут использоваться редко, а импорт всех зависимостей может быть пустой тратой ресурсов. теперь доступноasync / awaitДинамически импортировать зависимости при необходимости, можно не загружать все логические ресурсы при инициализации, а только загружать по требованию, что может ускорить отрисовку первого экрана, хотя вебпак, используемый в наших фронтенд-инжиниринговых проектах, уже хорошо поддерживается. быть импортирован по запросу, но теперь он может официально войти в спецификацию ES в 2020 году, и наш js становится все сильнее и сильнее.

Модуль экспорта demo.js:

export const sum=(num1,num2)=>num1+num2;

Динамический импорт:

let fun=async(num1,num2)=>{
  let model=await import('./demo.js');
  console.log(model.sum(num1,num2),"两个数的和")
}
fun(8,9)//17 "两个数的和"

//报错
//Access to script at 'file:///C:/Users/Administrator/Desktop/es11Demo/demo.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
   //demo.js:1 Failed to load resource: net::ERR_FAILED
   //demo.html:13 Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: file:///C:/Users/Administrator/Desktop/es11Demo/demo.js

//报错需要在http服务器环境下,才可以

Создайте http-сервер в корневом каталоге текущего проекта (на компьютере уже есть среда узла)

npm i http-server -gУстановить зависимости

Затем выполните в каталогеhttp-server

globalThis

В JavaScript есть разные способы получения глобальных объектов в разных средах.global, через Интернетwindow, selfд., некоторые даже проходятthisполучить, но черезthisчрезвычайно опасен,thisЧрезвычайно сложный в JavaScript, он сильно зависит от текущего контекста выполнения, что, несомненно, усложняет получение глобального объекта.

  • Окно глобальной переменной: классический способ получить глобальный объект. Но это не работает в Node.js и Web Workers.

  • Глобальная переменная self: обычно доступна только в веб-воркерах и браузерах. Но он не поддерживает Node.js.

  • Глобальная переменная global: действует только в Node.js

Написанный нами файл js может работать в браузере, в среде узла или в среде веб-воркеров.

В настоящее время глобальная переменная не является унифицированной. Мы можем использовать следующие методы для вынесения суждения. В прошлом для получения глобального объекта мы могли использовать глобальную функцию:

var getGlobal = function () {
  if (typeof self !== 'undefined') { return self; }
  if (typeofwindow !== 'undefined') { returnwindow; }
  if (typeof global !== 'undefined') { return global; }
  thrownewError('unable to locate global object');
};
var globals = getGlobal();

И в наш ES11 дает намglobalThis,

а такжеglobalThisЦель состоит в том, чтобы предоставить стандартизированный способ доступа к глобальным объектам сglobalThisПосле этого вы можете получить глобальный объект в любом контексте и в любое время.

globalThis предоставляет стандартный способ получить глобальный объект this в разных средах (то есть сам глобальный объект), так что не беспокойтесь о среде выполнения.

// worker.js
console.log(globalThis === self) //true
// node.js
console.log(globalThis === global) //true
// 浏览器
console.log(globalThis === window) //true

Promise.все ошибки

все знаютPromise.allИмеет возможность одновременного выполнения асинхронных задач. Но его самая большая проблема в том, что если одна из задач не удалась (reject), все задачи зависнут,Promiseвойти напрямуюrejectусловие.

Представьте себе такой сценарий: ваша страница имеет три области, соответствующие трем независимым данным интерфейса, используйтеPromise.allОдновременно для трех интерфейсов, если какая-либо из интерфейсных служб ненормальна, статус будет отклонен, что приведет к тому, что все данные в трех областях на странице будут невозможно отобразить, потому что любойrejectвойдет в обратный вызов catch, что явно неприемлемо, следующим образом:

let a= new Promise((resolve,reject)=>{
  //异步操作...
  resolve({ code: 200,msg:"请求成功"})
})
let b= new Promise((resolve,reject)=>{
  //异步操作...
  resolve({ code: 200,msg:"请求成功"})
})
let c= new Promise((resolve,reject)=>{
  //异步操作...
  reject({ code: 500,msg:"服务器出现异常"})
})
//使用Promise.all 进行并发执行异步任务
Promise.all([a,b,c])
.then((res) => {
    // 只有 上面所有的请求都是 resolve (成功) 的时候才会进入此回调中
    console.log(res,"res")
})
.catch((error) => {
    // 上面的请求中,只要有一个是reject (失败) 就会进入此回调
    console.log(error,"error")
    // error: {code: 500, msg: "服务异常"}
})

Promise.allSettled

когда мы обрабатываем несколькоpromiseМожет быть полезно регистрировать ошибки, возникающие при отладке, для каждого события, особенно когда они взаимозависимы. использоватьPromise.allSettled, он создает новыйpromise,В целомpromiseВозвращает файл, содержащий каждыйpromiseмассив результатов.

let a= new Promise((resolve,reject)=>{
  //异步操作...
  resolve({ code: 200,msg:"请求成功"})
})
let b= new Promise((resolve,reject)=>{
  //异步操作...
  resolve({ code: 200,msg:"请求成功"})
})
let c= new Promise((resolve,reject)=>{
  //异步操作...
  reject({ code: 500,msg:"服务器出现异常"})
})
//使用进行并发请求
Promise.allSettled([a,b,c]).then((data=>{
  console.log(data,"data")
}))

// 返回的数据中 ,status: "fulfilled" 表示请求成功,status: "rejected" 表示请求失败

image-20200713080751426

Преимущества Promise.allSettled

Promise.allSettledа такжеPromise.allПодобно одновременным запросам, но в двух приведенных выше примерах мы явно видели некоторые их отличия при использованииPromise.allПри совершении одновременных запросов, пока есть проблема с одним запросом (аномальным), все запросы не могут нормально получить данные, но в развитии нашего бизнеса нам необходимо обеспечить максимальную доступность нашего бизнеса, т.е. когда мы выполняем параллельных задач, независимо от того, является ли какая-либо из моих параллельных задач нормальной или ненормальной, нам нужно вернуть соответствующее состояние.Promise.allSettledтолько что решил проблему для нас, это иPromise.allТочно так же параметр принимает массив промисов и возвращает новый промис, что означает, что когда все промисы обработаны, мы можем получить статус каждого промиса, независимо от того, была ли обработка успешной или нет. мы можемthenпройти внутрьfilterЧтобы отфильтровать желаемые результаты бизнес-логики, это решаетсяPromise.allДефекты.