En JavaScript (en adelante, JS) existen diferentes tipos de datos, clasificados en 7 categorías. Dentro de una categoría existe una sub-categoría llamada reference types, pero nos encargaremos de eso más adelante.
Todos los data types tienen sus propiedades únicas y métodos específicos.
Tabla-resumen data types
data type | ¿qué son? |
---|---|
Number | Son números de toda la vida, tanto enteros como decimales. |
String | Son caracteres, letras o cualquier cosa que vaya entre comillas, tanto simples como dobles, eso es a criterio tuyo. |
Boolean | Caracteres de lógica.
Pueden tomar dos valores (true o false).
Se usan para evaluar condiciones y ver si son ciertas o no. |
Null | Utilizado para expresar explícitamente que una variable no tiene ningún valor asignado.
Está muy relacionado con el data type undefined, con la diferencia de que para que una variable tenga el valor de null deberemos asignárselo nosotros manualmente.
Dato curioso: si utilizamos una variable al que le hayamos dado el valor de null combinada con alguna fórmula matemática, null tomará el valor de 0. |
Undefined | Una variable es undefined cuando no le hemos dado ningún valor, así que nuestro navegador le atribuye automáticamente el valor de undefined.
Tanto null como undefined son valores vacíos.
Un detallito: las variables const deben ser inicializadas cuando se declaran. Si no, te dará un syntax error.
De ahí que utilice let para este ejemplo. |
Object | Son estructuras de datos complejas, que pueden tener múltiples propiedades, funciones, etc.
Aquí nos metemos en un tipo de tipos (aka reference types), ya que existen muchos tipos de objetos dentro de este data type, como Arrays, Functions, Dates, sets (disponible próximamente) etc. |
Symbol ES6 | Su característica principal es que son únicos, lo que los hace muy valiosos de cara a asociarlos con un único identificador. const symbOne = Symbol(); |
Strings
Métodos más comunes de los strings
Un method es una función asociada a un data type en concreto. Vamos a verlos asociados a los strings.
método | ¿qué hacen? |
---|---|
.lastIndexOf(‘ ‘) | Identifica la última posición del caracter que le pasemos como argumento. |
.slice(n,n) | Le pasamos dos parámetros numéricos. El primero indica desde qué posición queremos cortar la string y el último, hasta dónde queremos cortarla. |
.substr(n,n) | El primer parámetro indica desde dónde queremos empezar a cortar nuestro string, el segundo, cuántos caracteres queremos que imprima. |
.replace(‘x’, ‘y’) | Admite dos parámetros. El primero es buscado en la string y sustituido por el segundo. Solamente reemplaza la PRIMERA instancia del primer parámetro que encuentre.
Ejemplo (hecho en la consola de chrome): El replace es muy útil combinado con regular expressions. Ejemplo: |
.trim() | Sirve para eliminar los espacios en blanco antes y después de un string. Muy útil por ejemplo para corregir errores del usuario cuando escribe su contraseña en un formulario y teclea por error un espacio en blanco al principio o al final. |
Numbers
JS nos permite hacer operaciones matemáticas, desde la más simple a la más compleja.
En JS, como en matemáticas, el orden de los factores para realizar operaciones importa.
Podemos utilizar este truquito para recordar el orden en el que JS tratará el cálculo que le pidamos que haga: B I D M A S
Es un acrónimo que significa:
B – (brackets)
I – indices2
D – division /
M – multiplication *
A – addition +
S – substraction -
Atajos para los números
JS nos proporciona atajos (en inglés, shorthand notations) para optimizar nuestro código.
Y lo mismo es aplicable para restas, divisiones y multiplicaciones.
Objects
Arrays
Los arrays nos sirven para guardar datos de manera agrupada, algo así como una colección de datos relacionados entre sí.
Pueden almacenar cualquier tipo de data type.
Aquí tienes una guía completa sobre los métodos más comunes de los arrays.
Functions
Las funciones son básicamente bloques de código reutilizable.
Podemos clasificarlas en function declarations y function expressions.
Function declaration: función declarada sin vincularla a ninguna variable.
Function expression: declaramos una variable y le asignamos una función como valor.
Las dos funciones se comportan igual pero hay una pequeña diferencia que tiene que ver con el hoisting.
Así, si invocamos nuestra función greet() antes de haberla declarado, se ejecutará sin problemas, porque lo que en realidad pasa es que JS coge esa función y la eleva (hoisting) al principio del archivo. Por eso funciona.
El hoisting, sin embargo, NO FUNCIONA con las function expressions
Dicho esto, me parece más seguro y limpio usar functions expressions en lugar de function declarations.
Uso del return
En ocasiones querremos que una función nos devuelva algún valor no necesariamente a través de la consola de chrome. Por ejemplo, si queremos calcular la edad de una persona para poder usar ese número posteriormente, de nada nos serviría hacer un console.log, porque lo queremos es usar la variable age.
En este caso, la variable age no se guarda en ninguna parte más allá de la variable local dentro de la función.
Para poder guardarla, podemos usar un return, y guardar así el valor que queramos que la función nos devuelva. Así, el dato que sea estará disponible desde dentro de la función cuando lo necesitemos.
Arrow functions
A partir de la versión ES6 de JS existe una manera más limpia y moderna de escribir funciones. A las funciones que toman esta forma se las llama arrow functions (aka funciones de flecha).
Con esta característica, conseguimos que una función así:
se pueda simplificar, en una sola línea de esta manera:
Las normas son sencillas:
- eliminamos la keyword function.
- si sólo hay un parámetro, omitimos los paréntesis.
- si no hay ningún parámetro, ponemos paréntesis vacíos.
- añadimos una flecha después del parámetro.
- si tenemos un único return (en una sola línea), eliminamos la keyword return y las llaves.
Booleans
Los booleans son habitualmente utilizados en if statements, para evaluar si una condición se cumple o no y tomar ciertas decisiones en base a esa condición.
Ten en cuenta que la condición que pongas en el if se evalúa como true. Es decir, el ejemplo de arriba lo podríamos traducir como "si user es true", independientemente del valor que tome la variable user al inicializarla, que en este caso es false.
Métodos más comunes que devuelven booleans
método | uso (EJEMPLOS HECHOS EN LA CONSOLA DE CHROME) |
---|---|
.includes(‘x’) | Busca el que caracter (o grupo de caracteres) que le pasemos por parámetro y si lo encuentra, devuelve true. Si no, devuelve false. |
Symbols
Los symbols son únicos, no puede existir un symbol igual que otro.
SINTAXIS:
const symbolOne = Symbol();
Fíjate que no utilizamos la keyword "new", para crear un symbol.
Los symbols son primitive types (más información sobre eso en la sección de abajo).
const symb1 = Symbol(); const symb2 = Symbol(); console.log(symb1, symb2, typeof symb1); // Symbol() Symbol() "symbol"
Aunque parezcan idénticos, no lo son.
console.log(symb1 === symb2); // false console.log(symb1 == symb2); // false
Podemos pasarle identificadores (en inglés, indentifiers), para describirlos. Incluso dándoles el mismo indentifier, seguirían sin ser iguales.
const symb1 = Symbol('a generic name'); const symb2 = Symbol('a generic name'); console.log(symb1, symb2, typeof symb1); // Symbol(a generic name) Symbol(a generic name) "symbol" console.log(symb1 === symb2); // false console.log(symb1 == symb2); // false
Los symbols puede ser usados como keys o nombres de propiedades de un objeto. Vamos a verlo con un ejemplo, creando un objeto normal:
const friend = {}; friend.name = 'Chadler'; friend.job = 'business analyst';
Si ahora le damos otro valor a la propiedad job, éste se sobrescribirá, eliminando el valor business analyst y sustituyéndolo por el nuevo.
const friend = {}; friend.name = 'Chadler'; friend.job = 'business analyst'; friend.job = 'copywriter'; console.log(friend); // {name: "Chadler", job: "copywriter"}
Es decir, no podemos darle dos valores distintos a una misma propiedad. Pero sí que podríamos hacerlo utilizando symbols.
const symb1 = Symbol('a generic name'); const symb2 = Symbol('a generic name'); const friend = {}; friend.name = 'Chadler'; friend.job = 'business analyst'; friend.job = 'copywriter'; friend.symb1 = 'New York'; friend.symb2 = 'Tulsa'; console.log(friend); // {name: "Chadler", job: "copywriter", symb1: "New York", symb2: "Tulsa"}
Operadores de comparación
Es vital no confundir este signo = con este == ni con este otro === .
SIGNO | uso (EJEMPLOS HECHOS EN LA CONSOLA DE CHROME) |
---|---|
= | Asigna un valor a una variable. El valor la variable fish es Dori. |
== | Double equals Compara dos valores para ver si son iguales y de serlo, devuelve true.
Recuerda que JS es case sensitive.
A esto se le conoce como abstract equality o loose comparison (o "comparación flojilla" |
!= | Es una variante del anterior. Hace lo contrario: compara dos valores para ver si son diferentes, y de serlo, devuelve true. |
=== | Triple equals A este signo se le conoce como strict comparison.
Es más seguro y recomendable utilizar este tipo de operador de comparación, ya que también tiene en cuenta los value types a la hora de comparar. |
Otros operadores comunes
SIGNO | uso |
---|---|
+= | Sirve para agregar contenido al ya existente, en lugar de sobreescribirlo. |
Conversión de tipos (aka type coercion)
Imagina que tienes una puntuación en un string pero la necesitas en número porque tienes que operar con ella. Para convertir un string en un número:
Si queremos convertir un número en un string:
Primitive types versus reference types
Es fundamental entender la diferencia entre los primitive types y los reference types. Aquí un esquemita para empezar:
Primitive types
- numbers
- strings
- booleans
- null
- undefined
- symbols
Reference types
- todo tipo de objetos, por ejemplo:
object literals
Así que bien podríamos llamar a los reference types "object types", porque todo objeto es un reference type. La diferencia entre un tipo y otro radica en cómo se usan y guardan en la memoria. Existen dos tipos de memoria: la stack memory y la heap memory. Son dos partes distintas de la memoria destinadas a almacenar diferentes cosas.
Cuando declaramos un primitive type, JS lo guarda en su stack memory, mientras que los reference types son almacenados en la heap memory. Los valores almacenados en la stack memory son rápidamente accesibles, pero el espacio de esta memoria es limitado.
La memoria heap almacena tipos de datos más completos (o sea, objetos), por eso, su espacio es mayor, pero el acceso a ella es más lento. Lo que ocurre cuando almacenamos un valor en la stack memory, es que JS asigna el nombre de la variable como un accessor (como un punto de acceso). Es decir, si tenemos una variable así:
let name = 'Max';
'name' siempre será el accessor que buscará JS para darnos el valor de 'Max'.
Pero con los reference types no ocurre lo mismo, porque son almacenados en la heap memory y son accedidos por JS a través de un pointer que apunta a un sitio de la memoria stack donde se guarda una referencia a dicho reference type. Podemos entender un pointer como un puente entre el valor del reference type (que es un objeto) en la memoria heap y el nombre de ese objeto en la memoria stack. Aquí un esquemita para entendernos mejor:
Primitive y reference types en la práctica
Supongamos que declaramos dos variables y asignamos el valor de la segunda a la primera.
JS guarda estas variables en su memoria stack y hace una copia del valor de billOne, asignándolo también a billTwo. Es decir:
30
billOne
30
billTwo
El valor es el mismo, pero JS los almacena cada uno en un espacio, ocupando dos "sitios" en lugar de uno. Así si ahora actualizásemos el valor de billOne, billTwo no se vería afectada.
Pero no ocurre lo mismo cuando creamos un reference type. Vamos a crearnos un objeto y asignarlo a una variable llamada clientOne:
JS lo almacena en la memoria heap, pero creará un pointer en la memoria stack para tener una referencia a dicho objeto. Ese pointer queda vinculado al nombre de la variable (clientOne). Es un ejemplo parecido al del esquema de arriba, pero con un object literal en lugar de con un array.
Lo interesante viene cuando creamos otro objeto y lo asignamos al valor de clientOne:
JS no crea una copia del nuevo objeto en la memoria heap, al contrario de lo que hacía con primitive types en la memoria stack. Lo que hace es crear otro pointer vinculado a la nueva variable (clientTwo), pero que apunta al mismo objeto en la memoria heap. Así que ambos pointers apuntan al mismo objeto en la memoria heap.

Esto significa que si actualizásemos clientOne, clientTwo también obtendría el nuevo valor, porque ambos pointers están apuntando al mismo objeto en la memoria heap.
Visto esto, recuérdalo si en el futuro asignas a una variable el valor de otra, dependiendo de si estés creando una variable de tipo primitive o de tipo reference, porque el resultado, como hemos visto, será distinto.
¡Y hasta aquí el post de hoy! Si te queda alguna duda, ¡nos vemos en los comentarios!
Otros artículos que pueden interesarte
¡Me alegro mucho de que el post te sea útil, Leandro! ?.
Espero que te vaya genial en el bootcamp, recuerda preguntar todas las dudas que te surjan y sentar unas buenas bases de JavaScript, que luego lo agradecerás, jeje.
Saludos desde Argentina!
Hola Ro. Voy recién por la mitad de la guía pero no quería olvidarme de dejar mi comentario. Ya he visto varios de los posteos, el de POO por ejemplo, y realmente el contenido es excelente, me es muy util. Personalmente tengo conocimientos básicos de HTML y CSS y estoy comenzando a estudiar en un bootcamp JS. Es genial la forma que tienes de explicar de forma tan sencilla conceptos que son bastante complejos. Te agradezco por el contenido de tu sitio!!