Chapter 5: Advanced JavaScript Concepts
Tags: javascript
Published: 2023-05-30 12:57:40

## Prototypes and Inheritance

JavaScript is often described as a prototype-based language, which means that it doesn't have classical inheritance based on classes as seen in other languages like Java or C++. Instead, JavaScript uses prototypes to achieve object-oriented inheritance.

Each object in JavaScript has a private property called a prototype, which points to another object. When a property is accessed on an object, and the object does not have that property, JavaScript will traverse the prototype chain to find the property on one of the prototypes.

Here's an example of prototypes in action:


```javascript
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

Person.prototype.getFullName = function() {
  return this.firstName + " " + this.lastName;
}

let person = new Person("John", "Doe");
console.log(person.getFullName()); // Outputs: "John Doe"
```

In this example, the `getFullName` method is added to the prototype of the `Person` constructor function. All instances of `Person` can now use this method.

## Asynchronous JavaScript (Promises, async/await)

JavaScript is single-threaded, but it has features that allow it to handle tasks that take a long time to complete, such as fetching data from a server, without blocking the rest of the code from executing. This is achieved with async functions and the Promise object.

A Promise represents a value that is unknown now that may become known in the future. Promises can be in one of three states: pending, fulfilled, or rejected.


```javascript
let promise = new Promise(function(resolve, reject) {
  // some code

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  } else {
    reject(Error("It broke"));
  }
});

// We can chain a .then() call to our promise to specify what should happen when the promise is resolved:
promise.then(function(result) {
  console.log(result); // "Stuff worked!"
}, function(err) {
  console.log(err); // Error: "It broke"
});
```

`async` and `await` are extensions of promises, and they allow you to write promise-based code as if it were synchronous.


```javascript
async function getFullName() {
  try {
    let response = await fetch('/api/person');
    let person = await response.json();
    console.log(person.firstName + " " + person.lastName);
  } catch (error) {
    console.error('Error:', error);
  }
}

getFullName();
```

## Error Handling and Debugging

JavaScript provides several mechanisms for handling errors and debugging your code.

One such mechanism is the `try...catch` statement, which is used to handle exceptions (unusual or erroneous situations) that can be thrown by your program.


```javascript
try {
  // Code that may throw an exception
  throw new Error('Oops!');
} catch (error) {
  // Handle the error
  console.error(error.message); // Outputs: "Oops!"
}
```

JavaScript has built-in debugging capabilities that are usually accessed through developer tools in browsers. For example, the `console.log` function can be used to print values to the console, and the `debugger` statement can be used to set a breakpoint in your code.


```javascript
console.log('Hello, World!'); // Outputs: "Hello, World!"

function buggyFunction() {
  debugger; // Execution will stop here
  // Rest of the function
}
```

These tools and concepts are essential to understand and handle errors in your JavaScript code.