Skip to content

Objects

Objects are a fundamental building block in JavaScript. They enable you to represent and handle complex data structures. In this module, you’ll learn how to create and manipulate objects in JavaScript, including adding, removing, and modifying values. Additionally, you’ll understand how to use objects in conjunction with functions and arrays.

What is an object in JS

In essence, objects are simply hash tables with unique keys and their corresponding values.

There are several ways to create objects:

  • Bracket notation
  • Dot notation
  • Curly braces notation

By default, objects can be created using:

  • new Object()
  • {}

Objects inherit methods like toString() because of their prototype:

let o1 = new Object();
console.log(o1["toString"]()); // [object Object]
console.log(o1.toString());    // [object Object]

let o2 = {};
console.log(o2["toString"]()); // [object Object]
console.log(o2.toString());    // [object Object]

Bracket Notation

Using the bracket notation, you can dynamically set or get object properties:

let p1 = {};
p1["name"] = "Mathias";
p1["birthYear"] = 2006;
p1["estimatedAge"] = function () {
    return new Date().getFullYear() - this["birthYear"];
};
p1["toString"] = function () {
    console.log(`My name is ${this["name"]} and I am ${this["estimatedAge"]()} years old`);
};
p1["toString"](); // My name is Mathias and I am 19 years old

Dot Notation

Dot notation is a concise way to access object properties:

let p2 = {};
p2.name = "Mikkel";
p2.birthYear = 2003;
p2.estimatedAge = function () {
    return new Date().getFullYear() - this.birthYear;
};
p2.toString = function () {
    console.log(`My name is ${this.name} and I am ${this.estimatedAge()} years old`);
};
p2.toString(); // My name is Mikkel and I am 22 years old

Curly Braces Notation

Using curly braces, you can define an object and its properties/methods all at once:

let p3 = {
    name: "Michell",
    birthYear: 1966,
    estimatedAge: function () {
        return new Date().getFullYear() - this.birthYear;
    },
    toString: function () {
        console.log(`My name is ${this.name} and I am ${this.estimatedAge()} years old`);
    },
};
p3.toString(); // My name is Michell and I am 59 years old

Combining Notations

It’s possible to mix and match the notations when working with objects:

let p4 = {};
p4["name"] = "Lene";
p4.birthYear = 1964;
p4["estimatedAge"] = function () {
    return new Date().getFullYear() - this.birthYear;
};
p4.toString = function () {
    console.log(`My name is ${this.name} and I am ${this["estimatedAge"]()} years old`);
};
p4.toString(); // My name is Lene and I am 61 years old

Adding and Removing Properties

You can dynamically add or remove properties from an object:

let p5 = {
    name: "Villads",
    birthYear: 2017,
    estimatedAge: function () {
        return new Date().getFullYear() - this.birthYear;
    },
    toString: function () {
        console.log(`My name is ${this.name} and I am ${this.estimatedAge()} years old`);
    },
};
p5.toString(); // My name is Villads and I am 8 years old

p5.yearsTo18 = function () {
    return 18 - this.estimatedAge();
};
delete p5.name;
p5.toString(); // My name is undefined and I am 8 years old

Iterating Over Keys

You can loop through an object’s properties using a for...in loop:

let p6 = {
    navn: "Villads",
    fødselsår: 2017,
    estimeretAlder: function () {
        return new Date().getFullYear() - this.fødselsår;
    },
    toString: function () {
        console.log(
            `Jeg hedder ${this.navn} og er ${this.estimeretAlder()} gammel`
        );
    },
};
p6.toString(); // Jeg hedder Villads og er 8 gammel

for (const key in p6) {
    console.log(key + " = " + typeof p6[key]);
}
/*
navn = string
fødselsår = number
estimeretAlder = function
toString = function
*/

for (const key in p6) {
    console.log(`${key}: ${p6[key]}`);
}

/*
navn: Villads
fødselsår: 2017
estimeretAlder: function () {
    return new Date().getFullYear() - this.fødselsår;
  }
toString: function () {
    console.log(`Jeg hedder ${this.navn} og er ${this.estimeretAlder()} gammel`);
  }
*/

for (const key in p6) {
    if (typeof p6[key] === "function") {
        p6[key]();
    } else {
        console.log(`${key}: ${p6[key]}`);
    }
}
/*
navn: Villads
fødselsår: 2017
Jeg hedder Villads og er 8 gammel
*/

Arrays of Objects

Objects can be elements within an array:

let toString = function () {
    console.log(
        `Jeg hedder ${this.navn} og er ${this.estimeretAlder()} gammel`
    );
};
let estimeretAlder = function () {
    return new Date().getFullYear() - this.fødselsår;
};
let personer = [
    {
        navn: "Michell",
        fødselsår: 1966,
        estimeretAlder: estimeretAlder,
        toString: toString,
    },
    {
        navn: "Lene",
        fødselsår: 1964,
        estimeretAlder: estimeretAlder,
        toString: toString,
    },
];
personer.push({
    navn: "Mikkel",
    fødselsår: 2003,
    estimeretAlder: estimeretAlder,
    toString: toString,
});

let m = {};
m.navn = "Mathias";
m.fødselsår = 2006;
m.estimeretAlder = estimeretAlder;
m.toString = toString;
personer.push(m);

console.log(personer.length); // 4
for (let i = 0; i < personer.length; i++) {
    personer[i].toString();
}
/*
Jeg hedder Michell og er 59 gammel
Jeg hedder Lene og er 61 gammel
Jeg hedder Mikkel og er 22 gammel
Jeg hedder Mathias og er 19 gammel
*/

for (const person of personer) {
    person.toString();
}
/*
Jeg hedder Michell og er 59 gammel
Jeg hedder Lene og er 61 gammel
Jeg hedder Mikkel og er 22 gammel
Jeg hedder Mathias og er 19 gammel
*/

JSON

Use the JSON object to serialize (stringify) an object into a string and deserialize (parse) from a string back to an object:

let toString = function () {
    console.log(
        `Jeg hedder ${this.navn} og er ${this.estimeretAlder()} gammel`
    );
};
let estimeretAlder = function () {
    return new Date().getFullYear() - this.fødselsår;
};
let personer = [
    {
        navn: "Michell",
        fødselsår: 1966,
        estimeretAlder: estimeretAlder,
        toString: toString,
    },
    {
        navn: "Lene",
        fødselsår: 1964,
        estimeretAlder: estimeretAlder,
        toString: toString,
    },
];
let json = JSON.stringify(personer);
console.log(json);
// [{"navn":"Michell","fødselsår":1966},{"navn":"Lene","fødselsår":1964}]

let personer2 = JSON.parse(json);
console.log(personer2); // objekt
console.log(personer2.length); // 2

JSON.stringify() and functions

Note that JSON.stringify() does not include functions when serializing objects. Only data properties (strings, numbers, booleans, arrays, objects) are included in the JSON output. This is why the estimeretAlder and toString methods are missing from the JSON string above.

If you need to preserve methods, you’ll need to reconstruct them after parsing:

    let personer2 = JSON.parse(json);
    // Add methods back after parsing
    personer2.forEach(person => {
        person.estimeretAlder = estimeretAlder;
        person.toString = toString;
    });

Destructuring

Destructuring is a convenient way to extract values from arrays or properties from objects into distinct variables. Introduced in ES6, it makes code cleaner and more readable.

Object Destructuring

Extract properties from objects:

// Traditional way
const person = { name: 'John', age: 30, city: 'Copenhagen' };
const name = person.name;
const age = person.age;

// Destructuring way
const { name, age, city } = person;
console.log(name);  // "John"
console.log(age);   // 30
console.log(city);  // "Copenhagen"

Renaming Variables:

const person = { name: 'Alice', age: 25 };
const { name: personName, age: personAge } = person;

console.log(personName);  // "Alice"
console.log(personAge);   // 25
// console.log(name);  // Error: name is not defined

Default Values:

const person = { name: 'Bob' };
const { name, age = 30, city = 'Unknown' } = person;

console.log(name);  // "Bob"
console.log(age);   // 30 (default)
console.log(city);  // "Unknown" (default)

Nested Destructuring:

const person = {
  name: 'Alice',
  address: {
    city: 'Copenhagen',
    country: 'Denmark'
  }
};

const { name, address: { city, country } } = person;
console.log(name);     // "Alice"
console.log(city);     // "Copenhagen"
console.log(country);  // "Denmark"

Rest Pattern with Objects:

const person = { name: 'Alice', age: 25, city: 'Copenhagen', job: 'Developer' };
const { name, age, ...otherInfo } = person;

console.log(name);       // "Alice"
console.log(age);        // 25
console.log(otherInfo);  // { city: "Copenhagen", job: "Developer" }

Destructuring Function Parameters

Destructuring is particularly useful with function parameters:

// Without destructuring
function displayPerson(person) {
  console.log(`${person.name} is ${person.age} years old`);
}

// With destructuring
function displayPerson({ name, age }) {
  console.log(`${name} is ${age} years old`);
}

const person = { name: 'Alice', age: 25, city: 'Copenhagen' };
displayPerson(person);  // "Alice is 25 years old"

// With default values
function displayPerson({ name, age, city = 'Unknown' }) {
  console.log(`${name}, ${age}, from ${city}`);
}

displayPerson({ name: 'Bob', age: 30 });  // "Bob, 30, from Unknown"

Practical Example: API Response

// Common use case: extracting data from API responses
const apiResponse = {
  status: 'success',
  data: {
    user: {
      id: 123,
      name: 'Alice Johnson',
      email: 'alice@example.com'
    },
    posts: [1, 2, 3]
  }
};

// Extract nested data cleanly
const {
  status,
  data: {
    user: { name, email },
    posts
  }
} = apiResponse;

console.log(status);  // "success"
console.log(name);    // "Alice Johnson"
console.log(email);   // "alice@example.com"
console.log(posts);   // [1, 2, 3]

When to Use Destructuring

Destructuring is great for:

  • Extracting multiple values at once
  • Function parameters (especially with options objects)
  • Working with API responses
  • Making code more readable and concise

However, don’t overuse it - deep nested destructuring can become hard to read.

Summary

Objects are versatile data structures in JavaScript that allow you to organize and manipulate related data and functionality.

Key Takeaways

Creating Objects:

  • Objects are hash tables with key-value pairs
  • Three ways to create: new Object(), {} (preferred), or with properties inline
  • Objects inherit methods like toString() from their prototype

Accessing Properties:

  • Bracket notation: obj["property"] - useful for dynamic property names
  • Dot notation: obj.property - cleaner and more common
  • Both notations can be mixed in the same code

Manipulating Objects:

  • Add properties: obj.newProperty = value
  • Remove properties: delete obj.property
  • Properties can be added or removed at any time
  • Property values can be any type: primitives, functions, objects, arrays

Iterating Objects:

  • Use for...in loop to iterate over all enumerable properties
  • Check property type with typeof obj[key]
  • Filter properties by type to process data vs. methods differently

Objects in Arrays:

  • Objects can be stored in arrays
  • Useful for collections of related items (users, products, etc.)
  • Iterate with regular loops or for...of
  • Methods can be shared between objects for consistency

JSON Serialization:

  • JSON.stringify() converts objects to JSON strings
  • JSON.parse() converts JSON strings back to objects
  • Functions are NOT included in JSON serialization
  • Only data properties are preserved (strings, numbers, booleans, arrays, objects)

Best Practices:

  • Prefer {} over new Object() for creating objects
  • Use dot notation when property names are known
  • Use bracket notation for dynamic property access
  • Remember that delete only removes the property, doesn’t set it to undefined
  • Be aware that JSON.stringify drops functions

Understanding objects is fundamental to JavaScript programming, as they are used everywhere - from simple data structures to complex application state management.


Assignment(s)