1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
|
---
title: Plantillas literales (plantillas de cadenas)
slug: Web/JavaScript/Reference/Template_literals
tags:
- ECMAScript 2015
- Experimental
- Expérimental(2)
- JavaScript
translation_of: Web/JavaScript/Reference/Template_literals
original_slug: Web/JavaScript/Referencia/template_strings
---
<div>{{JsSidebar("More")}}</div>
<p>Las plantillas literales son cadenas literales que habilitan el uso de expresiones incrustadas. Con ellas, es posible utilizar cadenas de caracteres de más de una línea, y funcionalidades de interpolación de cadenas de caracteres.</p>
<p>En ediciones anteriores de la especificación ES2015, solían llamarse "plantillas de cadenas de caracteres".</p>
<h2 id="Syntax" name="Syntax">Sintaxis</h2>
<pre class="syntaxbox notranslate">`texto de cadena de caracteres`
`línea 1 de la cadena de caracteres
línea 2 de la cadena de caracteres`
`texto de cadena de caracteres ${expresión} texto adicional`
<em>etiqueta</em>`texto de cadena de caracteres ${expresión} texto adicional`
</pre>
<h2 id="Description" name="Description">Descripción</h2>
<p>Las plantillas literales se delimitan con el caracter de comillas o tildes invertidas (` `) (<a href="http://en.wikipedia.org/wiki/Grave_accent">grave accent</a>), en lugar de las comillas sencillas o dobles.</p>
<p>Las plantillas de cadena de caracteres pueden contener marcadores, identificados por el signo de dólar y envueltos en llaves (<code>${expresión}</code>). Las expresiones contenidas en los marcadores, junto con el texto entre ellas, son enviados como argumentos a una función.</p>
<p>La función por defecto sencillamente concatena las partes para formar una única cadena de caracteres. Si hay una expresión antes de la plantilla literal (aquí indicada mediante <em><code>etiqueta</code></em>), se le conoce como "plantilla etiquetada". En este caso, la expresión de etiqueta (típicamente una función) es llamada con la plantilla literal como parámetro, que luego puede ser manipulada antes de ser devuelta.</p>
<p>En caso de querer escapar una comilla o tilde invertida en una plantilla literal, se debe poner una barra invertida (<code>\</code>) antes de la comilla o tilde invertida.</p>
<pre class="brush: js line-numbers language-js notranslate"><code class="language-js"><span class="template-string token"><span class="string token">`\``</span></span> <span class="operator token">===</span> <span class="string token">'`'</span> <span class="comment token">// --> true (cierto)</span></code></pre>
<h3 id="Cadenas_de_más_de_una_línea">Cadenas de más de una línea</h3>
<p>Los caracteres de fin de línea encontrados forman parte de la plantilla literal.</p>
<p>Utilizando cadenas de caracteres normales, sería necesario utilizar la siguiente sintaxes para producir cadenas de más de una línea:</p>
<pre class="brush: js notranslate">console.log('línea 1 de cadena de texto\n' +
'\línea 2 de cadena de texto');
// "línea 1 de cadena de texto
// línea 2 de cadena de texto"
</pre>
<p>Utilizando plantillas literales, se puede obtener el mismo resultado de la siguiente forma:</p>
<pre class="brush: js notranslate">console.log(`línea 1 de la cadena de texto
línea 2 de la cadena de texto`);
// "línea 1 de la cadena de texto
// línea 2 de la cadena de texto"</pre>
<h3 id="Interpolación_de_expresiones">Interpolación de expresiones</h3>
<p>Para insertar expresiones dentro de cadenas de caracteres normales, se utilizaría la siguiente sintaxis:</p>
<pre class="brush: js notranslate">let a = 5;
let b = 10;
console.log('Quince es ' + (a + b) + ' y\nno ' + (2 * a + b) + '.');
// "Quince es 15 y
// no 20."</pre>
<p>Ahora, con las plantillas literales, se pueden utilizar sus nuevas capacidades (es decir, insertar expresiones con <code>${ }</code> e incluir caracteres de fin de linea literales dentro de la cadena) para simplificar la sintaxis:</p>
<pre class="brush: js notranslate">let a = 5;
let b = 10;
console.log(`Quince es ${a + b} y
no ${2 * a + b}.`);
// "Quince es 15 y
// no 20."</pre>
<h3 id="Anidamiento_de_plantillas">Anidamiento de plantillas</h3>
<p>En ciertos casos, anidar una plantilla es la forma más fácil, e incluso más legible, de tener cadenas configurables. Dentro de una plantilla con tildes invertidas, es sencillo permitir tildes invertidas interiores simplemente usándolas dentro de un marcador de posición <code>${ }</code> dentro de la plantilla.</p>
<p>Por ejemplo, si la condición a es <code>true</code> (cierta): entonces <code>return</code> (devuelva) este literal con plantilla.</p>
<p>En ES5:</p>
<pre class="brush: js notranslate"><code class="language-js">let classes <span class="operator token">=</span> <span class="string token">'header'</span>
classes <span class="operator token">+</span><span class="operator token">=</span> <span class="punctuation token">(</span><span class="function token">isLargeScreen</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="operator token">?</span>
<span class="string token">''</span> <span class="punctuation token">:</span> item<span class="punctuation token">.</span>isCollapsed <span class="operator token">?</span>
<span class="string token">' icon-expander'</span> <span class="punctuation token">:</span> <span class="string token">' icon-collapser'</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
<p>En ES2015 con plantillas literales y sin anidamiento:</p>
<pre class="brush: js notranslate"><code>const classes = `header ${ isLargeScreen() ? '' :
(item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;</code></pre>
<p>En ES5 con plantillas literales anidadas:</p>
<pre class="brush: js notranslate"><code>const classes = `header ${ isLargeScreen() ? '' :
`icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;</code></pre>
<h3 id="Plantillas_etiquetadas">Plantillas etiquetadas</h3>
<p>Una forma más avanzada de plantillas literales son las plantillas <em>etiquetadas</em>.</p>
<p>Con ellas es posible modificar la salida de las plantillas utilizando una función. El primer argumento contiene un array con una o más cadenas de caracteres. El segundo y subsiguientes argumentos se asocian con las expresiones de la plantilla.</p>
<p>La función de etiqueta puede ejecutar cualesquiera operaciones deseadas con estos argumentos, y luego devolver la cadena manipulada. (También puede devolver algo totalmente distinto, como se muestra en uno de los siguientes ejemplos.)</p>
<p>El nombre de la función utilizada con la etiqueta no es nada especial, se puede utilizar cualquier nombre de función en su lugar.</p>
<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">let persona <span class="operator token">=</span> <span class="string token">'Mike'</span><span class="punctuation token">;</span>
let edad <span class="operator token">=</span> <span class="number token">28</span><span class="punctuation token">;</span>
<span class="keyword token">function</span> <span class="function token">myTag</span><span class="punctuation token">(</span>strings<span class="punctuation token">,</span> expPersona<span class="punctuation token">,</span> expEdad<span class="punctuation token">)</span>
<span class="punctuation token">{</span>
let str0 <span class="operator token">=</span> strings<span class="punctuation token">[</span><span class="number token">0</span><span class="punctuation token">]</span><span class="punctuation token">;</span> <span class="comment token">// "Ese "</span>
let str1 <span class="operator token">=</span> strings<span class="punctuation token">[</span><span class="number token">1</span><span class="punctuation token">]</span><span class="punctuation token">;</span> <span class="comment token">// " es un "</span>
<span class="comment token">// Tecnicamente, hay una cadena de
// caracteres después de la expresión
// final (en nuestro ejemplo) pero
// está vacia (""), asi que se ignora.</span>
<span class="comment token">// let str2 = strings[2];</span>
let strEdad<span class="punctuation token">;</span>
<span class="keyword token">if</span> <span class="punctuation token">(expEdad</span> <span class="operator token">></span> <span class="number token">99</span><span class="punctuation token">)</span>
<span class="punctuation token"> {</span>
strEdad <span class="operator token">=</span> <span class="string token">'viejo'</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="keyword token">else</span>
<span class="punctuation token">{</span>
strEdad <span class="operator token">=</span> <span class="string token">'joven'</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="comment token">// Podemos incluso retornar una cadena de
// caracteres utilizando una plantilla literal.</span>
<span class="keyword token">return</span> <span class="template-string token"><span class="string token">`</span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>str0<span class="interpolation-punctuation punctuation token">}</span></span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${expPersona</span><span class="interpolation-punctuation punctuation token">}</span></span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>str1<span class="interpolation-punctuation punctuation token">}</span></span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>strEdad<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="keyword token">var</span> salida <span class="operator token">=</span> myTag<span class="template-string token"><span class="string token">`Ese </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span> persona <span class="interpolation-punctuation punctuation token">}</span></span><span class="string token"> es un </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span> edad <span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">;</span>
console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>salida<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="comment token">// Ese Mike es un joven</span></code>
</pre>
<p>Las funciones de etiqueta incluso pueden devolver valores que no sean cadenas de caracteres:</p>
<pre class="brush: js notranslate">function plantilla(cadenas, ...claves) {
return (function(...valores) {
let diccio = valores[valores.length - 1] || {};
let resultado = [cadenas[0]];
claves.forEach(function(clave, i) {
let valor = Number.isInteger(clave) ? valores[clave] : diccio[clave];
resultado.push(valor, cadenas[i + 1]);
});
return resultado.join('');
});
}
let t1Closure = plantilla`¡${0}${1}${2}${2}${3}!`;
//let t1Closure = plantilla(["¡","","","","","","!"],0,1,2,3);
t1Closure('H', 'U', 'R', 'A'); // "¡HURRA!"
let t2Closure = plantilla`${0} ${'foo'}!`;
//let t2Closure = plantilla(["¡",""," ","!"],0,"foo");
t2Closure('Hola', {foo: 'Mundo'}); // "¡Hola Mundo!"
let t3Closure = plantilla`Me llamo ${'nombre'}. Tengo casi ${'edad'} años.`;
//let t3Closure = plantilla(["Me llamo ", ". Tengo casi ", " años."], "nombre", "edad");
t3Closure('foo', {nombre: 'MDN', edad: 30}); //"Me llamo MDN. Tengo casi 30 años."
t3Closure({nombre: 'MDN', edad: 30}); //"Me llamo MDN. Tengo casi 30 años."</pre>
<h3 id="Cadenas_en_crudo_raw">Cadenas en crudo (<em>raw</em>)</h3>
<p>La propiedad especial <code>raw</code>, disponible en el primer argumento de la función de etiqueta, permite acceso a las cadenas de caracteres tal como fueron ingresadas, sin procesar <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Grammar_and_types#Literales_String">secuencias de escape</a>.</p>
<pre class="brush: js notranslate">function etiqueta(cadenas) {
console.log(cadenas.raw[0]);
}
etiqueta`texto de cadena de caracteres 1 \n texto de cadena de caracteres 2`;
// muestra "texto de cadena de caracteres 1 \n texto de cadena de caracteres 2" ,
// incluyendo los caracteres '\' y 'n'</pre>
<p>Adicionalmente, el método {{jsxref("String.raw()")}} permite crear cadenas de caracteres en crudo tal como serían generadas por la función por defecto de plantilla, concatenando sus partes.</p>
<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">let cadena <span class="operator token">=</span> String<span class="punctuation token">.</span>raw<span class="template-string token"><span class="string token">`¡Hola\n</span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span><span class="number token">2</span><span class="operator token">+</span><span class="number token">3</span><span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">!`</span></span><span class="punctuation token">;</span>
<span class="comment token">// "¡Hola\n5!"</span>
cadena<span class="punctuation token">.</span>length<span class="punctuation token">;</span>
<span class="comment token">// 9
</span>Array.from(cadena).join(',');
// "</code>¡,<code class="language-js">H,o,l,a,\,n,5,!"</code>
</pre>
<h3 id="Plantillas_etiquetadas_y_secuencias_de_escape">Plantillas etiquetadas y secuencias de escape</h3>
<h4 id="Comportamiento_en_ES2016">Comportamiento en ES2016</h4>
<p>Comenzando con ECMAScript 2016, las plantillas etiquetadas se comportan de acuerdo con las normas de las siguientes secuencias de escape:</p>
<ul>
<li>Secuencias de escape de formato Unicode comenzando con "<code>\u</code>", como <code>\u00A9</code></li>
<li>Secuencias de escape de formato Unicode de punto de código, indicadas con "<code>\u{}</code>", como <code>\u{2F804}</code></li>
<li>Secuencias de escape de numeros hexadecimales comenzando con "<code>\x</code>", como <code>\xA9</code></li>
<li>Secuencias de escape de octales literales comenzando con "<code>\0o</code>" seguidas de uno o más dígitos, como <code>\0o251</code></li>
</ul>
<p>Esto significa que una plantilla etiquetada como la siguiente podría causar problemas, dado que, de acuerdo con la gramática de ECMAScript, un analizador buscará secuencias de escape de formato Unicode válidas pero encontrará sintaxis equivocado:</p>
<pre class="brush: js notranslate">latex`\unicode`
// En ECMAScript 2016 y versiones anteriores, lanza
// SyntaxError: malformed Unicode character escape sequence</pre>
<h3 id="Revision_de_secuencias_de_escape_no_permitidas_en_ES2018">Revision de secuencias de escape no permitidas en ES2018</h3>
<p>Las plantillas etiquetadas deberías permitir la inserción de lenguages (como los <a href="https://en.wikipedia.org/wiki/Domain-specific_language">DSL</a>, o <a href="https://en.wikipedia.org/wiki/LaTeX">LaTeX</a>), en donde otras secuencias de escape se ven comúnmente. La propuesta para ECMAScript <a href="https://tc39.es/proposal-template-literal-revision/">Template Literal Revision</a> (Revisión de Plantilla Literal) (Cuarta Etapa, en camino a ser integrada al estándar de ECMAScript 2018) elimina la restricción de las secuencias de escape en ECMAScript para las plantillas etiquetadas.</p>
<p>Aún así, las secuencias de escape no permitidas deben ser representadas en la representación "cocinada" de la cadena. Aparecerán como elementos <a href="https://developer.mozilla.org/es/docs/Glossary/undefined">no definidos</a> en el array llamado "cocinado" en el siguiente ejemplo.</p>
<pre class="brush: js notranslate">function latex(str) {
return { "cocinado": str[0], "en crudo": str.raw[0] }
}
latex`\unicode`
// { cocinado: undefined, en crudo: "\\unicode" }</pre>
<p>Cabe destacar que la restricción para secuencias de escape solo ha sido eliminada para plantillas <em>etiquetadas</em>. Aún permanece para plantillas literales sin etiqueta:</p>
<pre class="brush: js example-bad notranslate">let bad = `bad escape sequence: \unicode`;</pre>
<h2 id="Especificaciones">Especificaciones</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Especificación</th>
<th scope="col">Status</th>
<th scope="col">Comentarios</th>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-template-literals', 'Template Literals')}}<br>
{{SpecName('ES6', '#sec-tagged-templates', 'Tagged Templates')}}</td>
<td>{{Spec2('ES6')}}</td>
<td>Definición inicial.</td>
</tr>
</tbody>
</table>
<h2 id="Compatibilidad_de_navegadores">Compatibilidad de navegadores</h2>
<div>{{CompatibilityTable}}</div>
<div id="compat-desktop">
<table class="compat-table">
<tbody>
<tr>
<th>Funcionalidad</th>
<th>Chrome</th>
<th>Firefox (Gecko)</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari</th>
</tr>
<tr>
<td>Soporte básico</td>
<td>{{CompatChrome(41)}}</td>
<td>{{CompatGeckoDesktop("34")}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatOpera(29)}}</td>
<td>{{CompatSafari(9.1)}}</td>
</tr>
</tbody>
</table>
</div>
<div id="compat-mobile">
<table class="compat-table">
<tbody>
<tr>
<th>Funcionalidad</th>
<th>Android</th>
<th>Chrome for Android</th>
<th>Firefox Mobile (Gecko)</th>
<th>IE Mobile</th>
<th>Opera Mobile</th>
<th>Safari Mobile</th>
</tr>
<tr>
<td><span style="font-size: 12px; line-height: 18px;">Soporte básico</span></td>
<td>{{CompatAndroid(67)}}</td>
<td>
<p class="p1">{{CompatChrome(71)}}</p>
</td>
<td>{{CompatGeckoMobile("63")}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatOpera(46)}}</td>
<td>{{CompatSafari(9)}}</td>
</tr>
</tbody>
</table>
</div>
<h2 id="See_also" name="See_also">Ver también</h2>
<ul>
<li>{{jsxref("String")}}</li>
<li>{{jsxref("String.raw()")}}</li>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Lexical_grammar">Lexical grammar</a></li>
<li><a href="https://gist.github.com/WebReflection/8f227532143e63649804">Template-like strings in ES3 compatible syntax</a></li>
</ul>
|