🔥"Пример" ES2021 грядет, Blue покажет вам, что стоит знать

JavaScript

OIP.bmp

Обзор ES12

ES2021 (сокращенно ES21) выйдет в середине 2021 года, так что, каких новинок стоит ждать, Blue вам покажет

На самом деле многие фичи мы используем уже давно, а официально доработали только в ES12, так что знакомые лица все встретят

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

  • Метод replaceAll строки
  • разделитель чисел
  • логический оператор присваивания
  • Promise.any
  • WeakRefs Слабые ссылки
  • Слушатель повторного использования слабых ссылок FinalizationRegistry
  • Международные локализованные строки

Я, наверное, это чувствую, давай поговорим об этом один за другим

Примечания: Следующая «практичность» имеет большую личную субъективную окраску и предназначена только для справки - в зависимости от того, что используется, в зависимости от того, что на 100% практично.

Подробное объяснение новых возможностей ES12

1- метод replaceAll строки

Практичность: ★★★★☆

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

const str='我是blue,这里好多abc abc的';

//1-普通replace
str.replace('b', '*');  //'我是*lue,这里好多abc abc的'

//2-传统的解决方法,正则+g
str.replace(/b/g, '*'); //'我是*lue,这里好多a*c a*c的'

//3-新方法-replaceAll
str.replaceAll('b', '*');//'我是*lue,这里好多a*c a*c的'

На первый взгляд эта штука кажется бесполезной, разве не хорошо мне быть штатной, на самом деле в ней тоже есть скрытая функция, можно ей воспользоваться

const str='我是blue,这里好多abc abc的';

//replaceAll也可以用于正则
str.replaceAll(/b/g, '*');  //'我是*lue,这里好多a*c a*c的'

//而且如果没有g,会报错
str.replaceAll(/b/, '*');  //报错"replaceAll called with a non-global RegExp argument"

На первый взгляд, эта фича кажется самодовольной, «У меня что, обида на себя? Насколько хорошо мне использовать замену, и я не сообщу об ошибке», но это не так:

  • Использование замены эквивалентно предоставлению выбора обычному. Есть ли опция g для обычного, которая будет напрямую мешать моим результатам (обновление 1 или все)
  • Использование replaceAll эквивалентно принудительной замене всего, поведение кода исправлено, что помогает нам устранять проблемы

типичное применение

Повышение надежности кода и упрощение отладки

Если вы намерены заменить все совпадающие элементы, то использование replaceAll — хороший способ предотвратить отклонение поведения программы от целевого из-за неправильного написания и передачи регулярного, итакже может устранять проблемы с кодом для вас

2 - разделитель чисел

Практичность: ★★★★☆

Число можно разделить на несколько частей для улучшения читаемости, аналогично тысячным.

let a=123456;
let b=12_345_6;

console.log(a===b);  //true

Единственное использование этой функции - улучшить читаемость, особенно если большие числа вызывают головокружение, это очень практично.

const maxCount=1000000;  //一顿数,个、十、百...、数到几位来着?

//这样就很清晰
const maxCount=1_000_000; //1兆(不是1M)
const maxCount=100_0000;  //100万

типичное применение

Используется для повышения удобочитаемости больших чисел.

3- Логический оператор присваивания

Практичность: ★★☆☆☆

Многие присваивания (+=, -=, %= и т. д.) могут быть сокращены в js, а начиная с ES12, логические операции также могут быть сокращены.

//等价
a = a&&b;
a &&= b;

//等价
a = a||b;
a ||= b;

//等价
a = a??b;
a ??= b;

&&и||Это более распространено, я думаю, что все знакомы с ним.??Может быть кто-то не видел, просто поясню вкратце -??Определите, является ли он пустым (нулевым или неопределенным)

c=a ?? b;
//等价于
if(a!==null && a!==undefined){
  c=a;
}else{
  c=b;
}

??Его достаточно удобно использовать, потому что он работает только с нулевыми и неопределенными значениями, а на другие ложные значения не реагирует (типа: 0, "", false и т.д.)

Кратко обобщить

  • a||=b:еслиa为真,ноa=a;в противном случаеa=b
  • a&&=b:еслиaверно, тоa=b;в противном случаеa=a
  • a??=b:еслиa为空,ноa=b;в противном случаеa=a

типичное применение

Когда любая логическая операция выполняется одновременно с присваиванием, вы можете использовать

//假设:校验用户权限
let isOK=true;

isOK &&= logined;
isOK &&= user.paied;
isOK &&= count>0;  //其实直接连起来写也差不多。。。(小声)

if(isOK){
  await db.query(...);
}else{
  throw new Error('invalid user state');
}

4-Promise.any

Практичность: ★★★★☆

Выполнять несколько асинхронных задач (то есть экземпляров обещаний) одновременно. Если одна из них завершается успешно (разрешено), возвращается успех. Если все терпят неудачу, сообщает об ошибке (отклонено). Вот важный момент:

  • Если кто-то из них преуспевает, это считается успехом; если оба терпят неудачу, это считается провалом (Дело в том, что вы поймете, почему через минуту)
//实例1:都成功,时间不同
Promise.any([
  //任务1:0.5秒后返回5
  new Promise((resolve, reject)=>{
    setTimeout(()=>resolve(5), 500);
  }),
  //任务2:1秒后返回12
  new Promise((resolve, reject)=>{
    setTimeout(()=>resolve(12), 1000);
  }),
]).then(console.log);

//结果是5,因为5先返回
//实例2:有成功有失败
Promise.any([
  //任务1:0.5秒后失败
  new Promise((resolve, reject)=>{
    setTimeout(()=>reject(), 500);
  }),
  //任务2:1秒后返回12
  new Promise((resolve, reject)=>{
    setTimeout(()=>resolve(12), 1000);
  }),
]).then(console.log);

//结果是12,任务1失败后,继续等待直到12返回

Отличие от расы

Прочитав приведенное выше введение и примеры, вы должны почувствовать, что это то же самое, чтоPromise.raceРазве это не то же самое? чем ты занимаешься

На самом деле разница между any и расой вполне очевидна(Чтобы усилить впечатление, ознакомьтесь с ключевыми моментами, упомянутыми выше.)

  • race: просто посмотреть, что быстрее, правильно или неправильно

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

  • any: подождите, пока не появится правильный

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

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

//为了突出对比,将忽略部分代码

Promise.race([
  reject(1, 500ms),
  resolve(2, 1000ms)
])  //在500ms时,reject结束——因为任务1更快,它的对错决定整体结果

Promise.any([
  reject(1, 500ms),
  resolve(2, 1000ms)
])  //在1000ms时,resolve结果2——因为任务1错了之后,会继续等待,直到任务2返回

типичное применение

Полезно для операций, которые должны возвращать результаты из нескольких источников.

//假设从三个不同地区的源获取数据——用于判别用户用哪个源更快
Promise.any([
  request('//bj.zhinengshe.com/1.json'),
  request('//sh.zhinengshe.com/1.json'),
  request('//sz.zhinengshe.com/1.json'),
]).then(res=>{
  if(res.name=='bj'){
    //后续以bj线交互
  }else if(res.name=='sh'){
    ...
  }else{...}
});

//备注:仅作为实例使用,现在智能多线和cdn这么发达,压根不用这么折腾

5-WeakRefs Слабые ссылки

Практичность: ★★★★★

Слабые ссылки распространены, но раньше у нас были толькоWeakMapиWeakSetWeakRefsПозволяет нам создавать слабые ссылки на произвольные объекты

Что такое слабая ссылка

Мы знаем, что JS имеет тот же механизм сборки мусора GC, что и java, и также использует引用计数чтобы определить, нужно ли его перерабатывать, поэтому сильные ссылки (например, переменные) сохранят данные живыми,в то время как сами слабые ссылки не увеличивают количество ссылок, когда все сильные ссылки объекта исчезнут и останутся только слабые ссылки, их можно переработать

//普通Map
let obj={name: 'blue', org: 'zhinengshe'};  //引用计数:1 (obj变量)
let map=new Map();

map.set(obj, 100);  //引用计数:2  (obj、map)

obj=null;  //不会回收
//WeakMap
let obj={name: 'blue', org: 'zhinengshe'};  //引用计数:1 (obj变量)
let map=new WeakMap();

map.set(obj, 100);  //引用计数:1  (obj变量)

obj=null;  //回收

типичное применение

Когда объекты необходимо сохранить, но они могут быть восстановлены в любое время (например, кеш) — особенно полезно для больших объектов данных (таких как изображения, аудио и видео и т. д.)

//方法1——不带缓存
export async function loadImage(name){
  //这里的逻辑不重要,就是读个图片过来
  return await request(imgRoot+name);
}

//方法2——带有缓存的
//重点在这里
const imgCache=new Map();
export async function loadImageCached(name){
  let val=imgCache.get(name);

  //检查缓存
  if(val){
    const img=val.deref();
    if(img)return img;
  }

  //没有缓存,重新读
  const img=await loadImage(name);

  /*************************
        重点来了
  *************************/
  imgCache.set(name, new WeakRef(img));

  return img;
}

Дело в томnew WeakRef(img), он может создать слабый ссылочный объект, который можно переработать в любое время, не занимая счетчик ссылок.

6-FinalizationRegistry слушатель повторного использования слабых ссылок

Практичность: ★★☆☆☆

Эта функция такая же, как и вышеWeakRefsВ связи с этим его можно использовать для мониторинга уведомлений о переработке слабых ссылок, но большинство наших приложений не будут полагаться на переработку слабых ссылок — поскольку вы уже являетесь слабой ссылкой, вам все равно, когда кто-то удалит ее для вас; если вы заботиться, то насколько хорошо использовать сильные ссылки

Поэтому эта функция не очень практична и не влияет на большинство приложений.

//回收通知对象
const registry=new FinalizationRegistry((value)=>{
  console.log('对象被回收了', value);  //这里的value是下面注册时传入的
});

(()=>{
  //构建一个对象,它回收时我们希望有回调
  const obj={name: 'blue'};
  
  registry.register(obj, '这里的值,会作为value传给callback');
})();

//函数结束后,obj被回收时可以看到——"对象被回收了" "这里的值,会作为value传给callback"
//备注:回收动作可能立即触发,也可能很久才触发,不可预测

типичное применение

Запускается, когда вам нужно прослушать действие по переработке объекта

7-строка международной локализации

Практичность: ★★★☆☆

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

const l=['a','b','c'];

//按英文输出
new Intl.ListFormat('en-GB').format(l);
//"a, b and c"

//按中文输出
new Intl.ListFormat('zh').format(l)
//"a、b和c"


//和
new Intl.ListFormat('en-GB', {type: 'conjunction'}).format(l)
//"a, b and c"

//或
new Intl.ListFormat('en-GB', {type: 'disjunction'}).format(l)
//"a, b or c"

также может обрабатывать дату и время

//英文格式
new Intl.DateTimeFormat('en', {}).format(Date.now())
//"3/10/2023"

//中文格式
new Intl.DateTimeFormat('zh', {}).format(Date.now())
//"2023/3/10"

типичное применение

Для сценариев с низкими требованиями к формату быстро реализовать локализацию данных (есть свои претензии: легко сказать, но i18n на самом деле много чего не хватает)

if(navigator.language=='en-US'){
  toast(
    `Thanks for signing up zhinengshe's course, your course will start at: `+
    new Intl.DateTimeFormat('en', {}).format(courseTime)
  );
}else{
  toast(
    '感谢报名智能社的课程,课程将开始于:'+
    new Intl.DateTimeFormat('zh', {}).format(courseTime)
  );
}

Суммировать

Пришло время разобраться в том, что сказала Блю, так что сначала

15-三连

  • replaceAll:**[Рекомендуется]**Принудительно заменить все совпадающие элементы, следует использовать в первую очередь, когда нужно заменить их все, что помогает найти ошибки программы (например: в обычном не написано g)
  • Разделитель чисел: используется для улучшения читаемости длинных чисел.
  • Логический оператор присваивания: это сокращение, присваивание и логические операции (&&, ||, ??) могут использоваться вместе.
  • Promise.any: ** [рекомендуется] ** Выполните несколько операций одновременно и выполните, когда любая операция успешна или все сбой. Например, гонка более практичная
  • WeakRefs:**[Рекомендуется]** Слабые эталонные сценарии, такие как кэширование, очень практичны.
  • FinalizationRegistry: не очень полезно, если ваша программа не использует механизмы сбора GC (например, написание инструментов разработчика)

Есть ошибка? Хотите добавить?

Спасибо за просмотр этого урока. Если у вас есть какие-либо вопросы или вы хотите связаться со мной, пожалуйста, оставьте сообщение напрямую. Если вы обнаружите какую-либо неуместность в статье, пожалуйста, укажите на нее, заранее спасибо