From bebf233b95c8899afc792f2ba39c545a9fb0e348 Mon Sep 17 00:00:00 2001 From: Frank Espinoza Date: Sun, 4 Aug 2024 01:11:48 +0930 Subject: [PATCH 1/2] Add new articles on `this` keyword, rest operator, and more Added comprehensive documentation for `this` keyword, rest operator, hoisting, and getters and setters in JavaScript. Updated the table of contents to include these new topics for better navigation and understanding. --- en/SUMMARY.md | 4 ++ en/functions/README.md | 6 +- en/functions/getters-setters.md | 105 +++++++++++++++++++++++++++ en/functions/hoisting.md | 64 +++++++++++++++++ en/functions/rest-operator.md | 75 +++++++++++++++++++ en/functions/this-keyword.md | 124 ++++++++++++++++++++++++++++++++ 6 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 en/functions/getters-setters.md create mode 100644 en/functions/hoisting.md create mode 100644 en/functions/rest-operator.md create mode 100644 en/functions/this-keyword.md diff --git a/en/SUMMARY.md b/en/SUMMARY.md index 9c23a927..e17cc7fa 100644 --- a/en/SUMMARY.md +++ b/en/SUMMARY.md @@ -53,6 +53,10 @@ - [Closures](functions/closures.md) - [Set Interval](functions/set-interval.md) - [Set Timeout](functions/set-timeout.md) + - [Rest Operator](functions/rest-operator.md) + - [This Keyword](functions/this-keyword.md) + - [Hoisting](functions/hoisting.md) + - [Getters and Setters](functions/getters-setters.md) - [Objects](objects/README.md) - [Properties](objects/properties.md) - [Mutable](objects/mutable.md) diff --git a/en/functions/README.md b/en/functions/README.md index dcb633c1..a781d453 100644 --- a/en/functions/README.md +++ b/en/functions/README.md @@ -51,4 +51,8 @@ In this chapter, we will explore following topics: * [High Order Functions](./higher-order.md) * [Recursive Functions](./recursive-functions.md) * [Set Interval](./set-interval.md) -* [Set Timeout](./set-timeout.md) \ No newline at end of file +* [Set Timeout](./set-timeout.md) +* [This Keyword](./this-keyword.md) +* [Rest Operator](./rest-operator.md) +* [Hoisting](./hoisting.md) +* [Getters and Setters](./getters-setters.md) \ No newline at end of file diff --git a/en/functions/getters-setters.md b/en/functions/getters-setters.md new file mode 100644 index 00000000..747b1799 --- /dev/null +++ b/en/functions/getters-setters.md @@ -0,0 +1,105 @@ +--- +chapter: 8 +description: Understanding Getters and Setters in JavaScript. +--- + +## Understanding Getters and Setters in JavaScript + +Getters and setters in JavaScript are special methods that provide a way to access and update the properties of an object. They allow you to control how a property is accessed and modified, adding a layer of abstraction and encapsulation. + +### What are Getters and Setters? + +- **Getters**: Methods that get the value of a specific property. +- **Setters**: Methods that set the value of a specific property. + +### Defining Getters and Setters + +You can define getters and setters using the `get` and `set` keywords within an object literal or a class. + +### Example with Object Literals + +Here's an example of defining getters and setters in an object literal: + +```javascript +let person = { + firstName: "John", + lastName: "Doe", + get fullName() { + return `${this.firstName} ${this.lastName}`; + }, + set fullName(name) { + [this.firstName, this.lastName] = name.split(" "); + } +}; + +console.log(person.fullName); // Output: John Doe +person.fullName = "Jane Smith"; +console.log(person.firstName); // Output: Jane +console.log(person.lastName); // Output: Smith +``` + +### Example with Classes + +Here's an example of defining getters and setters in a class: + +```javascript +class Person { + constructor(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + get fullName() { + return `${this.firstName} ${this.lastName}`; + } + + set fullName(name) { + [this.firstName, this.lastName] = name.split(" "); + } +} + +let person = new Person("John", "Doe"); +console.log(person.fullName); // Output: John Doe +person.fullName = "Jane Smith"; +console.log(person.firstName); // Output: Jane +console.log(person.lastName); // Output: Smith +``` + +### Benefits of Using Getters and Setters + +1. **Encapsulation**: Control how properties are accessed and modified. +2. **Validation**: Add validation logic when setting a property. +3. **Computed Properties**: Create properties that are computed based on other properties. + +### Example of Validation + +Here's an example of adding validation logic in a setter: + +```javascript +class User { + constructor(username) { + this._username = username; + } + + get username() { + return this._username; + } + + set username(name) { + if (name.length < 3) { + console.error("Username must be at least 3 characters long."); + } else { + this._username = name; + } + } +} + +let user = new User("jsmith"); +console.log(user.username); // Output: jsmith +user.username = "jo"; // Output: Username must be at least 3 characters long. +console.log(user.username); // Output: jsmith +``` + +### Conclusion + +Getters and setters provide a powerful way to manage object properties in JavaScript. By using them, you can add validation, encapsulation, and computed properties, making your code more robust and maintainable. diff --git a/en/functions/hoisting.md b/en/functions/hoisting.md new file mode 100644 index 00000000..9d27e257 --- /dev/null +++ b/en/functions/hoisting.md @@ -0,0 +1,64 @@ +--- +chapter: 8 +description: Understanding Hoisting for Functions in JavaScript. +--- + +## Understanding Hoisting for Functions in JavaScript + +Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their containing scope during the compile phase. This means that you can use functions and variables before they are declared in the code. + +### Function Hoisting + +In JavaScript, function declarations are hoisted to the top of their containing scope. This allows you to call a function before it is defined in the code. + +### Example of Function Hoisting + +Here's an example to illustrate function hoisting: + +```javascript +console.log(greet()); // Output: Hello, World! + +function greet() { + return "Hello, World!"; +} +``` + +In this example, the `greet` function is called before it is defined, but it works because the function declaration is hoisted to the top of the scope. + +### Function Expressions and Hoisting + +Unlike function declarations, function expressions are not hoisted. This means that you cannot call a function expression before it is defined. + +### Example of Function Expression + +Here's an example to illustrate the difference: + +```javascript +console.log(greet()); // Output: TypeError: greet is not a function + +var greet = function() { + return "Hello, World!"; +}; +``` + +In this example, the `greet` function is defined as a function expression, and calling it before the definition results in an error because the variable `greet` is hoisted, but its assignment is not. + +### Hoisting with `let` and `const` + +Variables declared with `let` and `const` are also hoisted, but they are not initialized. This means that accessing them before their declaration results in a `ReferenceError`. + +### Example with `let` and `const` + +```javascript +console.log(greet); // Output: ReferenceError: Cannot access 'greet' before initialization + +let greet = function() { + return "Hello, World!"; +}; +``` + +In this example, the `greet` variable is hoisted, but it is not initialized, resulting in a `ReferenceError` when accessed before its declaration. + +### Conclusion + +Understanding hoisting is crucial for writing predictable and bug-free JavaScript code. Function declarations are hoisted, allowing them to be called before they are defined, while function expressions are not hoisted, leading to potential errors if called before their definition. Variables declared with `let` and `const` are hoisted but not initialized, resulting in `ReferenceError` if accessed before their declaration. diff --git a/en/functions/rest-operator.md b/en/functions/rest-operator.md new file mode 100644 index 00000000..d61cc690 --- /dev/null +++ b/en/functions/rest-operator.md @@ -0,0 +1,75 @@ +--- +chapter: 8 +description: Understanding the Rest Operator for Functions in JavaScript. +--- + +## Understanding the Rest Operator for Functions in JavaScript + +The rest operator (`...`) in JavaScript allows you to represent an indefinite number of arguments as an array. It is particularly useful in function definitions to handle multiple parameters without explicitly specifying them. + +### Syntax + +The rest operator is used by prefixing three dots (`...`) before the parameter name in a function definition. + +### Example of Using the Rest Operator + +Here's a basic example of using the rest operator in a function: + +```javascript +function sum(...numbers) { + return numbers.reduce((acc, curr) => acc + curr, 0); +} + +console.log(sum(1, 2, 3)); // Output: 6 +console.log(sum(4, 5, 6, 7)); // Output: 22 +``` + +In this example, the `sum` function can accept any number of arguments, which are then combined into an array called `numbers`. + +### Combining Rest Operator with Other Parameters + +You can use the rest operator in combination with other parameters, but it must be the last parameter in the function definition. + +```javascript +function greet(greeting, ...names) { + return `${greeting}, ${names.join(" and ")}!`; +} + +console.log(greet("Hello", "Alice", "Bob")); // Output: Hello, Alice and Bob! +console.log(greet("Hi", "Charlie", "Dave", "Eve")); // Output: Hi, Charlie and Dave and Eve! +``` + +In this example, the `greet` function takes a fixed `greeting` parameter and a variable number of `names`. + +### Rest Operator in Arrow Functions + +The rest operator can also be used in arrow functions: + +```javascript +const multiply = (...numbers) => numbers.reduce((acc, curr) => acc * curr, 1); + +console.log(multiply(2, 3)); // Output: 6 +console.log(multiply(4, 5, 6)); // Output: 120 +``` + +### Practical Use Cases + +1. **Handling Variable Arguments**: Functions that need to handle a variable number of arguments, such as mathematical operations or string manipulations. +2. **Combining Arrays**: Functions that need to combine multiple arrays into one. +3. **Event Handlers**: Functions that handle events with varying numbers of arguments. + +### Example of Combining Arrays + +Here's an example of using the rest operator to combine arrays: + +```javascript +function combineArrays(...arrays) { + return arrays.flat(); +} + +console.log(combineArrays([1, 2], [3, 4], [5, 6])); // Output: [1, 2, 3, 4, 5, 6] +``` + +### Conclusion + +The rest operator is a powerful feature in JavaScript that allows functions to handle an indefinite number of arguments efficiently. By using the rest operator, you can write more flexible and concise functions that can adapt to various input scenarios. diff --git a/en/functions/this-keyword.md b/en/functions/this-keyword.md new file mode 100644 index 00000000..012d9ed2 --- /dev/null +++ b/en/functions/this-keyword.md @@ -0,0 +1,124 @@ +--- +chapter: 8 +description: Understanding the `this` Keyword in JavaScript. +--- + +## Understanding the `this` Keyword in JavaScript + +The `this` keyword in JavaScript refers to the object it belongs to. It has different values depending on where it is used: in a method, alone, in a function, in an event, etc. + +### `this` in Global Context + +In the global execution context (outside of any function), `this` refers to the global object, which is `window` in browsers. + +```javascript +console.log(this); // Output: Window {...} +``` + +### `this` in Object Methods + +When used in an object method, `this` refers to the object the method belongs to. + +```javascript +const person = { + firstName: "John", + lastName: "Doe", + fullName: function() { + return `${this.firstName} ${this.lastName}`; + } +}; + +console.log(person.fullName()); // Output: John Doe +``` + +### `this` in Constructor Functions + +In a constructor function, `this` refers to the newly created instance. + +```javascript +function Person(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; +} + +const person1 = new Person("Jane", "Smith"); +console.log(person1.firstName); // Output: Jane +``` + +### `this` in Arrow Functions + +Arrow functions do not have their own `this`. Instead, `this` is lexically inherited from the outer function where the arrow function is defined. + +```javascript +const person = { + firstName: "John", + lastName: "Doe", + fullName: function() { + const getFullName = () => `${this.firstName} ${this.lastName}`; + return getFullName(); + } +}; + +console.log(person.fullName()); // Output: John Doe +``` + +### `this` in Event Handlers + +In event handlers, `this` refers to the element that received the event. + +```html + + +``` + +### Changing `this` with `call`, `apply`, and `bind` + +You can explicitly set the value of `this` using `call`, `apply`, and `bind`. + +#### `call` Method + +The `call` method calls a function with a given `this` value and arguments provided individually. + +```javascript +function greet() { + console.log(`Hello, ${this.name}`); +} + +const person = { name: "Alice" }; +greet.call(person); // Output: Hello, Alice +``` + +#### `apply` Method + +The `apply` method calls a function with a given `this` value and arguments provided as an array. + +```javascript +function greet(greeting) { + console.log(`${greeting}, ${this.name}`); +} + +const person = { name: "Bob" }; +greet.apply(person, ["Hi"]); // Output: Hi, Bob +``` + +#### `bind` Method + +The `bind` method creates a new function that, when called, has its `this` keyword set to the provided value. + +```javascript +function greet() { + console.log(`Hello, ${this.name}`); +} + +const person = { name: "Charlie" }; +const greetPerson = greet.bind(person); +greetPerson(); // Output: Hello, Charlie +``` + +### Conclusion + +Understanding the `this` keyword is crucial for writing effective JavaScript code. Its value depends on the context in which it is used, and it can be explicitly set using `call`, `apply`, and `bind`. \ No newline at end of file From 5cb28b10f1408d1b97c7be09e79328ed9bf85b02 Mon Sep 17 00:00:00 2001 From: Frank Espinoza Date: Fri, 9 Aug 2024 17:47:44 +0930 Subject: [PATCH 2/2] Add chapters on factory and constructor functions and dynamic objects This commit introduces new documentation sections explaining factory functions, constructor functions, the constructor property, and the dynamic nature of objects in JavaScript. These additions aim to enhance understanding of object creation and manipulation in JavaScript. --- en/SUMMARY.md | 4 + en/objects/constructor-functions.md | 95 ++++++++++++++++++++++ en/objects/constructor-property.md | 67 ++++++++++++++++ en/objects/dynamic-nature.md | 117 ++++++++++++++++++++++++++++ en/objects/factory-functions.md | 106 +++++++++++++++++++++++++ 5 files changed, 389 insertions(+) create mode 100644 en/objects/constructor-functions.md create mode 100644 en/objects/constructor-property.md create mode 100644 en/objects/dynamic-nature.md create mode 100644 en/objects/factory-functions.md diff --git a/en/SUMMARY.md b/en/SUMMARY.md index e17cc7fa..a3c47a93 100644 --- a/en/SUMMARY.md +++ b/en/SUMMARY.md @@ -64,6 +64,10 @@ - [Prototype](objects/prototype.md) - [Delete Operator](objects/delete.md) - [Enumeration](objects/enumeration.md) + - [Factory Functions](objects/factory-functions.md) + - [Constructor Functions](objects/constructor-functions.md) + - [Constructor Property](objects/constructor-property.md) + - [Dynamic Nature](objects/dynamic-nature.md) - [Date and Time](date-and-time.md) - [JSON](json.md) - [Error Handling](error-handling/README.md) diff --git a/en/objects/constructor-functions.md b/en/objects/constructor-functions.md new file mode 100644 index 00000000..1cdf4083 --- /dev/null +++ b/en/objects/constructor-functions.md @@ -0,0 +1,95 @@ +--- +chapter: 9 +description: Understanding Constructor Functions in JavaScript. +--- + +## Understanding Constructor Functions in JavaScript + +Constructor functions in JavaScript are special functions used to create and initialize objects. They provide a way to define a blueprint for creating multiple objects with similar properties and methods. + +### Defining a Constructor Function + +A constructor function is defined like a regular function but is typically named with an initial capital letter to distinguish it from regular functions. + +### Example of a Constructor Function + +Here's a basic example of a constructor function: + +```javascript +function Person(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; +} + +const person1 = new Person("John", "Doe"); +const person2 = new Person("Jane", "Smith"); + +console.log(person1.firstName); // Output: John +console.log(person2.lastName); // Output: Smith +``` + +In this example, the `Person` constructor function initializes the `firstName` and `lastName` properties for each new object created. + +### Adding Methods to Constructor Functions + +You can add methods to the objects created by a constructor function by defining them on the constructor's prototype. + +```javascript +function Person(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; +} + +Person.prototype.getFullName = function() { + return `${this.firstName} ${this.lastName}`; +}; + +const person1 = new Person("John", "Doe"); +console.log(person1.getFullName()); // Output: John Doe +``` + +### Using `new` Keyword + +The `new` keyword is used to create an instance of an object from a constructor function. It performs the following steps: +1. Creates a new empty object. +2. Sets the `this` keyword to the new object. +3. Executes the constructor function. +4. Returns the new object. + +### Example with `new` Keyword + +```javascript +function Car(make, model) { + this.make = make; + this.model = model; +} + +const car1 = new Car("Toyota", "Corolla"); +console.log(car1.make); // Output: Toyota +``` + +### Constructor Functions vs. Classes + +ES6 introduced the `class` syntax, which provides a more concise and readable way to define constructor functions and methods. + +### Example with Classes + +```javascript +class Person { + constructor(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + getFullName() { + return `${this.firstName} ${this.lastName}`; + } +} + +const person1 = new Person("John", "Doe"); +console.log(person1.getFullName()); // Output: John Doe +``` + +### Conclusion + +Constructor functions are a fundamental feature in JavaScript for creating and initializing objects. They allow you to define a blueprint for objects and add methods to their prototype. With the introduction of ES6, the `class` syntax provides a more modern and readable way to achieve the same functionality. diff --git a/en/objects/constructor-property.md b/en/objects/constructor-property.md new file mode 100644 index 00000000..4f57b15d --- /dev/null +++ b/en/objects/constructor-property.md @@ -0,0 +1,67 @@ +--- +chapter: 9 +description: Understanding the `constructor` Property in JavaScript. +--- + +## Understanding the `constructor` Property in JavaScript + +The `constructor` property in JavaScript is a reference to the function that created an instance's prototype. It is a property of all objects that points to the function that was used to create the object. + +### What is the `constructor` Property? + +The `constructor` property returns a reference to the constructor function that created the instance. This is useful for identifying the type of an object. + +### Example of the `constructor` Property + +Here's a basic example to illustrate the `constructor` property: + +```javascript +function Person(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; +} + +const person1 = new Person("John", "Doe"); +console.log(person1.constructor); // Output: [Function: Person] +``` + +In this example, the `constructor` property of `person1` points to the `Person` function. + +### Using the `constructor` Property to Create New Instances + +You can use the `constructor` property to create new instances of the same type: + +```javascript +const person2 = new person1.constructor("Jane", "Smith"); +console.log(person2.firstName); // Output: Jane +``` + +### `constructor` Property in Built-in Objects + +The `constructor` property is also available in built-in JavaScript objects: + +```javascript +const arr = []; +console.log(arr.constructor); // Output: [Function: Array] + +const obj = {}; +console.log(obj.constructor); // Output: [Function: Object] +``` + +### Modifying the `constructor` Property + +You can modify the `constructor` property, but it is generally not recommended as it can lead to unexpected behavior: + +```javascript +function Animal(name) { + this.name = name; +} + +const dog = new Animal("Rex"); +dog.constructor = Person; +console.log(dog.constructor); // Output: [Function: Person] +``` + +### Conclusion + +The `constructor` property is a useful feature in JavaScript that allows you to reference the function that created an instance's prototype. It can be used to identify the type of an object and create new instances of the same type. However, modifying the `constructor` property should be done with caution. \ No newline at end of file diff --git a/en/objects/dynamic-nature.md b/en/objects/dynamic-nature.md new file mode 100644 index 00000000..2a95c0b5 --- /dev/null +++ b/en/objects/dynamic-nature.md @@ -0,0 +1,117 @@ +--- +chapter: 9 +description: Understanding the Dynamic Nature of Objects in JavaScript. +--- + +## Understanding the Dynamic Nature of Objects in JavaScript + +JavaScript objects are dynamic, meaning their properties can be added, modified, or deleted at runtime. This flexibility +allows for powerful and adaptable code but requires careful management to avoid unexpected behavior. + +### Adding Properties + +You can add properties to an object at any time using dot notation or bracket notation. + +```javascript +const person = { + firstName: "John", + lastName: "Doe" +}; + +// Adding a new property +person.age = 30; +console.log( person.age ); // Output: 30 + +// Adding a property using bracket notation +person["gender"] = "male"; +console.log( person.gender ); // Output: male +``` + +### Modifying Properties + +Existing properties can be modified by reassigning their values. + +```javascript +const car = { + make: "Toyota", + model: "Corolla" +}; + +// Modifying a property +car.model = "Camry"; +console.log( car.model ); // Output: Camry +``` + +### Deleting Properties + +Properties can be removed from an object using the `delete` operator. + +```javascript +const book = { + title: "1984", + author: "George Orwell", + year: 1949 +}; + +// Deleting a property +delete book.year; +console.log( book.year ); // Output: undefined +``` + +### Checking for Properties + +You can check if an object has a specific property using the `in` operator or the `hasOwnProperty` method. + +```javascript +const user = { + username: "johndoe", + email: "john@example.com" +}; + +// Using the `in` operator +console.log( "email" in user ); // Output: true + +// Using `hasOwnProperty` method +console.log( user.hasOwnProperty( "username" ) ); // Output: true +``` + +### Iterating Over Properties + +You can iterate over an object's properties using a `for...in` loop. + +```javascript +const student = { + name: "Alice", + age: 22, + major: "Computer Science" +}; + +for (let key in student) { + if (student.hasOwnProperty( key )) { + console.log( `${key}: ${student[key]}` ); + } +} +// Output: +// name: Alice +// age: 22 +// major: Computer Science +``` + +### Dynamic Property Names + +You can use dynamic property names by using computed property names in object literals. + +```javascript +const propName = "score"; +const game = { + [propName]: 100 +}; + +console.log( game.score ); // Output: 100 +``` + +### Conclusion + +The dynamic nature of JavaScript objects provides great flexibility in managing data structures. You can add, modify, +and delete properties at runtime, check for the existence of properties, and iterate over them. This flexibility, while +powerful, requires careful handling to maintain code stability and predictability. \ No newline at end of file diff --git a/en/objects/factory-functions.md b/en/objects/factory-functions.md new file mode 100644 index 00000000..10721ca1 --- /dev/null +++ b/en/objects/factory-functions.md @@ -0,0 +1,106 @@ +--- +chapter: 9 +description: Understanding Factory Functions for Objects in JavaScript. +--- + +## Understanding Factory Functions for Objects in JavaScript + +Factory functions are functions that create and return objects. They provide a flexible way to create multiple instances of objects without using the `new` keyword or constructor functions. + +### Defining a Factory Function + +A factory function is a regular function that returns an object. It can include parameters to customize the properties of the created object. + +### Example of a Factory Function + +Here's a basic example of a factory function: + +```javascript +function createPerson(firstName, lastName) { + return { + firstName: firstName, + lastName: lastName, + getFullName: function() { + return `${this.firstName} ${this.lastName}`; + } + }; +} + +const person1 = createPerson("John", "Doe"); +const person2 = createPerson("Jane", "Smith"); + +console.log(person1.getFullName()); // Output: John Doe +console.log(person2.getFullName()); // Output: Jane Smith +``` + +In this example, the `createPerson` function returns a new object with `firstName`, `lastName`, and `getFullName` properties. + +### Advantages of Factory Functions + +1. **No `new` Keyword**: Factory functions do not require the `new` keyword, making them simpler and less error-prone. +2. **Encapsulation**: Factory functions can encapsulate private variables and methods. +3. **Flexibility**: They can return different types of objects based on conditions. + +### Encapsulation with Factory Functions + +Factory functions can encapsulate private data by defining variables inside the function scope and returning an object with methods that access those variables. + +```javascript +function createCounter() { + let count = 0; + return { + increment: function() { + count++; + return count; + }, + decrement: function() { + count--; + return count; + }, + getCount: function() { + return count; + } + }; +} + +const counter = createCounter(); +console.log(counter.increment()); // Output: 1 +console.log(counter.getCount()); // Output: 1 +console.log(counter.decrement()); // Output: 0 +``` + +### Returning Different Objects + +Factory functions can return different objects based on conditions, providing flexibility in object creation. + +```javascript +function createShape(type) { + if (type === "circle") { + return { + type: "circle", + radius: 10, + getArea: function() { + return Math.PI * this.radius * this.radius; + } + }; + } else if (type === "square") { + return { + type: "square", + side: 10, + getArea: function() { + return this.side * this.side; + } + }; + } +} + +const circle = createShape("circle"); +const square = createShape("square"); + +console.log(circle.getArea()); // Output: 314.1592653589793 +console.log(square.getArea()); // Output: 100 +``` + +### Conclusion + +Factory functions are a powerful and flexible way to create objects in JavaScript. They provide advantages such as avoiding the `new` keyword, encapsulating private data, and returning different types of objects based on conditions. By using factory functions, you can write more modular and maintainable code.