JavaScript

JavaScript

Tutorial JavaScript: Tipos de datos

JavaScript tipos de datos: definición y ejemplos. Domina los diferentes tipos de datos en JavaScript con ejemplos prácticos y detallados.

Aprende JavaScript y certifícate

Tipos primitivos básicos: tipado dinámico, Number, String, Boolean

En JavaScript, el tipado dinámico permite que las variables cambien de tipo durante la ejecución del programa. No es necesario especificar el tipo al declarar una variable; JavaScript determina el tipo en función del valor asignado.

El tipo Number representa tanto números enteros como de punto flotante. Se utiliza para realizar operaciones matemáticas y cálculos numéricos. Por ejemplo:

let age = 30;
let temperature = -5.5;

Las Strings son cadenas de texto que se utilizan para representar caracteres y palabras. Se pueden definir usando comillas simples ' ', comillas dobles " " o backticks ` para crear template literals que permiten la interpolación de variables:

let firstName = "Juan";
let greeting = `Hola, ${firstName}!`;

El tipo Boolean tiene solo dos valores posibles: true o false. Es fundamental para realizar evaluaciones lógicas y controlar el flujo de ejecución mediante estructuras condicionales:

let isMember = true;
let hasAccess = false;

Debido al tipado dinámico, una variable en JavaScript puede cambiar de tipo al asignarle un nuevo valor de diferente tipo primitivo:

let variable = 100;    // variable es un Number
variable = "Cien";     // ahora es una String
variable = false;      // ahora es un Boolean

Es crucial estar al tanto del tipo de datos con el que se está trabajando para evitar errores inesperados. La función typeof es útil para verificar el tipo de una variable en tiempo de ejecución:

let data = 42;
console.log(typeof data); // "number"

Tipos primitivos especiales: undefined y null, Symbol, BigInt

JavaScript cuenta con varios tipos primitivos especiales que manejan situaciones únicas en el lenguaje. Estos tipos son undefined, null, Symbol y BigInt.

El valor undefined se asigna automáticamente a variables que han sido declaradas pero no inicializadas. Representa la ausencia de un valor asignado. Por ejemplo:

let user;
console.log(user); // undefined

Por otro lado, null es un valor que indica intencionalmente la ausencia de cualquier objeto o valor. Se utiliza para resetear una variable o indicar que aún no tiene un valor significativo:

let product = null;
console.log(product); // null

Aunque ambos representan una falta de valor, undefined y null tienen diferencias clave. undefined se refiere a variables que no han sido definidas o inicializadas, mientras que null es un valor asignable que indica ausencia intencional. Es importante distinguir entre ellos al realizar comparaciones:

console.log(undefined == null);  // true (igualdad débil)
console.log(undefined === null); // false (igualdad estricta)

El tipo Symbol, introducido en ES6, se utiliza para crear identificadores únicos e inmutables. Los Symbols son útiles para crear propiedades privadas en objetos o evitar colisiones de nombres:

const id = Symbol('id');
let user = {
  name: 'Alice',
  [id]: 12345
};

En este ejemplo, la propiedad [id] es única y no colisionará con otras propiedades. Los Symbols no son enumerables por defecto, lo que añade una capa de privacidad a las propiedades de los objetos.

El tipo BigInt permite representar números enteros de gran tamaño, más allá del límite del tipo Number (253 - 1). Es esencial cuando se trabaja con cifras muy grandes que requieren precisión:

const bigNumber = 9007199254740991n;
const anotherBigNumber = BigInt('9007199254740991500000000');

Para crear un BigInt, se añade la letra n al final del número o se utiliza la función BigInt(). Las operaciones aritméticas con BigInt son similares a las de Number, pero no se pueden mezclar tipos sin conversión explícita:

const sum = bigNumber + 10n; // Correcto
const invalidSum = bigNumber + 10; // TypeError

Es crucial entender que los BigInt y los Number no son intercambiables. Intentar combinarlos sin conversión resultará en un error de tipo. Para comparar un BigInt con un Number, es necesario asegurarse de que ambos son del mismo tipo:

const maxSafeInteger = Number.MAX_SAFE_INTEGER;
console.log(bigNumber > maxSafeInteger); // true
console.log(bigNumber === BigInt(maxSafeInteger)); // false

Al trabajar con estos tipos primitivos especiales, es fundamental ser consciente de sus características únicas para evitar errores y aprovechar al máximo las capacidades de JavaScript.

Tipos de referencia: diferencia entre tipos primitivos y tipos de referencia

En JavaScript, los tipos de referencia son esenciales para manejar datos complejos como objetos, arrays y funciones. A diferencia de los tipos primitivos, que almacenan directamente el valor asignado, los tipos de referencia almacenan una dirección en memoria que apunta al valor real.

Los tipos primitivos incluyen Number, String, Boolean, undefined, null, Symbol y BigInt. Cuando asignamos un tipo primitivo a una variable, esta almacena el valor en sí mismo:

let age = 30;
let greeting = "Hello";

En este ejemplo, age y greeting contienen directamente los valores 30 y "Hello" respectivamente.

Por otro lado, los tipos de referencia comprenden objetos, arrays y funciones. Al asignar un tipo de referencia a una variable, esta no almacena el valor directamente, sino una referencia al lugar en memoria donde se ubica el objeto:

let user = { name: "Alice", email: "alice@example.com" };
let numbers = [1, 2, 3, 4, 5];

Aquí, user y numbers almacenan referencias a sus respectivos objetos en el heap de memoria.

Una diferencia clave entre ambos tipos es cómo se comportan al asignar o copiar valores. Con los tipos primitivos, al copiar una variable a otra, se crea una copia independiente:

let x = 10;
let y = x;
y = 20;
console.log(x); // Output: 10

En este caso, x permanece con el valor 10, ya que y es una copia separada.

Sin embargo, con los tipos de referencia, al copiar una variable a otra, ambas apuntan al mismo objeto:

let obj1 = { message: "Hi" };
let obj2 = obj1;
obj2.message = "Hello";
console.log(obj1.message); // Output: "Hello"

Aquí, al modificar obj2.message, también cambiamos obj1.message porque ambos referencian al mismo objeto en memoria.

Este comportamiento es especialmente importante al pasar variables a funciones. Con tipos primitivos, se pasa una copia del valor:

function increment(num) {
  num++;
}

let count = 5;
increment(count);
console.log(count); // Output: 5

El valor de count no cambia, ya que la función trabaja con una copia.

Con tipos de referencia, se pasa la referencia al objeto, lo que permite que la función modifique el objeto original:

function addItem(array, item) {
  array.push(item);
}

let fruits = ["apple", "banana"];
addItem(fruits, "orange");
console.log(fruits); // Output: ["apple", "banana", "orange"]

En este ejemplo, la función addItem modifica directamente el array fruits.

Para evitar modificaciones no deseadas en objetos compartidos, es común crear copias de los mismos. Una forma de hacer una copia superficial de un objeto es usando el operador spread { ...obj }:

let original = { a: 1, b: 2 };
let copy = { ...original };
copy.a = 3;
console.log(original.a); // Output: 1

La variable copy es una nueva referencia que no afecta al objeto original.

Sin embargo, las copias superficiales no son suficientes para objetos anidados. En estos casos, es necesario realizar una copia profunda utilizando métodos como structuredClone:

let nestedObj = { a: 1, b: { c: 2 } };
let deepCopy = structuredClone(nestedObj);
deepCopy.b.c = 3;
console.log(nestedObj.b.c); // Output: 2

De esta manera, se asegura que las modificaciones en deepCopy no afecten a nestedObj.

Entender la diferencia entre tipos primitivos y tipos de referencia es crucial para manejar correctamente la mutabilidad y el alcance de los datos en JavaScript. Los tipos de referencia permiten una manipulación más flexible de los datos, pero requieren precaución para evitar efectos secundarios inesperados.

Operaciones y verificación de tipos

Al trabajar con diferentes tipos de datos en JavaScript, es fundamental entender cómo se comportan las operaciones entre ellos y cómo verificar el tipo de una variable en tiempo de ejecución. JavaScript es un lenguaje de tipado dinámico y realiza coerciones de tipo implícitas en ciertas operaciones, lo que puede conducir a resultados inesperados si no se maneja correctamente.

La coerción de tipos es el proceso por el cual JavaScript convierte un valor de un tipo a otro durante una operación. Por ejemplo, al sumar un Number y una String, JavaScript convierte el número a una cadena y realiza una concatenación:

let result = 5 + "10";
console.log(result); // "510"

En este caso, la variable result es una String que contiene "510", ya que el número 5 se convirtió en la cadena "5" antes de la concatenación. Es importante estar atento a estas conversiones automáticas para evitar comportamientos inesperados.

Al realizar operaciones aritméticas con operadores como -, * o /, JavaScript intenta convertir las Strings a Numbers:

let difference = "20" - 5;
console.log(difference); // 15

Aquí, la cadena "20" se convierte en el número 20 antes de realizar la resta. Sin embargo, si la cadena no puede convertirse en un número válido, el resultado será NaN (Not-a-Number):

let invalidOperation = "hello" * 2;
console.log(invalidOperation); // NaN

El valor NaN indica que una operación aritmética no produjo un número válido. Puedes verificar si un valor es NaN utilizando la función isNaN():

console.log(isNaN(invalidOperation)); // true

Comprender la diferencia entre los operadores de igualdad == y === es crucial. El operador == realiza una comparación débil, que incluye coerción de tipos, mientras que === realiza una comparación estricta, sin coerción:

console.log(5 == "5");  // true
console.log(5 === "5"); // false

En el primer caso, JavaScript convierte la cadena "5" al número 5 antes de comparar. En el segundo, como los tipos son diferentes (Number y String), la comparación estricta devuelve false. Es una buena práctica utilizar el operador === para evitar resultados inesperados debidos a coerciones implícitas de tipo.

La función typeof es útil para determinar el tipo primitivo de una variable:

let value = true;
console.log(typeof value); // "boolean"

Sin embargo, al trabajar con objetos, typeof puede no proporcionar suficiente información. Por ejemplo, tanto los arrays como los objetos literales devuelven "object":

console.log(typeof {}); // "object"
console.log(typeof []); // "object"

Para verificar si una variable es un array, se puede utilizar el método Array.isArray():

let list = [1, 2, 3];
console.log(Array.isArray(list)); // true

El operador instanceof permite comprobar si un objeto es instancia de una clase o constructor específico:

function Person(name) {
  this.name = name;
}

let alice = new Person("Alice");
console.log(alice instanceof Person); // true

Este operador es útil para verificar el tipo de objetos personalizados. Para obtener información más precisa sobre el tipo de un valor, se puede utilizar el método Object.prototype.toString.call():

console.log(Object.prototype.toString.call(null));      // "[object Null]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
console.log(Object.prototype.toString.call([]));        // "[object Array]"
console.log(Object.prototype.toString.call({}));        // "[object Object]"

Este método es especialmente útil para distinguir entre diferentes tipos de objetos y valores primitivos.

Para evitar las coerciones implícitas, es recomendable realizar conversiones explícitas de tipos cuando sea necesario. Por ejemplo, para convertir una String a Number:

let str = "42";
let num = Number(str);
console.log(num);        // 42
console.log(typeof num); // "number"

También es posible convertir una String a Number utilizando el operador unario +:

let num = +"42";

Para convertir un valor a String, se puede utilizar la función String():

let value = 100;
let str = String(value);
console.log(str);           // "100"
console.log(typeof str);    // "string"

La conversión a Boolean es útil para evaluar la "verdad" de un valor. Los valores que JavaScript considera falsy son: false, 0, "" (cadena vacía), null, undefined y NaN. Cualquier otro valor es truthy:

let value = 0;
let bool = Boolean(value);
console.log(bool); // false

Al realizar operaciones lógicas, JavaScript convierte automáticamente los valores a booleanos según estas reglas. Es esencial ser consciente de este comportamiento para evitar errores en las condiciones.

Recapitulando, para mantener un código robusto y evitar errores relacionados con los tipos de datos:

  • Utiliza comparaciones estrictas (=== y !==) en lugar de las débiles (== y !=).
  • Realiza conversiones explícitas de tipos en lugar de confiar en las coerciones implícitas.
  • Verifica los tipos de datos con typeof, instanceof o Array.isArray() según corresponda.
  • Ten cuidado al operar con null y undefined, y recuerda que typeof null devuelve "object".
  • Utiliza Number.isNaN() para verificar si un valor es NaN de manera fiable.

Conversiones entre tipos de datos

En JavaScript, es común la necesidad de convertir datos de un tipo a otro, ya sea para realizar operaciones específicas o para asegurar que los valores sean compatibles con ciertas funciones. Estas conversiones entre tipos de datos pueden ser explícitas o implícitas, y comprender cómo funcionan es esencial para evitar errores y comportamientos inesperados en el código.

Las conversiones implícitas, también conocidas como coerciones de tipo, ocurren automáticamente cuando JavaScript evalúa expresiones que involucran diferentes tipos de datos. Sin embargo, para tener un mayor control y claridad en el código, es recomendable realizar conversiones explícitas utilizando funciones y métodos proporcionados por el lenguaje.

Para convertir valores a números, se puede utilizar la función Number(), que intenta transformar el valor dado en un número. Si la conversión no es posible, devuelve NaN (Not-a-Number). Por ejemplo:

let value = "42";
let numberValue = Number(value); // 42

Otra forma de convertir cadenas a números enteros o decimales es mediante las funciones parseInt() y parseFloat(), respectivamente. parseInt() analiza la cadena y devuelve un número entero, permitiendo especificar la base numérica:

let hexNumber = "0xFF";
let intValue = parseInt(hexNumber, 16); // 255

Es importante tener en cuenta que parseInt() y parseFloat() analizan la cadena hasta donde es posible extraer un número válido, ignorando caracteres no numéricos posteriores:

let mixedString = "123abc";
let parsedNumber = parseInt(mixedString); // 123

Para convertir valores a cadenas de texto, se utiliza la función String() o el método toString(). El método toString() está disponible en muchos tipos de datos y permite especificar una base numérica cuando se trata de números:

let num = 255;
let hexString = num.toString(16); // "ff"

Al convertir valores a booleanos, la función Boolean() es útil. Esta conversión sigue las reglas de los valores truthy y falsy en JavaScript. Los valores considerados falsy son false, 0, "" (cadena vacía), null, undefined y NaN. Cualquier otro valor es truthy:

let zero = 0;
let isZeroTruthy = Boolean(zero); // false

En situaciones donde es necesario convertir objetos o arrays a valores primitivos, se utilizan los métodos valueOf() y toString(). Por defecto, JavaScript llama a estos métodos cuando necesita convertir un objeto a un tipo primitivo en operaciones como comparaciones o concatenaciones:

let date = new Date();
let timestamp = date.valueOf(); // Número que representa el tiempo en milisegundos

Para convertir objetos a JSON, se emplea el método JSON.stringify(), que transforma un objeto JavaScript en una cadena JSON. De manera inversa, JSON.parse() convierte una cadena JSON en un objeto:

let user = { name: "Alice", age: 30 };
let jsonString = JSON.stringify(user); // '{"name":"Alice","age":30}'
let parsedUser = JSON.parse(jsonString); // Objeto original

Al trabajar con tipos especiales como BigInt, es necesario realizar conversiones cuidadosas. Para convertir un BigInt a Number, se puede usar el constructor Number(), aunque hay que tener precaución, ya que puede provocar pérdida de precisión si el BigInt es demasiado grande:

let bigIntValue = 12345678901234567890n;
let numberValue = Number(bigIntValue); // Pérdida de precisión

En el caso de los Symbols, su conversión a otros tipos es limitada. Los Symbols no pueden convertirse automáticamente a cadenas de texto, y hacerlo puede generar errores. Si es necesario, se puede obtener su descripción:

let sym = Symbol("id");
let symDescription = sym.description; // "id"

Es recomendable evitar mezclas innecesarias de tipos y realizar conversiones explícitas cuando sea necesario. Esto mejora la legibilidad y confiabilidad del código, y previene comportamientos inesperados debido a las coerciones implícitas.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

Plan mensual

19.00 € /mes

Precio normal mensual: 19 €
47 % DE DESCUENTO

Plan anual

10.00 € /mes

Ahorras 108 € al año
Precio normal anual: 120 €
Aprende JavaScript online

Ejercicios de esta lección Tipos de datos

Evalúa tus conocimientos de esta lección Tipos de datos con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Funciones flecha

JavaScript
Puzzle

Polimorfismo

JavaScript
Test

Array

JavaScript
Código

Transformación con map()

JavaScript
Test

Gestor de tareas con JavaScript

JavaScript
Proyecto

Manipulación DOM

JavaScript
Test

Funciones

JavaScript
Test

Funciones flecha

JavaScript
Código

Async / Await

JavaScript
Código

Creación y uso de variables

JavaScript
Test

Excepciones

JavaScript
Puzzle

Promises

JavaScript
Código

Funciones cierre (closure)

JavaScript
Test

Herencia

JavaScript
Puzzle

Herencia

JavaScript
Test

Estructuras de control

JavaScript
Código

Selección de elementos DOM

JavaScript
Test

Modificación de elementos DOM

JavaScript
Test

Filtrado con filter() y find()

JavaScript
Test

Funciones cierre (closure)

JavaScript
Puzzle

Funciones

JavaScript
Puzzle

Mapas con Map

JavaScript
Test

Reducción con reduce()

JavaScript
Test

Callbacks

JavaScript
Puzzle

Manipulación DOM

JavaScript
Puzzle

Promises

JavaScript
Test

Async / Await

JavaScript
Test

Eventos del DOM

JavaScript
Puzzle

Introducción a JavaScript

JavaScript
Puzzle

Async / Await

JavaScript
Puzzle

Promises

JavaScript
Puzzle

Filtrado con filter() y find()

JavaScript
Código

Callbacks

JavaScript
Test

Creación de clases y objetos Restaurante

JavaScript
Código

Reducción con reduce()

JavaScript
Código

Filtrado con filter() y find()

JavaScript
Puzzle

Reducción con reduce()

JavaScript
Puzzle

Conjuntos con Set

JavaScript
Puzzle

Herencia de clases

JavaScript
Código

Eventos del DOM

JavaScript
Test

Clases y objetos

JavaScript
Puzzle

Modificación de elementos DOM

JavaScript
Puzzle

Mapas con Map

JavaScript
Puzzle

Introducción a JavaScript

JavaScript
Test

Funciones

JavaScript
Código

Tipos de datos

JavaScript
Test

Clases y objetos

JavaScript
Test

Array

JavaScript
Test

Conjuntos con Set

JavaScript
Test

Array

JavaScript
Puzzle

Encapsulación

JavaScript
Puzzle

Clases y objetos

JavaScript
Código

Uso de operadores

JavaScript
Puzzle

Uso de operadores

JavaScript
Test

Estructuras de control

JavaScript
Test

Excepciones

JavaScript
Test

Transformación con map()

JavaScript
Puzzle

Funciones flecha

JavaScript
Test

Selección de elementos DOM

JavaScript
Puzzle

Encapsulación

JavaScript
Test

Mapas con Map

JavaScript
Código

Creación y uso de variables

JavaScript
Puzzle

Polimorfismo

JavaScript
Puzzle

Tipos de datos

JavaScript
Puzzle

Estructuras de control

JavaScript
Puzzle

Todas las lecciones de JavaScript

Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a JavaScript y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender los tipos de datos primitivos y de objeto en JavaScript.
  2. Aprender a declarar y utilizar variables para almacenar diferentes tipos de datos.
  3. Familiarizarse con la creación y manipulación de objetos y arrays.
  4. Conocer cómo utilizar funciones y métodos para operar con diferentes tipos de datos.
  5. Entender el propósito y uso de los tipos de datos especiales undefined, null y Symbol.