Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Objetos

Contenidos
  1. Introducción
  2. Objetos básicos
  3. Accediendo a las propiedades
  4. Ejecutando métodos
  5. Modificando objetos
  6. El objeto global
  7. Funciones Constructoras
  8. La propiedad constructor
  9. Funciones que retornan objetos
  10. Prototipos
    1. _proto_
  11. Herencia

Introducción

En este módulo nos detenernos en objetos y experimentaremos como Javascript implementa este paradigma de una forma diferente a la forma clásica (o más enseñada) con Clases y Herencia.

En forma general un objeto es una colección de datos (propiedades) y métodos para interactuar con esas propiedades. En Javascript todo es un objeto, excepto los datos primitivos.

Recordemos los datos primitivos, aquellos que no son objetos ya que carecen de métodos y propiedades:

  • string
  • number
  • boolean
  • undefined
  • null

¡No entiendo! ¿Entonces cómo funciona la expresión: "foo".includes("oo")?

JavaScript crea un nuevo objeto (efímero) utilizando la función constructora String, el cual define la función includes en su prototipo. Al final de este capítulo comprenderás como funciona la cadena de prototipos en JavaScript.

Objetos básicos

Los objetos en Javascript comparten varias similitudes con los arreglos, ya que ambos son objetos. A diferencia de los arreglos, los objetos en lugar de identificar a sus valores con índices numéricos (ej. someArray[1]), los identifica usando llaves (ej. someObject 'prop_or_method']) keys.

Veamos un objeto simple y examinemos sus partes:

 
  var record = {
  band: 'Metallica',
  name: 'And justice for all',
  year: '1988',
  fullName: function(){
    return record.name + ", " + record.band + ", " + record.year
  }
}
console.log(record.fullName())
  • El nombre de la variable que referencia al objeto en este caso es record.
  • En lugar de definir al objeto con [ ] como en los arreglos, se definen con { }.
  • Para separar la llave y su valor se utilizan los dos puntos key:value.
  • Cada llave y valor es separada por commas.

Es posible usar comillas (“ “) en las llaves cuando contiene espacios, comienza con un número o es una palabra reservada.

Cuando hablamos de un arreglo se dice que este tiene elementos, cuando hablamos de objetos decimos es tiene propiedades y si el valor de esta propiedad es una función, se le llama método.

Arreglos -> tienen: elementos

Objetos -> tienen: propiedades

En otros lenguajes como php, python y ruby los objetos son conocidos como arreglos asociativos, diccionarios o hashes respectivamente

Accediendo a las propiedades

Hay dos formas de acceder a las propiedades:

  • Usando [ ] ó
  • Usando .

¿Cuál usar en cada caso?

La notación con punto es más rápida, pero no siempre puede ser usada. Si el nombre de la propiedad no cumple con un nombre de variable válida, se debe usar comillas.

Al acceder a una propiedad que no existe también retorna undefined al igual que en los arreglos.

 
  var guitar = {
  brand: 'Fender',
  model: 'Telecaster'
}
console.log(guitar.brand)
console.log(guitar["model"])
console.log(guitar["color"])

Es posible crear objetos y arreglos de otras formas además que solo usando { } y [ ] que veremos más adelante. La notación usada hasta acá se denomina notación literal

Ejecutando métodos

Ya sabemos que los métodos son solo una propiedad cuyo valor es una función por lo que puedes acceder a ellos usando el punto o los corchetes. Para invocar la función se agregan los paréntesis y podemos pasar parámetros a la función.

 
  var record = {
  band: 'Metallica',
  name: 'And justice for all',
  year: '1988',
  fullName: function(){
    return record.name + ", " + record.band + ", " + record.year
  }
}
console.log(record["fullName"]())
console.log(record.fullName())

Modificando objetos

Javascript permite modificar propiedades y métodos de objetos existentes en cualquier momento. Podemos partir con un objeto “vacío” y agregar propiedades después. En JavaScript podemos acceder directamente a las propiedades de un objeto, sin tener que programar métodos especiales (Setters y Getters). Por esto podemos decir que la encapsulación de los objetos en JavaScript es baja.

 
str = "some value"
console.log(str.includes("ome"))
str.foo = "anything"
console.log(str.foo)

El objeto global

El entorno global donde corre JavaScript (Navegador web por ejemplo) provee un objeto global y todas las variables globales son accesibles como propiedades de este objeto:

 
var someVar = "a var variable"
let someLetVar = "a  let variable"
const someConstVar = "a const variable"

console.log(this.someVar)
console.log(this.someLetVar)
console.log(this.someConstVar)

Funciones Constructoras

Además de crear objetos literales, existe otra forma de crear objetos usando funciones constructoras. En el siguiente ejemplo vemos un patrón frecuente para lograr objetos similares. Establecer las el valor de las propiedades en la función constructora Person y agregar los métodos mediante en objeto prototype de la función constructora. Este objeto se utiliza para compartir métodos en todas las instancias.

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

Person.prototype.getName = function() {
  return this.name;
};

Person.prototype.getAge = function() {
  return this.age;
};

var person = new Person("John Doe", 30);
console.log(person.getName()); // imprime "John Doe"
console.log(person.getAge()); // imprime 30

La propiedad constructor

Cuando se crea un objeto, una propiedad especial es asignada sin que lo veamos. La propiedad constructor. Esta contiene una referencia a la función constructora utilizada para crear el objeto.

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

var person = new Person("John Doe", 30);
console.log(person.constructor);

//Look at this
var person_two = new person.constructor("Alice", 32)
console.log(person_two.name)

Funciones que retornan objetos

Además de las funciones constructoras, las que usamos con new constructorFunction('some_params'), podemos usar funciones normales (function declarations) para crear objetos sin utilizar el operador new. Por ejemplo:

 
function student(name) {
  return{
    name: name
  }
}

var student = Student("John Doe");
console.log(student.constructor);
//Look at this
var student_two = new student.constructor("Alice")
console.log(student_two.name)

El ejemplo anterior muestra que las diferentes opciones para crear objetos retornan en realidad diferentes tipos de objetos. En el caso de la función constructora, retorna un objeto cuyo constructor apunta a la función constructora, mientras que cuando es una función normal, apunta a function Object, por lo que no podemos efectivamente crear nuevas instancias con el mismo comportamiento como sí lo tenemos con la función constructora.

Prototipos

En JavaScript, un prototipo es una característica del lenguaje que permite la creación de objetos heredando de otros objetos. Cada objeto en JavaScript tiene un prototipo, que es otro objeto del cual ese objeto hereda propiedades y métodos. Esta relación de herencia se conoce como la cadena de prototipos.

Sí, en JavaScript, cualquier objeto tiene un prototipo. Por defecto, todos los objetos heredan de un objeto especial llamado Object.prototype, que proporciona varios métodos y propiedades útiles, como toString() y hasOwnProperty(). Además, cuando se crea una función, se le asigna un prototipo especial llamado Function.prototype, que proporciona métodos adicionales para trabajar con funciones.

_proto_

Para acceder al prototipo de un objeto literal en JavaScript, puede utilizar la propiedad especial __proto__ del objeto. Sin embargo, esta propiedad no es compatible con todos los navegadores, por lo que se recomienda utilizar el método Object.getPrototypeOf() para acceder al prototipo de un objeto.

 
let obj = {a: 1, b: 2};

console.log(Object.getPrototypeOf(obj) == obj.__proto__ );

Los primitivos no tienen métodos, pero aún así se comportan como si los tuvieran. Cuando se accede a las propiedades de los primitivos, JavaScript automáticamente empaqueta el valor en un objeto envoltorio y accede a la propiedad en ese objeto en su lugar. Por ejemplo, “foo”.includes(“f”) implícitamente crea un objeto envoltorio de tipo String y llama a String.prototype.includes() en ese objeto. Este comportamiento de auto-empaquetamiento no es observable en el código de JavaScript, pero es un buen modelo mental para varios comportamientos, como por ejemplo, por qué “mutar” los primitivos no funciona (porque str.foo = 1 no está asignando a la propiedad foo de str en sí, sino a un objeto envoltorio efímero).

 
str = "some value"
console.log(str.includes("ome"))
str.foo = "anything"
console.log(str.foo)

Herencia