Elegant and efficient JavaScript – Classes and modularity


Blogger: The kitten is here
The core of the article: Elegant and efficient JavaScript – Class and modularity

Article directory

  • introduction
  • The concept and usage of Class
    • Definition of Class
    • Class inheritance
    • Class static methods and properties
  • The concept and usage of modularity
    • Export and import of modules
    • Default and named exports for modules
    • Module circular dependency problem
  • Combination application of Class and modularity
    • Implement a simple calculator using classes and modularity
    • Implement a simple shopping cart using Class and modularity
  • Summarize

Introduction

In the past, JavaScript was a prototype-based object-oriented programming language without the concepts of Class and modularity. This leads to a disorganized code structure that is difficult to maintain and extend. ES6 introduces the concepts of Class and modularity, making JavaScript more object-oriented and equipped with a modular organizational structure. This article will introduce the concept and usage of Class and modularity, and demonstrate its application through sample code.

Concept and usage of Class

Definition of Class

Class is a template or blueprint for creating objects. Through Class, we can define the properties and methods of objects and create specific objects through instantiation.

Sample code:

class Person {<!-- -->
  constructor(name, age) {<!-- -->
    this.name = name;
    this.age = age;
  }
  
  sayHello() {<!-- -->
    console.log(`Hello, my name is ${<!-- -->this.name}.`);
  }
}

const person = new Person("John", 25);
person.sayHello(); // Output: Hello, my name is John.

In the above example, we have defined a Class called Person, which has two properties name and age, and a method sayHello. Use the new keyword to create an instance of Person and call its methods.

Class inheritance

Class supports inheritance. Subclasses can inherit the properties and methods of the parent class and can override or extend them.

Sample code:

class Animal {<!-- -->
  constructor(name) {<!-- -->
    this.name = name;
  }
  
  speak() {<!-- -->
    console.log(`${<!-- -->this.name} makes a sound.`);
  }
}

class Dog extends Animal {<!-- -->
  speak() {<!-- -->
    console.log(`${<!-- -->this.name} barks.`);
  }
}

const dog = new Dog("Bobby");
dog.speak(); // Output: Bobby barks.

In the above example, we defined a parent class of Animal and a subclass of Dog. The subclass Dog inherits the properties and methods of the parent class Animal and overrides the speak method. By creating an instance of Dog we can call methods of the subclass.

Static methods and properties of Class

Class also supports static methods and properties, which can be called directly through the class name without creating an instance.

Sample code:

class MathUtils {<!-- -->
  static add(a, b) {<!-- -->
    return a + b;
  }
  
  static PI = 3.14159;
}

console.log(MathUtils.add(1, 2)); // Output: 3
console.log(MathUtils.PI); // Output: 3.14159

In the above example, we defined a MathUtils class, which has a static method add and a static property PI. We can call these static methods and properties directly through the class name without creating an instance.

The concept and usage of modularity

Export and import of modules

Modularization is a way of splitting code into independent modules and sharing and using these modules through exports and imports. ES6 introduces a modular syntax that allows JavaScript to better organize and manage code.

Sample code:
In a module called utils.js, we export two functions add and subtract:

export function add(a, b) {<!-- -->
  return a + b;
}

export function subtract(a, b) {<!-- -->
  return a - b;
}

In another file, we import these functions via the import keyword and use them:

import {<!-- --> add, subtract } from './utils.js';

console.log(add(1, 2)); // Output: 3
console.log(subtract(3, 2)); // Output: 1

In the above example, we exported the add and subtract functions as part of the utils.js module and imported and used them in another file via the import keyword.

Default and named exports of modules

In addition to exporting multiple functions or variables, we can also export a default function or variable through default export.

Sample code:
In a module called utils.js, we export a function multiply by default:

export default function multiply(a, b) {<!-- -->
  return a * b;
}

In another file, we import the default exported function via the import keyword and use it:

import multiply from './utils.js';

console.log(multiply(2, 3)); // Output: 6

In the above example, we exported the multiply function as part of the utils.js module by default and imported and used it in another file via the import keyword.

Circular dependency problem of modules

Circular dependencies are a common problem in modular code. Circular dependency refers to the mutual dependence between two or more modules, forming a circular dependency relationship.

Sample code:
In a module named moduleA.js, we import the module moduleB.js and use its functions:

import {<!-- --> foo } from './moduleB.js';

export function bar() {<!-- -->
  console.log(foo());
}

In another file moduleB.js, we import the moduleA.js module and use its functions:

import {<!-- --> bar } from './moduleA.js';

export function foo() {<!-- -->
  return 'Hello from moduleB.js';
}

bar();

In the above example, moduleA.js imports the foo function of moduleB.js, and moduleB.js imports the bar function of moduleA.js. This creates a circular dependency that prevents the code from executing correctly.

To solve the problem of circular dependencies, we can change the dependency to be one-way, or use other solutions such as importing at the top of the module.

Combination application of Class and modularity

Use Class and modularity to implement a simple calculator

// calculator.js
export class Calculator {<!-- -->
  add(a, b) {<!-- -->
    return a + b;
  }
  
  subtract(a, b) {<!-- -->
    return a - b;
  }
}

// main.js
import } from './calculator.js';

const calculator = new Calculator();
console.log(calculator.add(1, 2)); // Output: 3
console.log(calculator.subtract(3, 2)); // Output: 1

In the above example, we define a Calculator Class and export it. In another file, we use the methods in Calculator by importing it and creating an instance of it.

Use Class and modularity to implement a simple shopping cart

// product.js
export class Product {<!-- -->
  constructor(name, price) {<!-- -->
    this.name = name;
    this.price = price;
  }
}

// cart.js
export class Cart {<!-- -->
  constructor() {<!-- -->
    this.products = [];
  }
  
  addProduct(product) {<!-- -->
    this.products.push(product);
  }
  
  getTotalPrice() {<!-- -->
    return this.products.reduce((total, product) => total + product.price, 0);
  }
}

// main.js
import {<!-- --> Product } from './product.js';
import {<!-- --> Cart } from './cart.js';

const cart = new Cart();
const product1 = new Product("Apple", 1);
const product2 = new Product("Banana", 2);

cart.addProduct(product1);
cart.addProduct(product2);

console.log(cart.getTotalPrice()); // Output: 3

In the above example, we defined a Product Class and a Cart Class and exported them. In another file, we implement a simple shopping cart function by importing Product and Cart and creating instances of them.

Summary

ES6 introduces the concepts of Class and modularity, making JavaScript more object-oriented and equipped with a modular organizational structure. Class allows us to define and instantiate objects using an object-oriented approach, while modularization provides a way to organize and manage code. Through Class and modularization, we can better organize and manage code and improve the maintainability and scalability of code. In actual development, we can use Class and modularity to implement various functions, such as calculators, shopping carts, etc.