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

В этой статье мы постараемся сделать краткий обзор некоторых новых функций ES2018 / ES2019, которые уже одобрены TC39 (для тех, кто не знает, что такое TC39 , технический комитет, который отвечает за развитие JavaScript к ES2018, принимает предложения, и если они будут приняты, они будут добавлены в следующую редакцию).

ES2018

1- Асинхронная итерация:

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

Давайте посмотрим быстрее:

const iterator = {
        [Symbol.iterator]: () => {
            const data = ['J', 'a', 'v', 'a', 'S', 'c', 'r', 'i' , 'p', 't']
            return {
                next: () => {
                  if (data.length) {
                    return {
                      value: data.shift(),
                      done: false
                    };
                  } else {
                    return {
                      done: true
                    };
                  }
                }
            }
        }
      }
for(const letters of iterator) {
         console.log(letters);
     }

Но что, если у нас есть поток данных, который нам нужно обрабатывать асинхронно ?!

И здесь появляется новая функция асинхронной итерации в ES2018, а не фрагмент кода выше, который реализует логику итерации по данным с использованием синхронной итерации с символами.

Некоторые из вас, скорее всего, спрашивают, почему бы просто не вернуть обещание, которое возвращает массив со всем набором данных?

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



Есть несколько правил для асинхронного вызова нашего объекта:

1- Нам нужно использовать Symbol.asyncIterator вместо Symbol.iterator

2- next() должен вернуть обещание.

3- Чтобы перебрать такой объект, мы должны использовать for...await...of.

Итак, давайте попробуем:

const data = ['J', 'a', 'v', 'a', 'S', 'c', 'r', 'i' , 'p', 't']; 
// let's suppose we'll get this array asynchronously
const iterator = {
        [Symbol.asyncIterator]: () => {
            return {
                next: () => {
                  if (data.length) {
                    return  Promise.resolve({
                      value: data.shift(),
                      done: false
                    });
                  } else {
                    return Promise.resolve({
                      done: true
                    });
                  }
                }
            }
        }
      };
(async function() {
        for await (const item of iterator) {
          console.log(item);
        }
      })();

2- Операторы отдыха / спреда:

В ES2015 операторы rest / spread широко использовались разработчиками вместо использования других методов, таких как concat () и slice (), которые позволяют гораздо проще объединять и копировать массивы.

Но ES2018 поставляется с очень удобными инструментами для объектных литералов и деструктурирования объектов.

1- Распространение:

const obj = {
    a: 1,
    b: 2
  };
const obj1 = {
    ...obj,
    c: 3
  };
console.log(obj1); // { a: 1, b: 2, c: 3 }

Если мы попробуем это на ES2015, то это выдаст нам ошибку, но с новым ... в ES2018 для литерала объекта мы можем получить данные из obj и назначьте их obj1.

Обратите внимание, что имена имеют значение при копировании объекта в другой, поэтому, если есть свойства с таким же именем, будет использоваться последнее из них:

const obj = {
    a: 1,
    b: 2,
    c: 3
  };
const obj1 = {
    ...obj,
    c: 4
  };
console.log(obj1); // { a: 1, b: 2, c: 4 }

Также обратите внимание, что порядок имеет значение при копировании объектов:

const obj = {
  a: 1,
  b: 2,
};
const obj1 = {
  c: 3,
  ...obj
};
console.log(obj1); // {c: 3, a: 1, b: 2}

2- Отдых:

Деструктуризация массивов - отличный шаблон для извлечения данных из массивов в ES2015, поэтому TC39 сделал это возможным и внутри объектов в ES2018:

const obj = {
  a: 1,
  b: 2,
  c: 3
 };
 const { a, ...rest } = obj;
console.log(a); // 1
console.log(rest); // { b: 2, c: 3 }

Приведенный выше код позволяет скопировать перечислимые свойства в новый объект и скопировать конкретное требуемое свойство, но есть некоторые ограничения, когда rest свойства всегда должны находиться в конце объекта:

const obj = {
  a: 1,
  b: 2,
  c: 3
 };
 const { ...rest, a } = obj;
console.log(rest); // "SyntaxError: Rest element must be last element

Также нам нужно помнить, что мы можем использовать только один раз оператор отдыха на уровне:

const obj = {
    a: {
        b: 1,
        c: 2,
        d: 3,
    },
    e: 4,
    f: 5
};
const { ...rest, ...rest1} = obj; // "SyntaxError: Rest element must be last element
const {a: {b, ...rest}, ...rest1} = obj;
console.log(b); // 1
console.log(rest); // { c: 2, d: 3}
console.log(rest1); // { e: 4, f: 5}

Флаг 3 - точка (.) для регулярного выражения:

Пришло очень полезное обновление для расширения возможностей RegExp. Поскольку раньше мы знали, что \n не соответствует символу конца строки точка (.) И астральным (не BMP) символам, таким как эмодзи в шаблоне RegExp:

console.log(/^.$/.test('\n')); // false
console.log(/^.$/.test('😀')); // false

В то время как ECMAScript распознает терминаторы строки:

  • ЛИНИЯ ПОДАЧИ U + 000A (LF) (\n)
  • ВОЗВРАТ ПЕРЕВОЗКИ U + 000D (CR) (\r)
  • СЕПАРАТОР ЛИНИИ U + 2028
  • U + 2029 РАЗДЕЛИТЕЛЬ ПАРАГРАФОВ

Таким образом, у разработчиков не могло быть выбора сопоставить точку (.) Только несколькими способами:

console.log(/^[\s\S]$/.test('\n')); // true
console.log(/^[\w\W]$/.test('\n')); // true  
console.log(/^[^]$/.test('\n'));    // true

Затем разработчики ECMAScript придумали решение, следующее за другими языками программирования, такими как Perl и PHP, добавив \s для соответствия символу конца строки:

console.log(/newDotAll./s.test('newDotAll\n')); // true
console.log(/^.$/s.test('\n')); // true
console.log(/^.$/s.test('\r')); // true
console.log(/^.$/s.test('\u{2028}')); // true

4- Promise.prototype.finally ():

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

Вот как работает Promise и так работает новый метод finally:

let date = new Promise((resolve, reject) => {
  let response = Boolean(Math.round(Math.random()));
  if(response) {
    resolve('she will go out with me');
  } else {
    reject('she said no');
  }
});
date.then((success) => {
  console.log(success);
}).catch((failure) => {
   console.log(failure);
}).finally(()=> {
  console.log('I took my chance!');
});

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

Здравствуйте, ES2019

1-квартира / квартираКарта:

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

плоский:

Плоский метод в основном берет массив массивов, а затем объединяет их в один массив, давайте посмотрим:

const arr = [1,2,3,4,5, [6,7, [8,9,10]], [11, 12, 13] ];

Раньше мы применяли нормальную функцию примерно так:

const customFlat = (arr) => {
  return arr.reduce((acc, cur) => {
    return acc.concat(Array.isArray(cur) ? customFlat(cur) : cur);
  }, []);
};
console.log(customFlat([1,2,3,4,5, [6,7, [8,9,10]], [11, 12, 13] ])); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

На помощь приходит такая квартира!

const arr = [1,2,3,4,5, [6,7, [8,9,10]], [11, 12, 13] ];
const flatArrLev1 = arr.flat(); // [1, 2, 3, 4, 5, 6, 7, [8, 9, 10], 11, 12, 13]

Итак, здесь мы видим, что flat () берет первый вложенный уровень массива, а затем берет его на верхний уровень и принимает один аргумент, который является глубиной, которая указывает, на сколько уровней нужно сгладить. Обратите внимание, что по умолчанию глубина равна 1.

const flatArrLev2 = arr.flat(2); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Итак, мы замечаем, что [6,7] и [11, 12, 13] находились на уровне 1, поэтому они автоматически переходят на верхний уровень, затем во второй операции flatArrLev2 мы сделали это на более глубоком уровне на [8, 9, 10], так что у нас есть новый свежий массив без вложенных значений.

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

const flatInfinity = arr.flat(Infinity);

flatMap:

FlatMap - еще одна интересная функция, которая применяет две комбинированные операции к массиву, сначала вызывая map () для каждого элемента массива, а затем flat (), чтобы преобразовать результат в новый массив:

const arr1 = [ [1, 2], [3, 4], [5, 6] ];
console.log(arr1.flatMap(x => x[0]+x[1]));

1- Сопоставьте эти вложенные массивы и выполните вычисления по ним: [1,2]…

Двойное выравнивание

3- Результат: [3, 7, 11]

2- Object.fromEntries ():

За последние годы в Object добавлено множество методов, один полезный был добавлен в ES2019.



Object.fromEntries - это совершенно новый метод, который делает инверсию Object.entries и принимает итерируемый Сопоставьте или подобный карте массив и преобразует список пар "ключ-значение" в новый объект:

Так что давай попробуем;)

Object.fromEntries(new Map([["a", "b"], ["c", "d"]]));
// Object { a: "b", c: "d" }

Object.fromEntries([["a", "b"], ["c", "d"]]); 
// Object { a: "b", c: "d" }

PS: он полностью поддерживается не всеми браузерами, поэтому вам необходимо проверить свой движок перед его использованием.

3- trimStart / trimEnd:

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

let name = " Hamza Amdouni ";

console.log(name.trimStart()); // "Hamza Amdouni "
  
console.log(name.trimEnd()); // " Hamza Amdouni"
console.log(name.trimStart() === name.trimLeft()); // true

4- Symbol.prototype.description:

Описание символа было немного утомительным, в то время как у нас был только один способ - преобразовать его в строку:

const symbol = Symbol('new Symbol'); 
console.log(String(symbol) === 'Symbol(new Symbol)'); // true

Благодаря Майклу Фикарре с его новым предложением он дал нам простой способ доступа к дескриптору символа:

const symbol = Symbol('new Symbol');
console.log(symbol.description === 'new Symbol'); // true

Заключение

В конце концов, я просто хотел поделиться тем, что я узнал из ES2018 / ES2019, и любые предложения, комментарии принимаются, пока я с нетерпением жду ваших аплодисментов;)