Traducción en curso
Todos los lenguajes de programación contienen estructuras de datos, pero estas pueden diferir de un lenguajr a otro. Este artículo intenta listar las estructuras de datos incluídas en JavaScript y qué propiedades tienen; estas pueden ser usadas para construír otras estructuras de datos. Cuando sea posible, se ilustrará con comparaciones con otros lenguajes.
Tipos dinámicos
JavaScript es un lenguaje de tipado débil o dinámico. Esto significa que no es necesario declarar el tipo de variable antes de usarla. El tipo será determinado automáticamente cuando el programa comience a ser procesado. Esto también significa que puedes tener la misma variable con diferentes tipos:
var foo = 42; // foo es ahora un Number var foo = "bar"; // foo es ahora un String var foo = true; // foo es ahora un Boolean
Tipos de datos
La última definición del estandard ECMAScript define siete tipos de datos:
- Seis tipos de datos que son primitives:
Valores primitivos
Todos los tipos excepto los objetos definen valores inmutables (valores que no pueden ser cambiados). Por ejemplo y a diferencia de C, los Strings son inmutables. Hacemos referencia a valores de esos tipos como "valores primitivos".
Tipo Boolean
Boolean representa una entidad lógica y puede tener dos valores: true
, y false
.
Tipo Null
El tipo Null tiene exactamente un valor: null
. Consultar null
y Null para más detalles.
Tipo Undefined
Una variable a la cual no se le haya asignado valor tiene entonces el valor undefined
. Consultar undefined
y Undefined para más detalles.
Tipo Number
De acuerdo al standard ECMAScript, sólo existe un tipo numérico: el valor de doble precisión de 64-bits IEEE 754 (un número entre -(253 -1) y 253 -1). No existe un tipo específico para los números enteros. Adicionalmente a ser capaz de representar números de coma flotante, el tipo número tiene tres valores simbólicos: +Infinity
, -Infinity
, and NaN
(Not A Number o No Es Un Número).
Para chequear valores mayores o menores que +/-Infinity
, puedes usar las constantes Number.MAX_VALUE
o Number.MIN_VALUE
y comenzando con ECMAScript 6 también es posible chequear si un número está en el rango de coma flotante de doble precisión usando Number.isSafeInteger()
así como Number.MAX_SAFE_INTEGER
y Number.MIN_SAFE_INTEGER
. Fuera de este rango los números en javascript ya no son seguros de manipular.
El tipo número sólo tiene un valor entero que cuenta con dos representaciones: 0 es representado como -0 y +0. ("0" es un alias +0). Esto casi no tiene ningún impacto. Por ejemplo +0 === -0
es true
. Sin embargo, es posible notar esto cuando se divide por cero:
> 42 / +0 Infinity > 42 / -0 -Infinity
A pesar de que un número generalmente sólo representa su valor, JavaScript cuenta con operadores binarios. Estos pueden ser usados para representar varios valores Boolean en un mismo número usando máscaras de bits. Esto usualmente es considerado una mála práctica , sin embargo, JavaScript no ofrece maneras de representar un conjunto de valores Booleans (como un arreglo de Booleans o un objeto con valores Boolean asignados a sus propiedades). Usar máscaras de bits también tiende a volver el código más difícil de leer, entender y mantener. Puede ser necesario usar tales técnicas en ambientes muy restringidos, como cuando se intenta lidiar con la limitación de almacenamiento local o en casos extremos cuando cada bit que se transmite por la red cuenta. Esta técnica solo debería ser considerada como un último recurso para optimizar tamaño.
Tipo String
El tipo String
de Javascript es usado para representar datos textuales o cadenas de caracteres. Es un conjunto de "elementos", de valores enteros sin signo de 16 bits. Cada elemento ocupa una posición en el String. El primer elemento está en el índice 0, el próximo está en el índice 1, y así sucesivamente. La longitud de un String es el número de elementos en ella.
A diferencia de lenguajes como C, los strings en JavaScript son immutables. Esto significa que una vez que una cadena de caracteres es creada no es posible modificarla. Sin embargo es posible crear otra basandose en una operación de la cadena original. Por ejemplo:
- Un fragmento de la cadena original seleccionando letras individuales u usando
String.substr()
. - Una concatenación de dos cadenas usando el operador de concatenacion (
+
) oString.concat()
.
Ten cuidado de no "convertir a cadenas" tu código!
Puede ser tentador usar cadenas para representar datos complejos. Hacerlo trae beneficios a corto plazo:
- Es muy sencillo construir cadenas complejas con concatenación.
- Las cadenas de caracteres son fáciles de debuguear (lo que se imprime es siempre lo que contiene la cadena).
- Las cadenas son el denominador común de muchos APIs (campos de entrada, valores de almacenamiento local, respuestas
XMLHttpRequest
cuando se usaresponseText
, etc.) y puede ser tentador trabajarlo todo sólamente con cadenas de caracteres.
Con convenciones es posible representar cualquier estructura de datos en una cadena. Esto no necesariamente lo convierte en una buena idea. Por ejemplo, con un separador se pudiera simular una lista (un arreglo de JavaScript sería mas apropiado). Desafortunadamente cuando el separador es usado en uno de los elementos de la lista, entonces esta se rompe, habría que escoger entonces un caracter de escape. Todo esto crea un costo innecesario que hay que mantener.
Usa cadenas para datos textuales. Cuando quieras representar datos complejos, procesa las cadenas y usa la abstracción apropiada.
Tipo Symbol
El Symbol es un nuevo tipo en JavaScript introducido en la versión ECMAScript Edition 6. Un Symbol es un valor primitivo único e inmutable y puede ser usado como la clave de una propiedad de un Object (ver debajo). En algunos lenguajes de programación, los Symbols son llamados átomos. Se pueden comparar con enumeraciones de nombres (enum) en C. Para más detalles consultar Symbol y el objeto envoltura Symbol
en JavaScript.
Objetos
En la ciencia de la computación un objeto es un valor en memoria al cual es posible referirse mediante un identifcador.
Propiedades
En JavaScript los objetos pueden ser vistos como una colección de propiedades. Con la sintáxis literal de objetos, un limitado grupo de propiedades son inicializadas; luego pueden ser agregadas o eliminadas otras propiedades. Los valores de las propiedades pueden ser de cualquier tipo, incluyendo otros objetos lo cual permite construir estructuras de datos complejas. Las propiedades se identifican usando claves. Una clave es un valor String o Symbol.
Existen dos tipos de propiedades de objetos las cuales tienen ciertos atributos: La propiedad de datos y la propiedad de acceso.
Propiedad de datos
Asocia una clave con un valor y tiene los siguientes atributos:
Atributo | Tipo | Descripción | Valor por defecto |
---|---|---|---|
[[Value]] | Cualquier tipo JavaScript | El valor obtenido mediante un acceso get a la propiedad. | undefined |
[[Writable]] | Boolean | Si es false , el [[Value]] de la propiedad no puede ser cambiado. |
false |
[[Enumerable]] | Boolean | Si es true , la propiedad será enumerada en ciclos for...in. Consultar también Enumerabilidad y pertenencia de las propiedades |
false |
[[Configurable]] | Boolean | Si es false , la propiedad no puede ser eliminada y otros atributos que no sean [[Value]] y [[Writable]] no pueden ser cambiados. |
false |
Atributo | Tipo | Descripción |
---|---|---|
Read-only | Boolean | Estado inverso del atributode ES5 [[Writable]]. |
DontEnum | Boolean | Estado inverso del atributo ES5 [[Enumerable]]. |
DontDelete | Boolean | Estado inverso del atributo ES5 [[Configurable]]. |
Propiedad de acceso
Asocia una clave con una o más funciones de acceso (get y set) para obtener o almacenar un valor y tiene los siguientes atributos:
Atributo | Tipo | Descripción | Valor por defecto |
---|---|---|---|
[[Get]] | Función, objeto o undefined | La función es ejecutada con una lista de argumentos vacía y devuelve el valor de la propiedad cada vez que un acceso get al valor es realizado. Consultar también get . |
undefined |
[[Set]] | Function object or undefined | The function is called with an argument that contains the assigned value and is executed whenever a specified property is attempted to be changed. See also set . |
undefined |
[[Enumerable]] | Boolean | If true , the property will be enumerated in for...in loops. |
false |
[[Configurable]] | Boolean | If false , the property can't be deleted and can't be changed to a data property. |
false |
Note: Attribute is usually used by JavaScript engine, so you can't directly access it(see more about Object.defineProperty()).That's why the attribute is put in double square brackets instead of single.
"Normal" objects, and functions
A JavaScript object is a mapping between keys and values. Keys are strings (or Symbol
s) and values can be anything. This makes objects a natural fit for hashmaps.
Functions are regular objects with the additional capability of being callable.
Dates
When representing dates, the best choice is to use the built-in Date
utility in JavaScript.
Indexed collections: Arrays and typed Arrays
Arrays are regular objects for which there is a particular relationship between integer-key-ed properties and the 'length' property. Additionally, arrays inherit from Array.prototype
which provides to them a handful of convenient methods to manipulate arrays. For example, indexOf
(searching a value in the array) or push
(adding an element to the array), etc. This makes Arrays a perfect candidate to represent lists or sets.
Typed Arrays are new to JavaScript with ECMAScript Edition 6 and present an array-like view of an underlying binary data buffer. The following table helps you to find the equivalent C data types:
TypedArray objects
Type | Size in bytes | Description | Web IDL type | Equivalent C type |
Int8Array |
1 | 8-bit two's complement signed integer | byte |
int8_t |
Uint8Array |
1 | 8-bit unsigned integer | octet |
uint8_t |
Uint8ClampedArray |
1 | 8-bit unsigned integer (clamped) | octet |
uint8_t |
Int16Array |
2 | 16-bit two's complement signed integer | short |
int16_t |
Uint16Array |
2 | 16-bit unsigned integer | unsigned short |
uint16_t |
Int32Array |
4 | 32-bit two's complement signed integer | long |
int32_t |
Uint32Array |
4 | 32-bit unsigned integer | unsigned long |
uint32_t |
Float32Array |
4 | 32-bit IEEE floating point number | unrestricted float |
float |
Float64Array |
8 | 64-bit IEEE floating point number | unrestricted double |
double |
Keyed collections: Maps, Sets, WeakMaps, WeakSets
These data structures take object references as keys and are introduced in ECMAScript Edition 6. Set
and WeakSet
represent a set of objects, while Map
and WeakMap
associate a value to an object. The difference between Maps and WeakMaps is that in the former, object keys can be enumerated over. This allows garbage collection optimizations in the latter case.
One could implement Maps and Sets in pure ECMAScript 5. However, since objects cannot be compared (in the sense of "less than" for instance), look-up performance would necessarily be linear. Native implementations of them (including WeakMaps) can have look-up performance that is approximately logarithmic to constant time.
Usually, to bind data to a DOM node, one could set properties directly on the object or use data-*
attributes. This has the downside that the data is available to any script running in the same context. Maps and WeakMaps make it easy to privately bind data to an object.
Structured data: JSON
JSON (JavaScript Object Notation) is a lightweight data-interchange format, derived from JavaScript but used by many programming languages. JSON builds universal data structures. See JSON and JSON
for more details.
More objects in the standard library
JavaScript has a standard library of built-in objects. Please have a look at the reference to find out about more objects.
Determining types using the typeof
operator
The typeof
operator can help you to find the type of your variable. Please read the reference page for more details and edge cases.
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 1st Edition (ECMA-262) | Standard | Initial definition. |
ECMAScript 5.1 (ECMA-262) The definition of 'Types' in that specification. |
Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'ECMAScript Data Types and Values' in that specification. |
Standard | |
ECMAScript 2017 Draft (ECMA-262) The definition of 'ECMAScript Data Types and Values' in that specification. |
Draft |