BabelJS - Transpile las características de ES6 a ES5

En este capítulo, veremos las características agregadas a ES6. También aprenderemos a compilar las características en ES5 usando BabelJS.

A continuación se muestran las diversas características de ES6 que analizaremos en este capítulo:

  • Let + Const
  • Funciones de flecha
  • Classes
  • Promises
  • Generators
  • Destructuring
  • Iterators
  • Plantilla Literalst
  • Objeto mejorado
  • Propiedades predeterminadas, de descanso y propagación

Let + Const

Let declara una variable local de alcance de bloque en JavaScript. Considere el siguiente ejemplo para comprender el uso de let.

Ejemplo

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

Salida

2
1

La razón por la que la primera consola imprime 2 es porque a se declara de nuevo usando let y estará disponible solo en el ifbloquear. Cualquier variable declarada usando let solo está disponible dentro del bloque declarado. Hemos declarado la variable a dos veces usando let, pero no sobrescribe el valor de a.

Esta es la diferencia entre las palabras clave var y let. Cuando declaras una variable usando var, la variable estará disponible dentro del alcance de la función o si se declara actuará como una variable global.

En caso de que una variable se declare con let, la variable está disponible dentro del alcance del bloque. Si se declara dentro de la instrucción if, solo estará disponible dentro del bloque if. Lo mismo se aplica a switch, for-loop, etc.

Ahora veremos la conversión de código en ES5 usando babeljs.

Ejecutemos el siguiente comando para convertir el código:

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

La salida de es6 a es5 para la palabra clave let es la siguiente:

Deje que use ES6

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

Transpilado usando babel a ES5

"use strict";

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

Si ve el código ES5, la palabra clave let se reemplaza por la varpalabra clave. Además, la variable dentro del bloque if se renombra a_a tener el mismo efecto que cuando se declara con el let palabra clave.

Const

En esta sección, aprenderemos sobre el funcionamiento de la palabra clave const en ES6 y ES5. La palabra clave Const también está disponible dentro del alcance; y si está afuera, arrojará un error. El valor de la variable declarada const no se puede cambiar una vez asignado. Consideremos el siguiente ejemplo para entender cómo se usa la palabra clave const.

Ejemplo

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

Salida

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

La salida anterior arroja un error ya que la constante se define dentro del bloque if y está disponible dentro del bloque if.

Entenderemos la conversión a ES5 usando BabelJS.

ES6

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

Mando

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

Transpilado a ES6 usando BabelJS

"use strict";

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

En el caso de ES5, la palabra clave const se reemplaza con la palabra clave var como se muestra arriba.

Funciones de flecha

Una función de flecha tiene una sintaxis más corta en comparación con la expresión de variable. también se denomina función de flecha grasa o función lambda. La función no tiene esta propiedad propia. En esta función, se omite la función de palabra clave.

Ejemplo

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

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

Salida

9

Usando BabelJS, transpilaremos el código anterior a ES5.

ES6 - Función de flecha

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

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

Mando

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

BabelJS - ES5

Usando Babel, la función de flecha se convierte en función de expresión variable como se muestra a continuación.

"use strict";

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

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

Clases

ES6 viene con la nueva función Clases. Las clases son similares a la herencia basada en prototipos disponible en ES5. La palabra clave class se usa para definir la clase. Las clases son como funciones especiales y tienen similitudes como expresión de función. Tiene un constructor, que se llama dentro de la clase.

Ejemplo

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;

Salida

Siya-Kapoor

ES6 - Clases

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;

Mando

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

BabelJS - ES5

Se agrega código adicional usando babeljs para que la funcionalidad funcione para las clases igual que en ES5. BabelJs se asegura de que la funcionalidad funcione igual que en 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;

Promesas

Las promesas de JavaScript se utilizan para administrar solicitudes asincrónicas en su código.

Facilita la vida y mantiene el código limpio a medida que administra múltiples devoluciones de llamada de solicitudes asíncronas, que tienen dependencia. Las promesas proporcionan una mejor forma de trabajar con funciones de devolución de llamada. Las promesas son parte de ES6. De forma predeterminada, cuando crea una promesa, el estado de la promesa está pendiente.

Las promesas vienen en tres estados:

  • pendiente (estado inicial)
  • resuelto (completado con éxito)
  • rejected(failed)

new Promise()se utiliza para construir una promesa. El constructor de promesas tiene un argumento, que es una función de devolución de llamada. La función de devolución de llamada tiene dos argumentos: resolver y rechazar;

ambas son funciones internas. El código asincrónico que escriba, es decir, la llamada Ajax, la carga de imágenes, las funciones de sincronización irán a la función de devolución de llamada.

Si la tarea realizada en la función de devolución de llamada es un éxito, se llama a la función de resolución; de lo contrario, se llama a la función de rechazo con los detalles del error.

La siguiente línea de código muestra una llamada a la estructura de promesa:

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.
});

Ejemplo de promesa ES6

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

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

Salida

Promise is resolved!

ES6 - Promesas

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

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

Mando

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 las promesas, el código no cambia cuando se transpila. Necesitamos usar babel-polyfill para que funcione en navegadores más antiguos. Los detalles sobre babel-polyfills se explican en el capítulo babel - poyfill.

Generadores

La función del generador es normal function. La función tiene una función de sintaxis especial * con * para la función y la palabra clave de rendimiento que se utilizará dentro de la función. Esto está destinado a pausar o iniciar la función cuando sea necesario. Las funciones normales no se pueden detener entre una vez que comienza la ejecución. Ejecutará la función completa o se detendrá cuando encuentre la declaración de retorno. El generador funciona de manera diferente aquí, puede detener la función con la palabra clave yield e iniciarla llamando al generador nuevamente cuando sea necesario.

Ejemplo

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

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

Salida

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

ES6 - Generador

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

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

Mando

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 en JavaScript devuelve un objeto JavaScript, que tiene valor. El objeto también tiene un indicador llamado hecho, que tiene un valor verdadero / falso. Da falso si no es el final del iterador. Consideremos un ejemplo y veamos el funcionamiento del iterador en una matriz.

Ejemplo

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());

En el ejemplo anterior, hemos usado una matriz de números y hemos llamado a una función en la matriz usando Symbol.iterator como el índice.

La salida que obtenemos usando next () en la matriz es la siguiente:

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

La salida da un objeto con valor y se realiza como propiedades. Cadanext()La llamada al método da el siguiente valor de la matriz y se hace como falso. El valor de done será verdadero solo cuando los elementos de la matriz estén listos. Podemos usar esto para iterar sobre matrices. Hay más opciones disponibles comofor-of bucle que se utiliza de la siguiente manera:

Ejemplo

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

Salida

4
7
3
10

Cuando el for-of loopusa la clave, da detalles de los valores de la matriz como se muestra arriba. Comprobaremos ambas combinaciones y veremos cómo babeljs las transpila a es5.

Ejemplo

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);
}

mando

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

Salida

"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;
      }
   }
}

Hay cambios agregados for-ofbucle en es5. Pero iterator.next se deja como está. Necesitamos usarbabel-polyfillpara que funcione en navegadores antiguos. Babel-polyfill se instala junto con babel y lo mismo se puede usar desde node_modules como se muestra a continuación:

Ejemplo

<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>

Salida

Desestructurando

La propiedad de desestructuración se comporta como una expresión de JavaScript que descomprime valores de matrices, objetos.

El siguiente ejemplo explicará el funcionamiento de la sintaxis de desestructuración.

Ejemplo

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);

Salida

10
20
[30, 40, 50]
1
2

La línea de código anterior muestra cómo se asignan los valores del lado derecho de la matriz a las variables del lado izquierdo. La variable con...rem obtiene todos los valores restantes de la matriz.

También podemos asignar los valores del objeto en el lado izquierdo usando el operador condicional como se muestra a continuación:

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

Convirtamos lo mismo a ES5 usando babeljs -

mando

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);

Literales de plantilla

El literal de plantilla es un literal de cadena que permite expresiones dentro de él. Utiliza comillas inversas (``) en lugar de comillas simples o dobles. Cuando decimos expresión dentro de una cadena, significa que podemos usar variables, llamar a una función, etc.dentro de la cadena.

Ejemplo

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

Salida

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

ES6 - Literal de plantilla

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

mando

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));

Literales de objetos mejorados

En es6, las nuevas características agregadas a los objetos literales son muy buenas y útiles. Veremos algunos ejemplos de objetos literales en ES5 y ES6:

Ejemplo

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}

Si ve el código anterior, el objeto en ES5 y ES6 es diferente. En ES6, no tenemos que especificar el valor de la clave si los nombres de las variables son los mismos que los de la clave.

Veamos la compilación a ES5 usando babel.

Literal de objeto mejorado de ES6

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"

mando

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"

Propiedades predeterminadas, de descanso y propagación

En esta sección, discutiremos las propiedades predeterminadas, de descanso y de propagación.

Defecto

Con ES6, podemos usar parámetros predeterminados para los parámetros de la función de la siguiente manera:

Ejemplo

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

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

Transpilemos el código anterior a ES5 usando babel.

mando

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));

Descanso

El parámetro de descanso comienza con tres puntos (...) como se muestra en el siguiente ejemplo:

Ejemplo

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

En la función anterior, estamos pasando n número de parámetros a la función add. Para agregar todos esos parámetros si estaba en ES5, tenemos que confiar en el objeto de argumentos para obtener los detalles de los argumentos. Con ES6,rest it ayuda a definir los argumentos con tres puntos como se muestra arriba y podemos recorrerlos y obtener la suma de los números.

Note - No podemos usar argumentos adicionales cuando usamos tres puntos, es decir, resto.

Ejemplo

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

El código anterior dará error de sintaxis.

La compilación de es5 tiene el siguiente aspecto:

mando

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));

Propagar

La propiedad Spread también tiene los tres puntos como resto. A continuación se muestra un ejemplo práctico, que muestra cómo utilizar la propiedad spread.

Ejemplo

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

Veamos ahora cómo se transpila el código anterior usando babel -

mando

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 es un objeto en el que puede definir un comportamiento personalizado para operaciones como búsqueda de propiedad, asignación, enumeración, función, invocación, etc.

Sintaxis

var a = new Proxy(target, handler);

Tanto el objetivo como el controlador son objetos.

  • target es un objeto o puede ser otro elemento proxy.

  • handler será un objeto con sus propiedades como funciones que darán el comportamiento cuando sea llamado.

Intentemos comprender estas características con la ayuda de un ejemplo:

Ejemplo

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);

Hemos definido target y handler en el ejemplo anterior y lo usamos con proxy. Proxy devuelve el objeto con pares clave-valor.

Salida

Siya Kapoor
Mumbai
invalid key

Veamos ahora cómo transpilar el código anterior a ES5 usando babel -

mando

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);