habrahabr

Как использовать новейшие функции JavaScript в любом браузере

  • понедельник, 31 августа 2020 г. в 00:26:19
https://habr.com/ru/post/517134/
  • JavaScript


image

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

Polyfilling vs. Transpiling


Оба метода работают с одной и той же целью: мы можем написать код, использующий новые функции, которые не реализованы в нашей целевой среде, а затем применить один из этих методов.

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

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

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

Для этого мы создадим функцию, которая имитирует поведение функции isNaN и добавит её к свойству прототипа Number.

//Имитирует функцию isNaN
if (!Number.isNan) {//ещё не доступно.
    Number.prototype.isNaN = function isNaN(n) {
        return n !== n;
    };
}
let myNumber = 100;
console.log(myNumber.isNaN(100));

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

class mySuperClass {
  constructor(name) {
    this.name = name;
  }
hello() {
    return "Hello:" +this.name;
  }
}
const mySuperClassInstance = new mySuperClass("Rick");
console.log(mySuperClassInstance.hello()); 
//Hello Rick

Полученный код был перенесен с помощью онлайн-транспилятора Babel, и теперь мы можем выполнить его в Internet Explorer 11:

"use strict";
function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } }
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var mySuperClass = /*#__PURE__*/function () {
  function mySuperClass(name) {
    _classCallCheck(this, mySuperClass);
this.name = name;
  }
_createClass(mySuperClass, [{
    key: "hello",
    value: function hello() {
      return "Hello:" + this.name;
    }
  }]);
return mySuperClass;
}();
var mySuperClassInstance = new mySuperClass("Rick");
console.log(mySuperClassInstance.hello()); //Hello Rick

Один из самых распространенных транспиляторов для JavaScript — это Babel. Babel — это инструмент, который был создан для помощи в переносе кода между различными версиями JavaScript и может быть установлен через диспетчер пакетов Node (npm).

Babel стал стандартом для компиляции приложений ECMAScript в версию ECMAScript, которая работает в браузерах, не поддерживающих такие приложения. Babel может компилировать другие версии ECMAScript, такие как React JSX.

В следующих шагах мы увидим, как использовать Babel для транспиляции и выполнения предыдущего класса mySuperMethod на машине Linux с установленным старым Node.js. В других операционных системах, таких как Windows 10 или macOS, действия аналогичны.

Примечание. На вашем компьютере должен быть установлен Node.js. Npm добавлен как функция в установщик Node.js

1. Откройте командную строку и создайте каталог с именем babelExample:

/mkdir babelExample
/cd babelExample

2. Создайте проект npm и оставьте значения по умолчанию. Следующая команда создаст файл с именем package.json:

npm init

image
скриншот содержимого файла package.json после выполнения команды npm init

Здесь index.js (имя файла может быть другим) — это точка входа в наше приложение. Сюда мы собираемся поместить наш код javascript, поэтому создайте файл index.js и поместите в него следующий код:

class mySuperClass {
  constructor(name) {
    this.name = name;
  }
hello() {
    return "Hello:" +this.name;
  }
}
const mySuperClassInstance = new mySuperClass("Rick");
console.log(mySuperClassInstance.hello()); 
//Hello Rick

3. Хотя мы и можем установить Babel CLI глобально, лучше делать это локально, проект за проектом. Следующая команда добавит каталог node_modules и изменит файл package.json, чтобы добавить зависимости Babel:

npm install -save-dev @babel/core @babel/cli

image
скриншот package.json с зависимостями babel

4. Добавьте файл конфигурации .babelrc в корневую папку проекта и включите плагины для преобразований ES2015+.

Примечание. В Babel каждый трансформатор — это плагин, который мы можем установить индивидуально. Каждый пресет представляет собой набор связанных плагинов. Используя пресеты, нам не нужно самостоятельно устанавливать и обновлять десятки плагинов.

Установите пресет для всех функций ES6 (содержит группу плагинов):

npm install @babel/preset-env --save-dev

image
скриншот package.json с зависимостью preset-env babel

Отредактируйте файл .babelrc и добавьте конфигурацию, которая включает преобразования для ES6.

Запишите в файл .babelrc следующий код:

{
  "presets": ["@babel/preset-env"]
}

5. Использование

Примечание. Если вы используете Windows 10 PowerShell, будьте осторожны с кодированием файлов, поскольку при запуске Babel могут возникнуть ошибки синтаксического анализа. Желательно, чтобы файлы были в кодировке UTF-8.

вход: index.js
выход: папка out (здесь Babel оставит перенесённые файлы)

Непосредственно, выполнив следующую команду в консоли:

./node_modules/.bin/babel index.js -d out

С помощью сценария npm, добавляющего следующую строку в ваш файл package.json:

"build": "babel index.js -d out"

image
скриншот содержимого файла package.json после добавления скрипта сборки

Выполните следующую команду:

npm run build

В обоих случаях вы получаете в папке out файл (или файлы), транспилированные в готовый для работы в браузерах, которые не поддерживают синтаксис класса ES6, код:

"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var mySuperClass = /*#__PURE__*/function () {
  function mySuperClass(name) {
    _classCallCheck(this, mySuperClass);
this.name = name;
  }
_createClass(mySuperClass, [{
    key: "hello",
    value: function hello() {
      return "Hello:" + this.name;
    }
  }]);
return mySuperClass;
}();
var mySuperClassInstance = new mySuperClass("Rick");
console.log(mySuperClassInstance.hello());

Заключение



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

Надеюсь, вам понравилась эта статья. Эту и многие другие полезные статьи для начинающих Frontend-разработчиков я транслирую в Telegram-канале Frontend.school(), где также готовлю полезные викторины для проверки своих знаний. Обращаю внимание, что канал является исключительно хобби и желанием помочь и не несет для меня материальной выгоды.