
Nuevas características de ES2018 que todo desarrollador de JavaScript debería conocer

La novena edición del estándar ECMAScript, oficialmente conocida como ECMAScript 2018 (o ES2018 para abreviar), se lanzó en junio de 2018. A partir de ES2016, se lanzan nuevas versiones de las especificaciones de ECMAScript anualmente en lugar de cada varios años y agregan menos funciones que las ediciones principales. solía hacerlo. La edición más reciente del estándar continúa el ciclo de lanzamiento anual al agregar cuatro nuevas RegExp
características, propiedades de descanso/extensión, iteración asincrónica y Promise.prototype.finally
. Además, ES2018 elimina la restricción de sintaxis de las secuencias de escape de las plantillas etiquetadas.
Estos nuevos cambios se explican en las subsecciones siguientes.
Las propiedades de descanso/propagación
Una de las características más interesantes agregadas a ES2015 fue el operador diferencial. Este operador simplifica mucho la copia y combinación de matrices. En lugar de llamar al método concat()
o slice()
, puedes utilizar el ...
operador:
const arr1 = [10, 20, 30];// make a copy of arr1const copy = [...arr1];console.log(copy); // → [10, 20, 30]const arr2 = [40, 50];// merge arr2 with arr1const merge = [...arr1, ...arr2];console.log(merge); // → [10, 20, 30, 40, 50]
El operador de extensión también resulta útil en situaciones en las que se debe pasar una matriz como argumentos separados a una función. Por ejemplo:
const arr = [10, 20, 30]// equivalent to// console.log(Math.max(10, 20, 30));console.log(Math.max(...arr)); // → 30
ES2018 amplía aún más esta sintaxis al agregar propiedades de extensión a los literales de objetos. Con las propiedades de extensión se pueden copiar las propias propiedades enumerables de un objeto en un objeto nuevo. Considere el siguiente ejemplo:
const obj1 = { a: 10, b: 20};const obj2 = { ...obj1, c: 30};console.log(obj2); // → {a: 10, b: 20, c: 30}
En este código, el ...
operador se utiliza para recuperar las propiedades de obj1
y asignarlas a obj2
. Antes de ES2018, intentar hacerlo arrojaba un error. Si hay varias propiedades con el nombre, se utilizará la misma propiedad que aparezca en el último lugar:
const obj1 = { a: 10, b: 20};const obj2 = { ...obj1, a: 30};console.log(obj2); // → {a: 30, b: 20}
Las propiedades de extensión también proporcionan una nueva forma de fusionar dos o más objetos, que se puede utilizar como alternativa al Object.assign()
método:
const obj1 = {a: 10};const obj2 = {b: 20};const obj3 = {c: 30};// ES2018console.log({...obj1, ...obj2, ...obj3}); // → {a: 10, b: 20, c: 30}// ES2015console.log(Object.assign({}, obj1, obj2, obj3)); // → {a: 10, b: 20, c: 30}
Sin embargo, tenga en cuenta que las propiedades de distribución no siempre producen el mismo resultado que Object.assign()
. Considere el siguiente código:
Object.defineProperty(Object.prototype, 'a', { set(value) { console.log('set called!'); }});const obj = {a: 10};console.log({...obj}); // → {a: 10}console.log(Object.assign({}, obj)); // → set called!// → {}
En este código, el Object.assign()
método ejecuta la propiedad de establecimiento heredada. Por el contrario, las propiedades de dispersión simplemente ignoran al definidor.
Es importante recordar que las propiedades de distribución solo copian propiedades enumerables. En el siguiente ejemplo, la type
propiedad no aparecerá en el objeto copiado porque su enumerable
atributo está establecido en false
:
const car = { color: 'blue'};Object.defineProperty(car, 'type', { value: 'coupe', enumerable: false});console.log({...car}); // → {color: "blue"}
Las propiedades heredadas se ignoran incluso si son enumerables:
const car = { color: 'blue'};const car2 = Object.create(car, { type: { value: 'coupe', enumerable: true, }});console.log(car2.color); // → blueconsole.log(car2.hasOwnProperty('color')); // → falseconsole.log(car2.type); // → coupeconsole.log(car2.hasOwnProperty('type')); // → trueconsole.log({...car2}); // → {type: "coupe"}
En este código, car2
hereda la color
propiedad de car
. Debido a que las propiedades extendidas solo copian las propiedades propias de un objeto, color
no se incluyen en el valor de retorno.
Tenga en cuenta que las propiedades de propagación solo pueden realizar una copia superficial de un objeto. Si una propiedad contiene un objeto, solo se copiará la referencia al objeto:
const obj = {x: {y: 10}};const copy1 = {...obj}; const copy2 = {...obj}; console.log(copy1.x === copy2.x); // → true
La x
propiedad en copy1
se refiere al mismo objeto en la memoria al que se refiere x
en copy2
, por lo que el operador de igualdad estricta devuelve true
.
Otra característica útil agregada a ES2015 fueron los parámetros de descanso, que permitieron a los programadores de JavaScript utilizarlos ...
para representar valores como una matriz. Por ejemplo:
const arr = [10, 20, 30];const [x, ...rest] = arr;console.log(x); // → 10console.log(rest); // → [20, 30]
Aquí, el primer elemento arr
se asigna a x
y los elementos restantes se asignan a la rest
variable. Este patrón, llamado desestructuración de matrices, se volvió tan popular que el Comité Técnico de Ecma decidió agregar una funcionalidad similar a los objetos:
const obj = { a: 10, b: 20, c: 30};const {a, ...rest} = obj;console.log(a); // → 10console.log(rest); // → {b: 20, c: 30}
Este código utiliza las propiedades restantes en una tarea de desestructuración para copiar las propiedades enumerables restantes en un nuevo objeto. Tenga en cuenta que las propiedades de descanso siempre deben aparecer al final del objeto; De lo contrario, se generará un error:
const obj = { a: 10, b: 20, c: 30};const {...rest, a} = obj; // → SyntaxError: Rest element must be last element
También tenga en cuenta que el uso de varias sintaxis de descanso en un objeto provoca un error a menos que estén anidadas:
const obj = { a: 10, b: { x: 20, y: 30, z: 40 }};const {b: {x, ...rest1}, ...rest2} = obj; // no errorconst {...rest, ...rest2} = obj; // → SyntaxError: Rest element must be last element
Soporte para propiedades de descanso/propagación
cromo | Firefox | Safari | Borde |
---|---|---|---|
60 | 55 | 11.1 | No |
androidcromo | Firefox Android | Safari de iOS | Borde móvil | Internet Samsung | Vista web de Android |
---|---|---|---|---|---|
60 | 55 | 11.3 | No | 8.2 | 60 |
Nodo.js:
- 8.0.0 (requiere el
--harmony
indicador de tiempo de ejecución) - 8.3.0 (soporte total)
Iteración asincrónica
Iterar sobre una colección de datos es una parte importante de la programación. Antes de ES2015, JavaScript proporcionaba declaraciones como for
, for...in
y while
, y métodos como map()
, filter()
y forEach()
para este propósito. Para permitir a los programadores procesar los elementos de una colección uno a la vez, ES2015 introdujo la interfaz de iterador.
Un objeto es iterable si tiene una Symbol.iterator
propiedad. En ES2015, las cadenas y los objetos de colección como Set
, Map
y Array
vienen con una Symbol.iterator
propiedad y, por lo tanto, son iterables. El siguiente código da un ejemplo de cómo acceder a los elementos de un iterable a la vez:
const arr = [10, 20, 30];const iterator = arr[Symbol.iterator](); console.log(iterator.next()); // → {value: 10, done: false}console.log(iterator.next()); // → {value: 20, done: false}console.log(iterator.next()); // → {value: 30, done: false}console.log(iterator.next()); // → {value: undefined, done: true}
Symbol.iterator
es un símbolo bien conocido que especifica una función que devuelve un iterador. La forma principal de interactuar con un iterador es el next()
método. Este método devuelve un objeto con dos propiedades: value
y done
. La value
propiedad contiene el valor del siguiente elemento de la colección. La done
propiedad contiene true
o false
indica si se ha llegado al final de la colección.
De forma predeterminada, un objeto simple no es iterable, pero puede volverse iterable si se define una Symbol.iterator
propiedad en él, como en este ejemplo:
const collection = { a: 10, b: 20, c: 30, [Symbol.iterator]() { const values = Object.keys(this); let i = 0; return { next: () =gt; { return { value: this[values[i++]], done: i gt; values.length } } }; }};const iterator = collection[Symbol.iterator](); console.log(iterator.next()); // → {value: 10, done: false}console.log(iterator.next()); // → {value: 20, done: false}console.log(iterator.next()); // → {value: 30, done: false}console.log(iterator.next()); // → {value: undefined, done: true}
Este objeto es iterable porque define una Symbol.iterator
propiedad. El iterador utiliza el Object.keys()
método para obtener una matriz de nombres de propiedades del objeto y luego la asigna a la values
constante. También define una variable de contador y le da un valor inicial de 0. Cuando se ejecuta el iterador, devuelve un objeto que contiene un next()
método. Cada vez que next()
se llama al método, devuelve un {value, done}
par, que value
contiene el siguiente elemento de la colección y done
un valor booleano que indica si el iterador ha alcanzado la necesidad de la colección.
Si bien este código funciona perfectamente, es innecesariamente complicado. Afortunadamente, utilizar una función generadora puede simplificar considerablemente el proceso:
const collection = { a: 10, b: 20, c: 30, [Symbol.iterator]: function * () { for (let key in this) { yield this[key]; } }};const iterator = collection[Symbol.iterator](); console.log(iterator.next()); // → {value: 10, done: false}console.log(iterator.next()); // → {value: 20, done: false}console.log(iterator.next()); // → {value: 30, done: false}console.log(iterator.next()); // → {value: undefined, done: true}
Dentro de este generador, for...in
se utiliza un bucle para enumerar la colección y generar el valor de cada propiedad. El resultado es exactamente el mismo que el del ejemplo anterior, pero es mucho más corto.
Una desventaja de los iteradores es que no son adecuados para representar fuentes de datos asincrónicas. La solución de ES2018 para remediar esto son los iteradores asincrónicos y los iterables asincrónicos. Un iterador asincrónico se diferencia de un iterador convencional en que, en lugar de devolver un objeto simple en forma de {value, done}
, devuelve una promesa que cumple {value, done}
. Un iterable asincrónico define un Symbol.asyncIterator
método (en lugar de Symbol.iterator
) que devuelve un iterador asincrónico.
Un ejemplo debería aclarar esto:
const collection = { a: 10, b: 20, c: 30, [Symbol.asyncIterator]() { const values = Object.keys(this); let i = 0; return { next: () =gt; { return Promise.resolve({ value: this[values[i++]], done: i gt; values.length }); } }; }};const iterator = collection[Symbol.asyncIterator](); console.log(iterator.next().then(result =gt; { console.log(result); // → {value: 10, done: false}}));console.log(iterator.next().then(result =gt; { console.log(result); // → {value: 20, done: false} }));console.log(iterator.next().then(result =gt; { console.log(result); // → {value: 30, done: false} }));console.log(iterator.next().then(result =gt; { console.log(result); // → {value: undefined, done: true} }));
Tenga en cuenta que no es posible utilizar un iterador de promesas para lograr el mismo resultado. Aunque un iterador sincrónico normal puede determinar los valores de forma asincrónica, aún necesita determinar el estado de “hecho” de forma sincrónica.
Nuevamente, puedes simplificar el proceso usando una función generadora, como se muestra a continuación:
const collection = { a: 10, b: 20, c: 30, [Symbol.asyncIterator]: async function * () { for (let key in this) { yield this[key]; } }};const iterator = collection[Symbol.asyncIterator](); console.log(iterator.next().then(result =gt; { console.log(result); // → {value: 10, done: false}}));console.log(iterator.next().then(result =gt; { console.log(result); // → {value: 20, done: false} }));console.log(iterator.next().then(result =gt; { console.log(result); // → {value: 30, done: false} }));console.log(iterator.next().then(result =gt; { console.log(result); // → {value: undefined, done: true} }));
Normalmente, una función generadora devuelve un objeto generador con un next()
método. Cuando next()
se llama, devuelve un {value, done}
par cuya value
propiedad contiene el valor obtenido. Un generador asíncrono hace lo mismo excepto que devuelve una promesa que cumple {value, done}
.
Una manera fácil de iterar sobre un objeto iterable es usar la for...of
declaración, pero for...of
no funciona con iterables asíncronos ya value
que done
no se determina de forma sincrónica. Por este motivo, ES2018 aporta el for...await...of
comunicado. Veamos un ejemplo:
const collection = { a: 10, b: 20, c: 30, [Symbol.asyncIterator]: async function * () { for (let key in this) { yield this[key]; } }};(async function () { for await (const x of collection) { console.log(x); }})();// logs:// → 10// → 20// → 30
En este código, la for...await...of
declaración llama implícitamente al Symbol.asyncIterator
método en el objeto de la colección para obtener un iterador asíncrono. Cada vez que se recorre el bucle, next()
se llama al método del iterador, que devuelve una promesa. Una vez que se resuelve la promesa, la value
propiedad del objeto resultante se lee en la x
variable. El ciclo continúa hasta que la done
propiedad del objeto devuelto tenga un valor de true
.
Tenga en cuenta que la for...await...of
declaración solo es válida dentro de los generadores asincrónicos y las funciones asincrónicas. Si se viola esta regla, se generará un error SyntaxError
.
El next()
método puede devolver una promesa rechazada. Para gestionar con elegancia una promesa rechazada, puede convertir la for...await...of
declaración en una try...catch
declaración, como esta:
const collection = {
[Symbol.asyncIterator]() { return { next: () =gt; { return Promise.reject(new Error('Something went wrong.')) } }; }};(async function() { try { for await (const value of collection) {} } catch (error) { console.log('Caught: ' + error.message); }})();// logs:// → Caught: Something went wrong.
Soporte para iteradores asincrónicos
Cromo | Firefox | Safari | Borde |
---|---|---|---|
63 | 57 | 12 | No |
Android Chrome | Firefox Android | Safari en iOS | Borde móvil | internet samsung | Vista web de Android |
---|---|---|---|---|---|
63 | 57 | 12 | No | 8.2 | 63 |
Node.js:
- 8.10.0 (requiere el indicador –harmony_async_iteration)
- 10.0.0 (soporte completo)
Promesa.prototipo.finalmente
Otra interesante incorporación a ES2018 es el finally()
método. Varias bibliotecas de JavaScript habían implementado previamente un método similar, que resultó útil en muchas situaciones. Esto animó al Comité Técnico de ECMA a añadirlo finally()
a la especificación. Con este método, los programadores podrán ejecutar un bloque de código independientemente del destino de la promesa. Veamos un ejemplo sencillo:
fetch('https://www.google.com') .then((response) =gt; { console.log(response.status); }) .catch((error) =gt; { console.log(error); }) .finally(() =gt; { document.querySelector('#spinner').style.display = 'none'; });
El finally()
método resulta útil cuando es necesario realizar un poco de limpieza una vez finalizada la operación, independientemente de si tuvo éxito o no. En este código, el finally()
método simplemente oculta el control giratorio de carga después de que se obtengan y procesen los datos. En lugar de duplicar la lógica final en los métodos then()
y catch()
, el código registra una función que se ejecutará una vez que la promesa se cumpla o se rechace.
Podrías lograr el mismo resultado usando promise.then(func, func)
en lugar de promise.finally(func)
, pero tendrías que repetir el mismo código tanto en el controlador de cumplimiento como en el controlador de rechazo, o declarar una variable para él:
fetch('https://www.google.com') .then((response) =gt; { console.log(response.status); }) .catch((error) =gt; { console.log(error); }) .then(final, final);function final() { document.querySelector('#spinner').style.display = 'none';}
Al igual que con then()
y catch()
, el finally()
método siempre devuelve una promesa, por lo que puedes encadenar más métodos. Normalmente, se desea utilizar finally()
como última cadena, pero en determinadas situaciones, como cuando se realiza una solicitud HTTP, es una buena práctica encadenar otra catch()
para solucionar los errores que puedan ocurrir en el archivo finally()
.
Soporte para Promise.prototype.finally
Cromo | Firefox | Safari | Borde |
---|---|---|---|
63 | 58 | 11.1 | 18 |
Android Chrome | Firefox Android | Safari en iOS | Borde móvil | internet samsung | Vista web de Android |
---|---|---|---|---|---|
63 | 58 | 11.1 | No | 8.2 | 63 |
Node.js:
10.0.0 (soporte completo)
Nuevas funciones de RegExp
ES2018 agrega cuatro características nuevas al RegExp
objeto, lo que mejora aún más las capacidades de procesamiento de cadenas de JavaScript. Estas características son las siguientes:
- bandera s (puntoTodo)
- Grupos de captura con nombre
- Afirmaciones de tipo “mirar hacia atrás”
- La propiedad Unicode se escapa
Bandera s (puntoTodo)
El punto ( .
) es un carácter especial en un patrón de expresión regular que coincide con cualquier carácter excepto los de salto de línea, como el avance de línea ( n
) o el retorno de carro ( r
). Una solución alternativa para hacer coincidir todos los caracteres, incluidos los saltos de línea, es utilizar una clase de caracteres con dos abreviaturas opuestas, como [dD]
. Esta clase de caracteres le dice al motor de expresiones regulares que busque un carácter que sea un dígito ( d
) o no un dígito ( D
). Como resultado, coincide con cualquier carácter:
console.log(/one[dD]two/.test('onentwo')); // → true
ES2018 introduce un modo en el que se puede utilizar el punto para lograr el mismo resultado. Este modo se puede activar por expresión regular usando la s
bandera:
console.log(/one.two/.test('onentwo')); // → falseconsole.log(/one.two/s.test('onentwo')); // → true
La ventaja de usar una bandera para optar por el nuevo comportamiento es la compatibilidad con versiones anteriores. Por lo tanto, los patrones de expresiones regulares existentes que usan el carácter de punto no se ven afectados.
Grupos de captura con nombre
En algunos patrones de expresiones regulares, el uso de un número para hacer referencia a un grupo de captura puede resultar confuso. Por ejemplo, tomemos la expresión regular /(d{4})-(d{2})-(d{2})/
que coincida con una fecha. Debido a que la notación de fecha en inglés americano es diferente a la del inglés británico, es difícil saber a qué grupo se refiere al día y a qué grupo se refiere al mes:
const re = /(d{4})-(d{2})-(d{2})/;const match= re.exec('2019-01-10');console.log(match[0]); // → 2019-01-10console.log(match[1]); // → 2019console.log(match[2]); // → 01console.log(match[3]); // → 10
ES2018 introduce grupos de captura con nombre que utilizan la (?name...)/name
sintaxis. Entonces, el patrón para coincidir con una fecha se puede escribir de una manera menos ambigua:
const re = /(?yeard{4})-(?monthd{2})-(?dayd{2})/;const match = re.exec('2019-01-10');console.log(match.groups); // → {year: "2019", month: "01", day: "10"}console.log(match.groups.year); // → 2019console.log(match.groups.month); // → 01console.log(match.groups.day); // → 10/day/month/year
Puede recuperar un grupo de captura con nombre más adelante en el patrón utilizando la kname/name
sintaxis. Por ejemplo, para encontrar palabras duplicadas consecutivas en una oración, puedes usar /b(?dupw+)s+kdupb//dup/dup
:
const re = /b(?dupw+)s+kdupb/;const match = re.exec('Get that that cat off the table!'); console.log(match.index); // → 4console.log(match[0]); // → that that/dup/dup
Para insertar un grupo de captura con nombre en la cadena de reemplazo del replace()
método, será necesario utilizar la $name/name
construcción. Por ejemplo:
const str = 'red amp; blue';console.log(str.replace(/(red) amp; (blue)/, '$2 amp; $1')); // → blue amp; redconsole.log(str.replace(/(?redred) amp; (?blueblue)/, '$blue amp; $red')); // → blue amp; red/red/blue/blue/red
Afirmaciones de tipo lookbehind
ES2018 incorpora aserciones de lookbehind a JavaScript, que han estado disponibles en otras implementaciones de expresiones regulares durante años. Anteriormente, JavaScript solo admitía aserciones de anticipación. Una aserción de lookbehind se denota por (?lt;=...)
y le permite hacer coincidir un patrón en función de la subcadena que precede al patrón. Por ejemplo, si desea hacer coincidir el precio de un producto en dólares, libras o euros sin capturar el símbolo de la moneda, puede utilizar /(?lt;=$|£|€)d+(.d*)?/
:
const re = /(?lt;=$|£|€)d+(.d*)?/;console.log(re.exec('199')); // → nullconsole.log(re.exec('$199')); // → ["199", undefined, index: 1, input: "$199", groups: undefined]console.log(re.exec('€50')); // → ["50", undefined, index: 1, input: "€50", groups: undefined]
También hay una versión negativa de mirar hacia atrás, que se denota por(?. A negative lookbehind allows you to match a pattern only if it is not preceded by the pattern within the lookbehind. For example, the pattern code/(? matches the word available if it does not have a "un" prefix:
code
pre rel="JavaScript"codeconst re = /(?h4Unicode Property Escapes/h4ES2018 provides a new type of escape sequence known as Unicode property escape, which provides support for full Unicode in regular expressions. Suppose you want to match the Unicode character ㉛ in a string. Although ㉛ is considered a number, you can’t match it with the coded
Clase de caracteres abreviados, ya que solo admite caracteres ASCII [0-9]. Por otro lado, los escapes de propiedades Unicode se pueden usar para hacer coincidir cualquier número decimal en Unicode:
const str = '㉛';console.log(/d/u.test(str)); // → falseconsole.log(/p{Number}/u.test(str)); // → true
De manera similar, si desea hacer coincidir cualquier código UnicodepalabraCaracteres alfabéticos que puedes utilizar p{Alphabetic}
:
const str = 'ض';console.log(/p{Alphabetic}/u.test(str)); // → true// the w shorthand cannot match ض console.log(/w/u.test(str)); // → false
También existe una versión negada de p{...}
, que se denota por P{...}
:
console.log(/P{Number}/u.test('㉛')); // → falseconsole.log(/P{Number}/u.test('ض')); // → trueconsole.log(/P{Alphabetic}/u.test('㉛')); // → trueconsole.log(/P{Alphabetic}/u.test('ض')); // → false
Además de Alfabético y Número, hay varias propiedades más que se pueden utilizar en los escapes de propiedades Unicode. Puede encontrar una lista de propiedades Unicode admitidas en la propuesta de especificación actual.
Compatibilidad con nuevas funciones RegExp
Cromo | Firefox | Safari | Borde | |
---|---|---|---|---|
Bandera s (puntoTodo) | 62 | No | 11.1 | No |
Grupos de captura con nombre | 64 | No | 11.1 | No |
Afirmaciones de tipo lookbehind | 62 | No | No | No |
Propiedades de escape Unicode | 64 | No | 11.1 | No |
Cromo (Android) | Firefox (Android) | Safari en iOS | Borde móvil | internet samsung | Vista web de Android | |
---|---|---|---|---|---|---|
Bandera s (puntoTodo) | 62 | No | 11.3 | No | 8.2 | 62 |
Grupos de captura con nombre | 64 | No | 11.3 | No | No | 64 |
Afirmaciones de tipo lookbehind | 62 | No | No | No | 8.2 | 62 |
Propiedades de escape Unicode | 64 | No | 11.3 | No | No | 64 |
Node.js:
- 8.3.0 (requiere el indicador de tiempo de ejecución –harmony)
- 8.10.0 (soporte para el indicador s (dotAll) y aserciones de búsqueda hacia atrás)
- 10.0.0 (soporte completo)
Revisión literal de plantilla
Cuando una expresión precede inmediatamente a una plantilla literal, se denomina plantilla literal etiquetada. Una plantilla etiquetada resulta útil cuando se desea analizar una plantilla literal con una función. Considere el siguiente ejemplo:
function fn(string, substitute) { if(substitute === 'ES6') { substitute = 'ES2015' } return substitute + string[1];}const version = 'ES6';const result = fn`${version} was a major update`;console.log(result); // → ES2015 was a major update
En este código, se invoca una expresión de etiqueta (que es una función normal) y se le pasa el literal de plantilla. La función simplemente modifica la parte dinámica de la cadena y la devuelve.
Antes de ES2018, los literales de plantilla etiquetados tenían restricciones sintácticas relacionadas con secuencias de escape. Una barra invertida seguida de una determinada secuencia de caracteres se trataba como caracteres especiales: a x
se interpretaba como un escape hexadecimal, a u
se interpretaba como un escape Unicode y seguido de un dígito se interpretaba como un escape octal. Como resultado, el intérprete consideró cadenas como
"C:xxxuuu"
o "ubuntu"
secuencias de escape no válidas y arrojaron un archivo SyntaxError
.
ES2018 elimina estas restricciones de las plantillas etiquetadas y, en lugar de generar un error, representa secuencias de escape no válidas como undefined
:
function fn(string, substitute) { console.log(substitute); // → escape sequences: console.log(string[1]); // → undefined}const str = 'escape sequences:';const result = fn`${str} ubuntu C:xxxuuu`;
Tenga en cuenta que el uso de secuencias de escape ilegales en un literal de plantilla regular aún provoca un error:
const result = `ubuntu`;// → SyntaxError: Invalid Unicode escape sequence
Soporte para revisión literal de plantilla
Cromo | Firefox | Safari | Borde |
---|---|---|---|
62 | 56 | 11 | No |
Android Chrome | Firefox Android | Safari en iOS | Borde móvil | internet samsung | Vista web de Android |
---|---|---|---|---|---|
62 | 56 | 11 | No | 8.2 | 62 |
Node.js:
- 8.3.0 (requiere el indicador de tiempo de ejecución –harmony)
- 8.10.0 (soporte total)
terminando
Hemos analizado en profundidad varias características clave introducidas en ES2018, incluyendo la iteración asincrónica, las propiedades rest/spread Promise.prototype.finally()
y las incorporaciones al RegExp
objeto. Aunque algunos proveedores de navegadores aún no han implementado por completo algunas de estas características, todavía se pueden usar hoy en día gracias a los transpiladores de JavaScript como Babel.
ECMAScript evoluciona rápidamente y cada cierto tiempo se incorporan nuevas funciones, así que consulta la lista de propuestas finalizadas para conocer todas las novedades. ¿Hay alguna función nueva que te entusiasme especialmente? ¡Compártela en los comentarios!
Deja una respuesta