Back to JavaScript
2026-01-236 min read

Structs (JavaScript)

Learn Structs (JavaScript) step by step with clear examples and exercises.

Title: Mastering JavaScript Structs - A full guide to Custom Data Structures

Why This Matters

JavaScript structs, also known as custom objects, are fundamental for managing data effectively and enhancing code readability. By understanding how to create and manipulate them proficiently, you can write cleaner, more efficient code, particularly when dealing with complex applications or large datasets. In this lesson, we'll delve into the world of JavaScript structs, covering their creation, manipulation, and common best practices for using them in your projects.

Prerequisites

Before jumping into JavaScript structs, ensure you have a solid foundation in the following concepts:

  • Understanding variables and data types in JavaScript
  • Familiarity with object literals and properties
  • Comfort with functions and methods
  • Knowledge of loops (for loops and for-of loops)
  • Understanding the this keyword and its behavior in JavaScript
  • Familiarity with arrow functions and their limitations

Additional Prerequisites

  • Understanding prototypes, inheritance, and the new operator in JavaScript
  • Knowledge of ES6 classes (optional but recommended)

Core Concept

In JavaScript, a struct is essentially an object that contains properties with specific names. Unlike built-in objects like Array or Date, custom objects don't have predefined methods or behaviors. However, you can add your own methods to make them more powerful and user-friendly.

A struct can be created using an object literal, a constructor function, or an ES6 class. Here's an example of a simple struct using an object literal:

const Person = {
name: '',
age: 0,
greet() {
console.log(`Hello! I am ${this.name}.`);
}
};

In this example, we've created a Person struct with two properties (name and age) and one method (greet). The greet method employs the this keyword to access the current object's properties.

Using a Constructor Function

To create a constructor function, you can define a function that returns an object with specific properties and methods:

function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log(`Hello! I am ${this.name}.`);
}
}

Now you can create instances of the Person struct using the constructor function:

const john = new Person('John', 30);
john.greet(); // Output: Hello! I am John.

Using ES6 Classes

ES6 classes provide a more concise syntax for creating objects with properties and methods:

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello! I am ${this.name}.`);
}
}

You can create instances of the Person struct using an ES6 class in a similar manner:

const jane = new Person('Jane', 28);
jane.greet(); // Output: Hello! I am Jane.

Worked Example

Let's create a more intricate struct representing a book, including methods for common operations:

function Book(title, author) {
this.title = title;
this.author = author;
this.pages = 0;
this.chapters = [];

this.setTitle = function(title) {
this.title = title;
};

this.setAuthor = function(author) {
this.author = author;
};

this.addChapter = function(chapter) {
this.chapters.push(chapter);
};

this.getChapters = function() {
return this.chapters;
}
}

In this example, we've crafted a Book struct with four properties (title, author, pages, and chapters) and four methods (setTitle, setAuthor, addChapter, and getChapters). The setTitle and setAuthor methods update the corresponding properties, while the addChapter method appends a new chapter to the chapters array. The getChapters method returns the current chapters.

Now let's create an instance of the Book struct and execute some operations:

const myBook = new Book('The Catcher in the Rye', 'J.D. Salinger');
myBook.addChapter('Chapter 1');
myBook.addChapter('Chapter 2');
console.log(myBook.getChapters()); // Output: [ 'Chapter 1', 'Chapter 2' ]

Additional Worked Example: Inheritance

function Book(title, author) {
this.title = title;
this.author = author;
this.pages = 0;
this.chapters = [];
}

function Novel extends Book {
constructor(title, author, genre) {
super(title, author);
this.genre = genre;
}

setGenre() {
this.genre = genre;
}
}

const myNovel = new Novel('Pride and Prejudice', 'Jane Austen', 'Romance');
console.log(myNovel.genre); // Output: 'Romance'

In this example, we've created a Novel struct that inherits from the Book struct and adds a setGenre method. We then create an instance of the Novel struct and set its genre.

Common Mistakes

  1. Neglecting to bind the this keyword when defining methods as arrow functions:
const Book = {
// ... (other properties and methods)

greet() {
console.log(`Hello! I am ${this.name}.`);
}
};

// Incorrect usage:
const myBook = Object.create(Book);
myBook.name = 'John';
myBook.greet(); // Uncaught ReferenceError: this is not defined

To rectify this issue, you can use a regular function and bind the this keyword explicitly or employ an arrow function with Function.prototype.call or Function.prototype.apply:

const Book = {
// ... (other properties and methods)

greet() {
console.log(`Hello! I am ${this.name}.`);
}
};

// Correct usage with bind:
const myBook = Object.create(Book);
myBook.name = 'John';
myBook.greet.bind(myBook)(); // Output: Hello! I am John.
  1. Forgetting to return values from methods:
const Book = {
// ... (other properties and methods)

getChapters() {
console.log(this.chapters);
}
};

// Incorrect usage:
const myBook = Object.create(Book);
myBook.getChapters(); // Outputs: [ undefined ]

To address this issue, ensure to return the value from the method:

const Book = {
// ... (other properties and methods)

getChapters() {
return this.chapters;
}
};

// Correct usage:
const myBook = Object.create(Book);
console.log(myBook.getChapters()); // Outputs: [ undefined ]

Additional Common Mistakes

  1. Forgetting to handle undefined or null values when accessing properties:
const Book = {
title: 'The Catcher in the Rye',
author: null,
getAuthor() {
console.log(this.author);
}
};

// Incorrect usage:
Book.getAuthor(); // Outputs: null

To handle this situation, you can use the optional chaining operator (?.) or a ternary expression to check for null or undefined values before accessing properties:

const Book = {
title: 'The Catcher in the Rye',
author: null,
getAuthor() {
console.log(this.author?.toString() || 'Unknown');
}
};

// Correct usage:
Book.getAuthor(); // Outputs: Unknown

Practice Questions

  1. Create a Student struct with properties for name, age, and GPA. Include methods to calculate the student's tuition fee (based on age and GPA), print their details, and check if they are eligible for financial aid.
  2. Create a Car struct with properties for make, model, year, color, and horsepower. Include methods to start the engine, accelerate, brake, and display vehicle information.
  3. Implement a LinkedList struct using custom objects to create a doubly-linked list data structure. Include methods to add, remove, and traverse nodes in the list.
  4. Create a TreeNode struct for binary trees, including methods to insert a new node, find a node by value, and perform an in-order traversal of the tree.

FAQ

  1. Why not use built-in objects like Array or Map for data structures?
  • While built-in objects can be used for certain data structures, custom objects offer more flexibility and allow you to define your own methods and properties that are tailored to your specific needs.
  1. How can I iterate over the properties of a custom object?
  • You can use a for...in loop or the Object.keys(), Object.values(), or Object.entries() methods to iterate over the properties of a custom object.
  1. Can I extend an existing object with new properties and methods?
  • Yes, you can use the Object.assign() method to merge two objects, or you can create a new constructor function that extends an existing one using the extends keyword (ES6 syntax).
  1. What is the difference between creating a custom object with a constructor function and using an object literal?
  • A constructor function creates an object with a specific prototype, allowing for inheritance and method sharing among instances. An object literal simply initializes an object with properties and methods defined within its scope. Using a constructor function offers more organization and reusability when dealing with multiple objects of the same type.
  1. What is the purpose of the this keyword in JavaScript?
  • The this keyword refers to the object that a method or property belongs to, providing access to its properties and methods within the context of the function. In JavaScript, the value of this can change depending on how the function is called.
Structs (JavaScript) | JavaScript | XQA Learn