template concatenar javascript ecmascript-6

javascript - concatenar - ¿Por qué la sintaxis extendida convierte mi cadena en una matriz?



template string javascript (5)

Debido a que una cadena en javascript es tratada como una matriz de caracteres.

Por ejemplo, cuando haces un bucle por cada cadena (digamos hello ), con lodash:

_.forEach(''hello'', function(i) { console.log(i) })

da salida:

h e l l o

Las funciones como slice() también funcionan tanto en cadenas como en matrices.

¿Por qué la sintaxis extendida convierte mi cadena en una matriz?

var v = ''hello''; var [, ...w] = v; // ["e", "l", "l", "o"]

¿Por qué w no es una cuerda?


En ES2015, la sintaxis de propagación actúa específicamente contra la propiedad String @@iterator interna. Cualquier objeto puede ser iterado de esta manera asignando su propio iterator o generador / function* a la propiedad obj[Symbol.iterator] .

Por ejemplo, podría cambiar el comportamiento predeterminado de su nueva matriz ...

const a = [...''hello'']; a[Symbol.iterator] = function* (){ for(let i=0; i<this.length; ++i) yield `${this[i]}!`; }; console.log([...a]);

También puedes cambiar tu iterador de cadenas, pero deberías crear explícitamente un objeto String .


Hay dos cosas que suceden aquí.

Primero, estás usando la desestructuración de matrices. Esto le permite tomar un iterable y asignar valores a variables individuales.

En segundo lugar, está utilizando un parámetro de descanso. Esto convierte cualquier salida restante de lo iterable en una matriz.

Entonces su cadena ''hello'' se itera en sus caracteres individuales, la primera se ignora (porque omitió el destino), luego los caracteres restantes se convierten en una matriz y se asignan a w .


La sintaxis de propagación (en realidad un puntuador como lo señala RobG ) permite que los resultados se distribuyan en bits más pequeños. Dado que las cadenas son iterables (son matrices de caracteres internamente, más específicamente secuencias ordenadas de enteros que representan caracteres), se pueden distribuir en caracteres individuales.

A continuación, la desestructuración se realiza en la matriz para desempaquetar y agrupar los valores de propagación. Ya que omite el primer elemento de la matriz de caracteres con , y no asigna una referencia, se pierde, y el resto del objeto iterable se guarda en w , se extiende en sus partes individuales, caracteres individuales de la matriz de caracteres.

La semántica específica de esta operación se define en la Especificación ECMAScript 2015 por el ArrayAssignmentPattern: producción de [Elision opt AssignmentRestElement] :

12.14.5.2 Semántica de tiempo de ejecución: DesestructuraciónAsignaciónEvaluación

con valor de parámetro

[...]

ArrayAssignmentPattern: [Elision opt AssignmentRestElement]

  1. Deje que iterador sea GetIterator ( valor ).
  2. ReturnIfAbrupt ( iterador ).
  3. Deje que iteratorRecord sea ​​Registro {[[iterador]]: iterador , [[hecho]]: falso }.
  4. Si Elision está presente, entonces
    a. Deje que el estado sea ​​el resultado de la ejecución de IteratorDestructuringAssignmentEvaluation de Elision con iteratorRecord como argumento.
    segundo. Si el estado es una finalización abrupta , entonces
    yo. Si iteratorRecord . [[Hecho]] es falso , devuelva IteratorClose ( iterador , estado ).
    ii. Retorno completado ( estado ).
  5. Deje que el resultado sea ​​el resultado de realizar IteratorDestructuringAssignmentEvaluation of AssignmentRestElement con iteratorRecord como argumento.
  6. Si iteratorRecord . [[Hecho]] es falso , devuelve IteratorClose ( iterador , resultado ).
  7. Resultado de retorno.

Aquí, Elision se refiere a un elemento omitido cuando se propaga con una o más comas ( , ), comparables a las sílabas omitidas como sugiere su nombre, y AssignmentRestElement se refiere al objetivo que recibirá los valores de propagación y desestructuración, w en este caso.

Lo que esto hace es obtener primero el iterador del objeto, del método interno @@iterator y los pasos a través de ese iterador, omitiendo sin embargo muchos elementos indicados por el ancho de elision por la producción de Elision en IteratorDestructuringAssignmentEvaluation . Una vez hecho esto, pasará por el iterador de la producción AssignmentRestElement y asignará una nueva matriz con todos los valores de dispersión, eso es lo que w es. Recibe la matriz de un solo carácter extendida, desempaquetada para excluir el primer carácter.

El método @@iterator en el que se obtiene la iteración es un símbolo conocido y cambiarlo por un objeto puede cambiar la forma en que se itera, como en la respuesta del Emisario . Específicamente, la implementación predeterminada del método @@iterator para String es la siguiente:

21.1.3.27 String.prototype [@@ iterator] ()

Cuando se llama al método @@ iterator, devuelve un objeto 25.1.1.2 ( 25.1.1.2 ) que itera sobre los puntos de código de un valor de String, devolviendo cada punto de código como un valor de String.

Por lo tanto, el iterador permite la iteración a través de puntos de código únicos , o caracteres de una cadena, y en consecuencia, la difusión de la cadena dará como resultado una matriz de sus caracteres.


La sintaxis de propagación solo se puede aplicar a objetos iterables. Dado que la cadena es iterable, el operador de difusión funciona bien y divide su matriz de caracteres (cadena) en caracteres de caracteres.

Puede verificarlo con la siguiente muestra que demuestra que la cadena es iterable de forma predeterminada.

var s = ''test''; for (k in s) { console.log(k); }

Y la especificación ECMAScript6 incluso mencionó sobre este caso específico de String.

Operador de propagación

Distribución de elementos de una colección iterable (como una matriz or even a string ) en elementos literales y parámetros de función individuales.

http://es6-features.org/#SpreadOperator

var str = "foo"; var chars = [ ...str ]; // [ "f", "o", "o" ]

Y vale la pena mencionar que este es un caso específico y solo ocurre cuando se utiliza un operador directo de cadena con propagación. Cuando se asigna una cadena única dentro de una matriz, toda la matriz se tratará como el objeto iterable y no como la cadena interna.

var str = [ "hello" ,2 ]; var other = [ ...str ]; // [ "hello" ,2 ]

Sé que el ejemplo anterior no tiene mucho sentido, pero solo para transmitir el hecho de que el String será tratado de manera diferente en este caso.