Tipos de datos y estructuras en JavaScript

Este articulo necesita una revisión editorial. Cómo puedes ayudar.

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

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

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 undefinedUndefined 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 (+) o String.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 usa responseText, 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 únicoinmutable 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:

Atributos de una propiedad de datos
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
Atributos obsoletos (a partir de ECMAScript 3, renombrados en ECMAScript 5)
Atributo Tipo Descripción
Read-only Boolean Estado inverso del atributo 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:

Atributos de una propiedad de acceso
Atributo Tipo Descripción Valor por defecto
[[Get]] Función, objeto o undefined

La función es llamada 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

La función es llamada con un argumento que contiene la variable asignada y es ejecutada siempre que una propiedad especifica se intenta cambiar. Consultar también set.

undefined
[[Enumerable]] Boolean  

Si el valor es true, la propiedad será enumerada en bucles for...in.

false
[[Configurable]] Boolean Si el valor es  false, la propiedad no podrá ser eliminada y tampoco ser modificada a una propiedad de datos. false

Nota: El atributo normalmente es usado por el motor de JavaScript, por lo que no puedes acceder directamente a él (Consulta acerca de Object.defineProperty()). Esa es la razón de porque el atributo es puesto con doble corchete, en lugar de uno.

Objetos "Normales", y funciones

Un objeto en JavaScript es una lista de pares de llaves y valores, Las llaves son una cadena de carácteres (string) o en dado caso Symbols y los valores pueden ser cualquier tipo de dato. Esto hace a los objetos un ajuste natural para hashmaps.

Las funciones son objetos regulares con una capacidad adicional de poder ser llamadas.

Fechas

Cuando representas fechas, la mejor elección es usar el objeto Date incorporado en 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  

See also

Etiquetas y colaboradores del documento

 Colaboradores en esta página: damnyorch, devconcept, sancospi
 Última actualización por: damnyorch,