Crear un objeto en JavaScript

Objetos en JavaScript

En JavaScript, un objeto sigue la notación “clave” : valor, similar a un Hash o Dictionary en otros lenguajes de programación. Para crear objetos en JavaScript, podemos hacerlo de diferentes maneras, ya sea a través de un Object Literal, mediante el método Object.create o por instanciación con el operador new.

Recordemos que JavaScript es un lenguaje basado en prototipos, lo cual quiere decir que todos los objetos que usemos se basan en un objeto pre-existente que le sirve de prototipo (o plantilla). ⭐ Vea más sobre éste tema en el artículo POO en JavaScript – Prototipos.

Podemos pensar en un objeto como un map. Los key en el Map son los nombres de las propiedades del objeto.

⭐ Todos los objetos heredan de Object y poseen la propiedad oculta __proto__, la cual contiene la cadena de prototipos heredada, es por eso que implícitamente heredan métodos como toString, valueOf o constructor.

Object Literal

La notación literal de un objeto se describe en pares de "clave": valor contenidos entre corchetes { }. El nombre de la clave es un String y puede contener caracteres especiales.

    //nuevo objeto vacío
    var obj = {};
    obj.__proto__ === Object.prototype; //true

    //nuevo objeto con propiedades
    var TYPES = {
        text: "text",
        email: "email",
        number: "number",
        date: "date"
    };

    //nuevo objeto con nombres especiales
    var field = {
        "#text": "28/09/2017",
        category: { type: TYPES.date, required: true },
        disabled: false
    };

⭐ Hay que tener en cuenta que las propiedades con caracteres especiales no pueden ser accedidas mediante la notación de punto, ya que no es un identificador válido, por ejemplo, intentar acceder field.#text arrojará un error; sin embargo esas propiedades pueden ser accedidas mediante la notación array-like [""], por ejemplo field["#text"] (vea Property Accessors).

ES2015

Algunas características se han añadido en ES2015 para extender la notación literal de objetos, como la capacidad de establecer el prototipo del objeto, shorthand assignments, shorthand method definition, nombres de propiedades calculadas, getters y setters.

const n42 = () => 42;
let value = "something";

let obj = {
    // Algún prototipo
    __proto__: Object.getPrototypeOf([]),
    // Shorthand de value: value
    value,
    // Shorthand de toString: function()
    toString() {
       // Super calls
       return `custom ${super.toString()}`;
    },
    // Propiedad calculada (dynamic)
    ['prop_' + n42()]: 42,
    ['_#handlers']: [],
    // getter
    get handlers() {
        return this['_#handlers'].length;
    },
    // setter
    set handlers(fn) {
        if (typeof fn === 'function') {
            this['_#handlers'].push(fn);
        }
    }
};

Object.create

El método Object.create() crea un nuevo objeto a partir de un prototipo especificado.

    //nuevo objeto a partir de otro objeto
    var field =
        Object.create({
            name: "username",
            content: { type: TYPES.text, required: true },
            disabled: false
        });

    field.__proto__ === Object.prototype; //true

    //crear un objeto vacío
    var obj =Object.create({});
    obj.__proto__ === Object.prototype; //true

💡 Como vimos anteriormente, el objeto vacío {} no es realmente vacío, ya que contiene un link hacia Object.prototype. Para crear un verdadero objeto vacío, lo hacemos así:

    var obj = Object.create(null);
    obj.__proto__ === Object.prototype; //false
    obj.__proto__ === undefined; // true

Ésta técnica nos permite crear un objeto sin cadena de prototipos. En ES2015 un objeto Map tiene mucha semejanza con este tipo de objetos.

Veamos un ejemplo en donde creamos un objeto a partir del prototipo de una “clase”:

    function Person(name) { this.name = name; }
    Person.prototype.vote = () => this.age > 18;

    //nuevo objeto a partir de un prototipo:
    var mario = Object.create(Person.prototype);
    console.dir(mario);

    Object.prototype.hasOwnProperty.call(mario, "name"); //false

:/ Al imprimir el objeto mario, vemos que no existe la propiedad name la cual fue definida en el constructor Person; esto ocurre porque Object.create crea un objeto a partir de un prototipo, y no de una función constructor. Otra cosa que podemos notar es que al determinar si la propiedad name pertenece a mario, el método hasOwnProperty() retorna false, y como ya lo mencionamos, esto es porque dicha propiedad fue definida en el constructor y no en el prototipo.

➡ Para conocer más detalles sobre Object.create(), sugiero ver el artículo Definir propiedades de un objeto en JavaScript.

El operador new

Al utilizar el operador new creamos una instancia de un objeto basado en el constructor provisto. Debemos tener en cuenta que el constructor es una función a partir de la cual creamos una nueva copia de un objeto específico, la cual hereda una cadena de prototipos definida. Se podría decir que la función constructor es lo que en otros lenguajes de programación llamamos como clase.

➡ Para ver más detalles sobre éste tema, recomiendo leer el artículo POO en JavaScript.

    //nuevo objeto vacío, no se recomienda esto
    var field = new Object();
    // mejor usar la notación literal
    field = {};

La mejor práctica para crear objetos vacíos es mediante la notación Object Literal debido a las optimizaciones que hace el browser en el wrapper de éstos literales ({}, [], /regexp/i, 9, true, "string", ...)

⭐ Si necesitamos crear objetos y reutilizar métodos en donde accedemos a las propiedades de ese objeto, una forma de hacerlo es mediante un constructor o “clase”.

    //definimos el constructor
    function View(name, template) {
        "use strict";
        this.name = name || "index";
        this.template = template || "";
    }

    View.prototype.update = function(data) {
        //implementacion
    };

    //creamos las instancias
    var aboutView = new View("about");
    var productsView = new View("products");

:mrgreen: Para verificar el tipo de instancia lo podemos hacer de las siguientes maneras:

    productsView instanceof View; // true
    productsView instanceof Object; // true
    productsView.__proto__ === View.prototype; // true
    Object.getPrototypeOf(aboutView) === View.prototype; // true
    View.prototype.isPrototypeOf(aboutView); // true
    aboutView.constructor === View; // true

ES2015

ECMAScript2015 viene con muchas adiciones en la sintaxis para la Programación Orientada a Objetos (OOP).

class View {
  constructor (name='index', template='') {
    this.name = name;
    this.template = template;
  }
  
  update() {
    //implementacion
  }
}

Object.freeze(View.prototype);

💡 Al crear una Class es recomendado congelar su prototipo, haciéndolo inmutable, para evitar que pueda ser modificado, por lo tanto añadimos la línea:

Object.freeze(View.prototype);

Conclusión

Podemos resumir que en JavaScript los objetos son dinámicos, y podemos agregar propiedades en tiempo de ejecución, también podemos usar Object.create(null) para crear objetos sin prototipo, el cual puede ser usado como Map, y también podemos crear objetos que hereden de otros objetos y reutilizar su prototipo.

⭐ Para concluir, quiero recomendar la lectura de la segunda parte de este artículo: Definir propiedades de un objeto en JavaScript, y también Let’s explore objects in JavaScript de Cristi Salcescu.

>:D Happy coding!

Advertisements

2 thoughts on “Crear un objeto en JavaScript

Comentarios

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s