ES2017 или ES8 - это последняя спецификация ECMAScript, выпущенная в июне прошлого года. В ES2016 / ES7 очень мало серьезных изменений по сравнению с ES2015 / ES6 (обещания, функции стрелок и другие элементы современного языка). Но в ES2017 добавлено несколько интересных функций. Вы можете прочитать полную спецификацию ES2017 здесь. Но я не думаю, что вам захочется читать 885-страничную спецификацию, поэтому давайте углубимся в основные изменения в ES2017, а также рассмотрим предложения ES2018.

Основные изменения:
1. Асинхронные функции
2. Общая память и атомики

Незначительные изменения:
3. Object.values ​​() и Object.entries ()
4. Object.getOwnPropertyDescriptors ()
5. Заполнение строк
6. Конечные запятые в списках параметров функций и вызовах

По моему мнению, самая захватывающая особенность ES2017 - это асинхронные функции (async / await), поскольку они позволяют писать более чистый код с меньшим количеством строк при работе с обещаниями. Он обеспечивает простой и элегантный способ обработки асинхронных операций.

1. Асинхронные функции
Асинхронные функции (или async / await) - это оболочки поверх обещаний. Мотивом этого является упрощение обработки асинхронного кода. Теперь вы можете определять асинхронные функции, которые могут иметь или не иметь какие-либо блокирующие операции (обещанные асинхронные), используя ключевое слово await.

function getVolume(length, breadth, height) {
  return new Promise(resolve => { 
    setTimeout(() => { 
      resolve(length * breadth * height);
    }, 3000);
  });
}
async function printVolume(length, breadth, height) {
  console.log(1);
  const text = await getVolume(length, breadth, height);
  console.log(`Volume: ${text}`);
  console.log(2);
}
console.log(printVolume(5, 4, 3));

Это напечатает следующие значения

1
Volume: 60 // will be printed after 3-second delay
2

Теперь, если мы выполним следующее вместо

console.log (printVolume (5, 4, 3)); в приведенном выше коде мы получим другой результат:

console.log(3);
console.log(printVolume(5, 4, 3));
console.log(4);

Это напечатает следующие значения

3
1
4
Volume: 60 // will be printed after 3-second delay
2

Это потому, что вызов функции не блокирует выполнение основного потока.

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

var printVolume = (function() {
  var _ref = _asyncToGenerator(
    /*#__PURE__*/ regeneratorRuntime.mark(function _callee(
      length,
      breadth,
      height
    ) {
      var text;
      return regeneratorRuntime.wrap(
        function _callee$(_context) {
          while (1) {
            switch ((_context.prev = _context.next)) {
              case 0:
                console.log(1);
                _context.next = 3;
                return getVolume(length, breadth, height);
              case 3:
                text = _context.sent;
                console.log("Volume: " + text);
                console.log(2);
              case 6:
              case "end":
                return _context.stop();
            }
          }
        },
        _callee,
        this
      );
    })
  );
return function printVolume(_x, _x2, _x3) {
    return _ref.apply(this, arguments);
  };
})();
function _asyncToGenerator(fn) {
  return function() {
    var gen = fn.apply(this, arguments);
    return new Promise(function(resolve, reject) {
      function step(key, arg) {
        try {
          var info = gen[key](arg);
          var value = info.value;
        } catch (error) {
          reject(error);
          return;
        }
        if (info.done) {
          resolve(value);
        } else {
          return Promise.resolve(value).then(
            function(value) {
              step("next", value);
            },
            function(err) {
              step("throw", err);
            }
          );
        }
      }
      return step("next");
    });
  };
}

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

2. Общая память и атомики
ES2017 представил конструктор SharedArrayBuffer и глобальный объект Atomics с их вспомогательными функциями.

Javascript работает в одном потоке, но вы можете выполнять задачи асинхронно. Движок JS запускает эти задачи в отдельных потоках, а затем передает их результат обратно в основной поток с помощью обратных вызовов, или вы можете использовать веб-рабочих, которые являются тяжелыми процессами со своей собственной глобальной средой, и по умолчанию ничего не разделяется, а затем SIMD (одна инструкция, несколько данных) была введен для низкоуровневого параллелизма данных.

SharedArrayBuffer и Atomics представлены для достижения высокоуровневого параллелизма. Объект SharedArrayBuffer совместно используется несколькими рабочими процессами и основным потоком, поэтому вы можете быстро и легко обмениваться данными, а координация между общими данными проста.

// main.js
const worker = new Worker(‘worker.js’);
const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 100); // 100 primes shared memory
worker.postMessage({sharedBuffer});

// worker.js
self.addEventListener(‘message’, function (event) {
  const {sharedBuffer} = event.data;
  const ia = new Int32Array(sharedBuffer); 
});

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

// main.js
const worker = new Worker(‘worker.js’);
const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 100000); // 100000 primes
const ia = new Int32Array(sab); // ia.length == 100000
const primes = new PrimeGenerator();
for ( let i=0 ; i < ia.length ; i++ )
  ia[i] = primes.next();
worker.postMessage(ia);
// worker.js
let ia;
self.addEventListener(‘message’, function (event) {
  ia = event.data; // ia.length == 100000
  console.log(ia[30]); // prints 100, the 31st prime
  ia[30] = 200; // update the data
}

Он обновит общий буфер, но трудно сказать, сколько времени потребуется, чтобы запись появилась от одного рабочего к другому (это зависит от системы).

Таким образом, для достижения синхронизации используются атомарные операции. Новый глобальный объект Atomics предоставляет несколько атомарных операций в виде статических методов. Атомика используется для синхронизации (метод загрузки и сохранения), ожидания (метод ожидания и пробуждения) и других арифметических атомарных операций (добавление, подметоды). Операции Atomics (загрузка, сохранение и другие) обеспечивают безопасное чтение и запись.

Подробнее на https://github.com/tc39/ecmascript_sharedmem/blob/master/TUTORIAL.md

3. Object.values ​​() и Object.entries ()
В JS вы можете получить доступ к свойствам объекта с помощью Property Accessors (obj [prop '], obj.prop), поэтому вам необходимо иметь предварительный знание ключа. Вы можете использовать Object.keys (obj), чтобы получить все ключи obj в виде массива, но его беспокойные операции при выполнении сложных операций. В ES2017 появились два новых метода - Object.values ​​() и Object.entries ().

Object.values ​​(obj) - возвращает массив значений.
Object.entries (obj) - возвращает массив пар [ключ, значение].
Object.keys (obj) - возвращает массив ключи.

const user = {
  name: "Ridham",
  id: 12,
  post: "SE"
};
console.log(Object.values(user)); // ["Ridham", 12, "SE"]
console.log(Object.entries(user)); // [["name", "Ridham"], ["id", 12], ["post", "SE"]]
console.log(Object.keys(user)); // ["name", "id", "post"]

4. Object.getOwnPropertyDescriptors ()
Метод getOwnPropertyDescriptors возвращает все собственные дескрипторы свойств (перечисляемые или нет) указанного объекта. Он не включает свойства, унаследованные от прототипа объекта.
Он в основном используется для создания неглубокого клона или копирования свойств в другой объект. перед этим используется Object.assign (), но он не копирует свойства с атрибутами, отличными от значений по умолчанию.
Вы можете использовать Object.defineProperties () с getOwnPropertyDescriptor () для копирования свойств

const source = {
 set log(data) {
        console.log(data);
    }
};
// clone object
const clone = Object.create(
  Object.getPrototypeOf(obj), 
  Object.getOwnPropertyDescriptors(obj) 
);
// copy properties
const target = {};
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
console.log(Object.getOwnPropertyDescriptor(target, 'log'));

5. Заполнение строк
ES2017 представил методы padEnd () и padStart () для применения отступов к строке. Перед этим мы должны написать код полифиллов, чтобы добиться этого.

console.log(‘1.00’.padStart(15)) 
console.log(‘40,000.00’.padStart(15)) 
console.log(‘199,500.00’.padStart(15)) 
            1.00
       40,000.00
      199,500.00
console.log(‘1.00’.padEnd(15, ‘*’)) 
console.log(‘40,000.00’.padEnd(15, ‘*’)) 
console.log(‘199,500.00’.padEnd(15, ‘*’))
1.00***********
40,000.00******
199,500.00*****

6. Конечные запятые в списках параметров функций и вызовах
из ES2017 конечная запятая в параметре функций (es2017 (1, 3,);) не вызывает SyntaxError. Аналогично завершению запятых в литералах объектов ({x: 1,}) и литералах массива [1, 3,]

Предложения ES2018

Готовые предложения

Снятие ограничения литералов шаблона:
- В настоящее время вы не можете использовать escape-символы Unicode (\ u, \ 0100, \ xFF) в литералах шаблона. Это вызывает SyntaxError. Итак, предложение состоит в том, чтобы снять ограничение на escape-последовательности.

Флаг s (dotAll) для регулярных выражений:
- в шаблонах регулярных выражений точка. соответствует одному символу, независимо от того, что это за символ.
В ECMAScript есть два исключения:

. не соответствует астральным персонажам. Это исправляет установка флага u (Unicode).
. не соответствует символам конца строки.

/foo.bar/.test(‘foo\nbar’);
// → false

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

На ранней стадии (3,2 и 1) все еще есть много интересных предложений, таких как пересмотр toString (стадия - 3), Асинхронная итерация (стадия 3), Rest / Spread Properties (стадия 3), Promise.prototype.finally (стадия 3), BigInt (stage-3), поля публичных экземпляров класса и поля частных экземпляров (stage-3), String.prototype. {TrimStart, trimEnd} (stage-2), Atomics.waitAsync (stage-2) и многие другие .

Ознакомиться со всеми предложениями можно здесь.

Если вам понравилась эта статья, дайте мне много аплодисментов - для писателя это мир. Следуйте за мной, если вы хотите прочитать больше статей о JS, технологиях и стартапах.