BabelJS - Recursos do Transpile ES6 para ES5

Neste capítulo, veremos os recursos adicionados ao ES6. Também aprenderemos como compilar os recursos para ES5 usando BabelJS.

A seguir estão os vários recursos ES6 que discutiremos neste capítulo -

  • Let + Const
  • Funções de seta
  • Classes
  • Promises
  • Generators
  • Destructuring
  • Iterators
  • Literalst de modelo
  • Objeto aprimorado
  • Propriedades padrão, descanso e propagação

Let + Const

Let declara uma variável local de escopo de bloco em JavaScript. Considere o seguinte exemplo para entender o uso de let.

Exemplo

let a = 1;
if (a == 1) {
   let a = 2;
   console.log(a);
}
console.log(a);

Resultado

2
1

A razão pela qual o primeiro console imprime 2 é porque a é declarado novamente usando let e estará disponível apenas no ifquadra. Qualquer variável declarada usando let está apenas disponível dentro do bloco declarado. Declaramos a variável a duas vezes usando let, mas isso não sobrescreve o valor de a.

Esta é a diferença entre as palavras-chave var e let. Quando você declara uma variável usando var, a variável estará disponível no escopo da função ou, se declarada, atuará como uma variável global.

Caso uma variável seja declarada com let, a variável está disponível no escopo do bloco. Se declarado dentro da instrução if, estará disponível apenas dentro do bloco if. O mesmo se aplica a switch, for-loop, etc.

Agora veremos a conversão do código no ES5 usando babeljs.

Vamos executar o seguinte comando para converter o código -

npx babel let.js --out-file let_es5.js

A saída de es6 a es5 para a palavra-chave let é a seguinte -

Vamos usar ES6

let a = 1;
if (a == 1) {
   let a = 2;
   console.log(a);
}
console.log(a);

Transpilado usando babel para ES5

"use strict";

var a = 1;
if (a == 1) {
   var _a = 2;
   console.log(_a);
}
console.log(a);

Se você vir o código ES5, a palavra-chave let é substituída pelo varpalavra-chave. Além disso, a variável dentro do bloco if é renomeada para_a para ter o mesmo efeito que quando declarado com o let palavra-chave.

Const

Nesta seção, aprenderemos sobre o funcionamento da palavra-chave const no ES6 e ES5. A palavra-chave Const também está disponível no escopo; e se estiver fora, gerará um erro. O valor da variável declarada const não pode ser alterado depois de atribuído. Vamos considerar o exemplo a seguir para entender como a palavra-chave const é usada.

Exemplo

let a =1;
if (a == 1) {
   const age = 10;
}
console.log(age);

Resultado

Uncaught ReferenceError: age is not defined at 
      
       :5:13 
      

A saída acima gera um erro, pois a const idade é definida dentro do bloco if e está disponível dentro do bloco if.

Vamos entender a conversão para ES5 usando BabelJS.

ES6

let a =1;
if (a == 1) {
   const age = 10;
}
console.log(age);

Comando

npx babel const.js --out-file const_es5.js

Transpilado para ES6 usando BabelJS

"use strict";

var a = 1;
if (a == 1) {
   var _age = 10;
}
console.log(age);

No caso do ES5, a palavra-chave const é substituída pela palavra-chave var conforme mostrado acima.

Funções de seta

Uma função de seta tem uma sintaxe mais curta em comparação com a expressão de variável. também é chamada de função seta gorda ou função lambda. A função não possui esta propriedade própria. Nesta função, a função de palavra-chave é omitida.

Exemplo

var add = (x,y) => {
   return x+y;
}

var k = add(3,6);
console.log(k);

Resultado

9

Usando BabelJS, iremos transpilar o código acima para ES5.

ES6 - Função de seta

var add = (x,y) => {
   return x+y;
}

var k = add(3,6);
console.log(k);

Comando

npx babel arrowfunction.js --out-file arrowfunction_es5.js

BabelJS - ES5

Usando Babel, a função de seta é convertida em função de expressão variável, conforme mostrado abaixo.

"use strict";

var add = function add(x, y) {
   return x + y;
};

var k = add(3, 6);
console.log(k);

Aulas

ES6 vem com o novo recurso Classes. As classes são semelhantes à herança baseada em protótipo disponível no ES5. A palavra-chave class é usada para definir a classe. As classes são como funções especiais e têm semelhanças, como expressão de função. Ele possui um construtor, que é chamado dentro da classe.

Exemplo

class Person {
   constructor(fname, lname, age, address) {
      this.fname = fname;
      this.lname = lname;
      this.age = age;
      this.address = address;
   }

   get fullname() {
      return this.fname +"-"+this.lname;
   }
}
var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;

Resultado

Siya-Kapoor

ES6 - Classes

class Person {
   constructor(fname, lname, age, address) {
      this.fname = fname;
      this.lname = lname;
      this.age = age;
      this.address = address;
   }

   get fullname() {
      return this.fname +"-"+this.lname;
   }
}
var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;

Comando

npx babel class.js --out-file class_es5.js

BabelJS - ES5

Há um código extra adicionado usando babeljs para fazer a funcionalidade funcionar para as classes da mesma forma que no ES5. O BabelJs garante que a funcionalidade funcione da mesma forma que teria feito no ES6.

"use strict";

var _createClass = 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);
      }
   }
   return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
   };
}();

function _classCallCheck(instance, Constructor) {
   if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
   }
}

var Person = function () {
   function Person(fname, lname, age, address) {
      _classCallCheck(this, Person);

      this.fname = fname;
      this.lname = lname;
      this.age = age;
      this.address = address;
   }

   _createClass(Person, [{
      key: "fullname",
      get: function get() {
         return this.fname + "-" + this.lname;
      }
   }]);

   return Person;
}();

var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;

Promessas

As promessas de JavaScript são usadas para gerenciar solicitações assíncronas em seu código.

Isso torna a vida mais fácil e mantém o código limpo enquanto você gerencia vários retornos de chamada de solicitações assíncronas, que têm dependência. As promessas fornecem uma maneira melhor de trabalhar com funções de retorno de chamada. As promessas fazem parte do ES6. Por padrão, quando você cria uma promessa, o estado da promessa fica pendente.

As promessas vêm em três estados -

  • pendente (estado inicial)
  • resolvido (concluído com sucesso)
  • rejected(failed)

new Promise()é usado para construir uma promessa. O construtor de promessa tem um argumento, que é uma função de retorno de chamada. A função de retorno de chamada tem dois argumentos - resolver e rejeitar;

ambas são funções internas. O código assíncrono que você escreve, ou seja, chamada Ajax, carregamento de imagem, funções de temporização irão para a função de retorno de chamada.

Se a tarefa executada na função de retorno de chamada for bem-sucedida, a função de resolução será chamada; caso contrário, a função de rejeição é chamada com os detalhes do erro.

A linha de código a seguir mostra uma chamada de estrutura de promessa -

var _promise = new Promise (function(resolve, reject) {
   var success = true;
   if (success) {
      resolve("success");
   } else {
      reject("failure");
   }
});
_promise.then(function(value) {
   //once function resolve gets called it comes over here with the value passed in resolve
   console.log(value); //success
}).catch(function(value) {
   //once function reject gets called it comes over here with the value passed in reject
   console.log(value); // failure.
});

Exemplo de promessa ES6

let timingpromise = new Promise((resolve, reject) => {
   setTimeout(function() {
      resolve("Promise is resolved!");
   }, 1000);
});

timingpromise.then((msg) => {
   console.log(msg);
});

Resultado

Promise is resolved!

ES6 - Promessas

let timingpromise = new Promise((resolve, reject) => {
   setTimeout(function() {
      resolve("Promise is resolved!");
   }, 1000);
});

timingpromise.then((msg) => {
   console.log(msg);
});

Comando

npx babel promise.js --out-file promise_es5.js

BabelJS - ES5

"use strict";

var timingpromise = new Promise(function (resolve, reject) {
   setTimeout(function () {
      resolve("Promise is resolved!");
   }, 1000);
});

timingpromise.then(function (msg) {
   console.log(msg);
});

Para promessas, o código não muda quando transpilado. Precisamos usar o babel-polyfill para que funcione em navegadores mais antigos. Os detalhes sobre o babel-polyfills são explicados no capítulo babel - poyfill.

Geradores

A função do gerador é normal function. A função tem uma função de sintaxe especial * com * para a função e a palavra-chave yield a ser usada dentro da função. Isso serve para pausar ou iniciar a função quando necessário. As funções normais não podem ser interrompidas após o início da execução. Ele irá executar a função completa ou parar quando encontrar a instrução return. O gerador tem um desempenho diferente aqui, você pode interromper a função com a palavra-chave yield e iniciá-la chamando o gerador novamente sempre que necessário.

Exemplo

function* generatorfunction(a) {
   yield a;
   yield a +1 ;
}

let g = generatorfunction(8);
console.log(g.next());
console.log(g.next());

Resultado

{value: 8, done: false}
{value: 9, done: false}

ES6 - Gerador

function* generatorfunction(a) {
   yield a;
   yield a +1 ;
}

let g = generatorfunction(8);
console.log(g.next());
console.log(g.next());

Comando

npx babel generator.js --out-file generator_es5.js

BabelJS - ES5

"use strict";

var _marked = /*#__PURE__*/regeneratorRuntime.mark(generatorfunction);

function generatorfunction(a) {
   return regeneratorRuntime.wrap(function generatorfunction$(_context) {
      while (1) {
         switch (_context.prev = _context.next) {
            case 0:
               _context.next = 2;
               return a;

            case 2:
               _context.next = 4;
               return a + 1;
               
            case 4:
            case "end":
               return _context.stop();
         }
      }
   }, _marked, this);
}

var g = generatorfunction(8);
console.log(g.next());
console.log(g.next());

Iteradores

Iterator em JavaScript retorna um objeto JavaScript, que tem valor. O objeto também possui um sinalizador denominado done, que possui valor verdadeiro / falso. Ele dá falso se não for o fim do iterador. Vamos considerar um exemplo e ver o funcionamento do iterador em um array.

Exemplo

let numbers = [4, 7, 3, 10];
let a = numbers[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());

No exemplo acima, usamos uma matriz de números e chamamos uma função na matriz usando Symbol.iterator como o índice.

A saída que obtemos usando o next () na matriz é a seguinte -

{value: 4, done: false}
{value: 7, done: false}
{value: 3, done: false}
{value: 10, done: false}
{value: undefined, done: true}

A saída fornece um objeto com valor e é feita como propriedades. Cadanext()A chamada do método fornece o próximo valor do array e é feita como false. O valor de done será true apenas quando os elementos do array estiverem prontos. Podemos usar isso para iterar em arrays. Existem mais opções disponíveis, como ofor-of loop que é usado da seguinte forma -

Exemplo

let numbers = [4, 7, 3, 10];
for (let n of numbers) {
   console.log(n);
}

Resultado

4
7
3
10

Quando o for-of loopusa a chave, fornece detalhes dos valores da matriz conforme mostrado acima. Verificaremos ambas as combinações e veremos como babeljs as transpila para es5.

Exemplo

let numbers = [4, 7, 3, 10];
let a = numbers[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());

let _array = [4, 7, 3, 10];
for (let n of _array) {
   console.log(n);
}

comando

npx babel iterator.js --out-file iterator_es5.js

Resultado

"use strict";

var numbers = [4, 7, 3, 10];
var a = numbers[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());

var _array = [4, 7, 3, 10];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;

try {
   for (var _iterator = _array[Symbol.iterator](),
      _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
      _iteratorNormalCompletion = true) {
      var n = _step.value;

      console.log(n);
   }
} catch (err) {
   _didIteratorError = true;
   _iteratorError = err;
} finally {
   try {
      if (!_iteratorNormalCompletion && _iterator.return) {
         _iterator.return();
      }
   } finally {
      if (_didIteratorError) {
         throw _iteratorError;
      }
   }
}

Existem alterações adicionadas for-ofloop em es5. Mas iterator.next é deixado como está. Precisamos usarbabel-polyfillpara fazer funcionar em navegadores antigos. Babel-polyfill é instalado junto com o babel e o mesmo pode ser usado a partir de node_modules como mostrado abaixo -

Exemplo

<html>
   <head>
      <script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
      <script type="text/javascript" src="iterator_es5.js"></script>
   </head>
   <body>
      <h1>Iterators</h1>
   </body>
</html>

Resultado

Destruição

A propriedade de desestruturação se comporta como uma expressão JavaScript que descompacta valores de arrays, objetos.

O exemplo a seguir explicará o funcionamento da sintaxe de desestruturação.

Exemplo

let x, y, rem;
[x, y] = [10, 20];

console.log(x);
console.log(y);
[x, y, ...rem] = [10, 20, 30, 40, 50];
console.log(rem);

let z = 0;
({ x, y } = (z) ? { x: 10, y: 20 } : { x: 1, y: 2 });
console.log(x);
console.log(y);

Resultado

10
20
[30, 40, 50]
1
2

A linha de código acima mostra como os valores são atribuídos do lado direito da matriz às variáveis ​​do lado esquerdo. A variável com...rem obtém todos os valores restantes da matriz.

Também podemos atribuir os valores do objeto no lado esquerdo usando o operador condicional, conforme mostrado abaixo -

({ x, y } = (z) ? { x: 10, y: 20 } : { x: 1, y: 2 });
console.log(x); // 1
console.log(y); // 2

Vamos converter o mesmo para ES5 usando babeljs -

comando

npx babel destructm.js --out-file destruct_es5.js

destruct_es5.js

"use strict";

var x = void 0,
   y = void 0,
   rem = void 0;
x = 10;
y = 20;

console.log(x);
console.log(y);
x = 10;
y = 20;
rem = [30, 40, 50];

console.log(rem);

var z = 0;

var _ref = z ? { x: 10, y: 20 } : { x: 1, y: 2 };

x = _ref.x;
y = _ref.y;

console.log(x);
console.log(y);

Literais de modelo

O literal de modelo é um literal de string que permite expressões dentro dele. Ele usa crase (``) em vez de aspas simples ou duplas. Quando dizemos expressão dentro de uma string, significa que podemos usar variáveis, chamar uma função, etc. dentro da string.

Exemplo

let a = 5;
let b = 10;
console.log(`Using Template literal : Value is ${a + b}.`);
console.log("Using normal way : Value is " + (a + b));

Resultado

Using Template literal : Value is 15.
Using normal way : Value is 15

ES6 - Modelo Literal

let a = 5;
let b = 10;
console.log(`Using Template literal : Value is ${a + b}.`);
console.log("Using normal way : Value is " + (a + b));

comando

npx babel templateliteral.js --out-file templateliteral_es5.js

BabelJS - ES5

"use strict";

var a = 5;
var b = 10;
console.log("Using Template literal : Value is " + (a + b) + ".");

console.log("Using normal way : Value is " + (a + b));

Literais de objeto aprimorados

No es6, os novos recursos adicionados aos literais de objeto são muito bons e úteis. Veremos alguns exemplos de literal de objeto em ES5 e ES6 -

Exemplo

ES5
var red = 1, green = 2, blue = 3;
var rgbes5 = {
   red: red,
   green: green,
   blue: blue
};
console.log(rgbes5); // {red: 1, green: 2, blue: 3}

ES6
let rgbes6 = {
   red,
   green,
   blue
};
console.log(rgbes6); // {red: 1, green: 2, blue: 3}

Se você vir o código acima, o objeto em ES5 e ES6 é diferente. No ES6, não precisamos especificar o valor da chave se os nomes das variáveis ​​forem iguais aos da chave.

Vamos ver a compilação para ES5 usando o babel.

Literal de objeto ES6-Enhanced

const red = 1, green = 2, blue = 3;
let rgbes5 = {
   red: red,
   green: green,
   blue: blue
};
console.log(rgbes5);

let rgbes6 = {
   red,
   green,
   blue
};
console.log(rgbes6);

let brand = "carbrand";
const cars = {
   [brand]: "BMW"
}
console.log(cars.carbrand);  //"BMW"

comando

npx babel enhancedobjliteral.js --out-file enhancedobjliteral_es5.js

BabelJS - ES5

"use strict";

function _defineProperty(obj, key, value) {
   if (key in obj) {
      Object.defineProperty(obj, key, {
         value: value, enumerable: true, configurable: true, writable: true
      });
   } else { obj[key] = value; } return obj;
}

var red = 1,
   green = 2,
   blue = 3;
var rgbes5 = {
   red: red,
   green: green,
   blue: blue
};
console.log(rgbes5);

var rgbes6 = {
   red: red,
   green: green,
   blue: blue
};
console.log(rgbes6);

var brand = "carbrand";
var cars = _defineProperty({}, brand, "BMW");

console.log(cars.carbrand); //"BMW"

Propriedades padrão, descanso e propagação

Nesta seção, discutiremos as propriedades padrão, repouso e propagação.

Padrão

Com ES6, podemos usar parâmetros padrão para os parâmetros de função da seguinte forma -

Exemplo

let add = (a, b = 3) => {
   return a + b;
}

console.log(add(10, 20));  // 30
console.log(add(10));      // 13

Vamos transpilar o código acima para ES5 usando o babel.

comando

npx babel default.js --out-file default_es5.js

BabelJS - ES5

"use strict";

var add = function add(a) {
   var b = arguments.length > 1 >> arguments[1] !== undefined ? arguments[1] : 3;
   return a + b;
};

console.log(add(10, 20));
console.log(add(10));

Descansar

O parâmetro de descanso começa com três pontos (...), conforme mostrado no exemplo abaixo -

Exemplo

let add = (...args) => {
   let sum = 0;
   args.forEach(function (n) {
      sum += n;
   });
   return sum;
};

console.log(add(1, 2));    // 3
console.log(add(1, 2, 5, 6, 6, 7));   //27

Na função acima, estamos passando n número de parâmetros para a função add. Para adicionar todos esses parâmetros se fosse no ES5, temos que contar com o objeto de argumentos para obter os detalhes dos argumentos. Com ES6,rest it ajuda a definir os argumentos com três pontos como mostrado acima e podemos percorrê-los e obter a soma dos números.

Note - Não podemos usar argumentos adicionais ao usar três pontos, ou seja, descanso.

Exemplo

let add = (...args, value) => {    //syntax error
   let sum = 0;
   args.forEach(function (n) {
      sum += n;
   });
   return sum;
};

O código acima apresentará erro de sintaxe.

A compilação para es5 é a seguinte -

comando

npx babel rest.js --out-file rest_es5.js

Babel -ES5

"use strict";

var add = function add() {
   for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
   }

   var sum = 0;
   args.forEach(function (n) {
      sum += n;
   });
   return sum;
};

console.log(add(1, 2));
console.log(add(1, 2, 5, 6, 6, 7));

Propagação

A propriedade Spread também possui os três pontos como repouso. A seguir está um exemplo prático, que mostra como usar a propriedade spread.

Exemplo

let add = (a, b, c) => {
   return a + b + c;
}
let arr = [11, 23, 3];
console.log(add(...arr));   //37

Vamos agora ver como o código acima é transpilado usando babel -

comando

npx babel spread.js --out-file spread_es5.js

Babel-ES5

"use strict";

var add = function add(a, b, c) {
   return a + b + c;
};
var arr = [11, 23, 3];
console.log(add.apply(undefined, arr));

Proxies

Proxy é um objeto onde você pode definir o comportamento personalizado para operações como pesquisa de propriedade, atribuição, enumeração, função, invocação, etc.

Sintaxe

var a = new Proxy(target, handler);

O destino e o manipulador são objetos.

  • target é um objeto ou pode ser outro elemento proxy.

  • handler será um objeto com suas propriedades como funções que darão o comportamento quando chamado.

Vamos tentar entender esses recursos com a ajuda de um exemplo -

Exemplo

let handler = {
   get: function (target, name) {
      return name in target ? target[name] : "invalid key";
   }
};

let o = {
   name: 'Siya Kapoor',
   addr: 'Mumbai'
}

let a = new Proxy(o, handler);
console.log(a.name);
console.log(a.addr);
console.log(a.age);

Definimos o destino e o manipulador no exemplo acima e os usamos com o proxy. Proxy retorna o objeto com valores-chave.

Resultado

Siya Kapoor
Mumbai
invalid key

Vamos agora ver como transpilar o código acima para ES5 usando o babel -

comando

npx babel proxy.js --out-file proxy_es5.js

Babel-ES5

'use strict';

var handler = {
   get: function get(target, name) {
      return name in target ? target[name] : "invalid key";
   }
};

var o = {
   name: 'Siya Kapoor',
   addr: 'Mumbai'
};

var a = new Proxy(o, handler);
console.log(a.name);
console.log(a.addr);
console.log(a.age);