top of page

Advanced JavaScript - Episode 3

There's a saying: there are only things many people curse and things no one bothers to use. JavaScript is a prime example. It has some interesting points but also gives us headaches. Theory is easy to understand, but practice is a whole different issue. Therefore, let's dive into specific examples and analyze them to better understand JavaScript.

This series might be quite long, and I don't know how many episodes there will be, but to help those who haven't read my previous articles on JS, I will explain everything again in this series. I might also repeat the theories several times (depending on my mood) to ensure you grasp them well. Alright, let's get started... LET'S GO 🚀

If you have any questions, don't hesitate to comment below. Or just leave a comment to say hi, and that will give me more motivation to complete this series. Thank you very much. 🤗


JavaScript

1. Using Prototype

What is the output of the following code?

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = function() {
  return `${this.firstName} ${this.lastName}`;
};
console.log(member.getFullName());

Choices: A: TypeErrorB: SyntaxErrorC: Lydia HallieD: undefined undefined

Answer: A

1.1. Analyzing the Problem

Looking at the code above, you might think we're adding a getFullName method to the member object. But when you run the code, you encounter a TypeError.

1.2. Why Do We Get This Error?

When you add a method or property to a constructor function through Person.getFullName, you're actually adding it to the function object, not to its prototype. This means you cannot access the getFullName method from an instance of Person like member.

1.3. What is Prototype and Why Should We Use It?

JavaScript is a prototype-based language. Every object in JavaScript has a special property called prototype. The prototype is another object from which objects inherit properties and methods.

Example

Imagine you have an IT class with hundreds of students. You want to teach a new JavaScript technique to any student who wants to learn. Instead of teaching every single student, you can teach the teacher, and then the teacher can convey the knowledge to any student who needs it. Here, the teacher is the prototype, and the students are the instances. Not every instance/student needs to learn the new technique, but if a student needs it, they can just contact the teacher.

1.4. Fixing the Code

To fix the error, we should add the getFullName method to the prototype of Person:

Person.prototype.getFullName = function() {
  return `${this.firstName} ${this.lastName}`;
};

This way, each instance of Person can access and use the getFullName method. It means that each instance doesn't need to contain the getFullName method, but when needed, they can access it through the prototype.

This Solution Solves the Problem in Several Ways:

  • Memory Optimization: Not every Person instance needs this method. If you add it directly to the constructor, each instance will contain a copy of this method, leading to memory waste. Adding it to the prototype helps all instances share a single copy of the method.

  • Extendability: This also helps us easily extend and update methods for all instances without modifying each instance.

1.5. Conclusion

Understanding the prototype in JavaScript is very important. It helps us minimize memory usage when creating instances and manage our code more efficiently. Hopefully, this brief introduction has helped you understand the prototype better and know how to use it effectively.

2. The Mechanism of the new Keyword

What is the output of the following code?

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}
const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");
console.log(lydia);
console.log(sarah);

Choices: A: Person {firstName: "Lydia", lastName: "Hallie"} and undefinedB: Person {firstName: "Lydia", lastName: "Hallie"} and Person {firstName: "Sarah", lastName: "Smith"}C: Person {firstName: "Lydia", lastName: "Hallie"} and {}D: Person {firstName: "Lydia", lastName: "Hallie"} and ReferenceError

Answer: A

2.1. The new Keyword

First, we need to understand the new keyword in JavaScript. When creating a new instance from a function using new, the function becomes a constructor. At this point:

  • A new object is created.

  • this in the constructor function refers to that new object.

  • If the function does not return a value, it will return the new object.

const example = new Person("Example", "Person");

Here, example is an instance of Person and contains the properties firstName and lastName.

2.2. When Not Using new

If we call a function without using new, it behaves as a regular function. Here, this refers to the global object (in a browser, it's window). Therefore, when we call:

const sarah = Person("Sarah", "Smith");

We are actually defining window.firstName and window.lastName instead of creating a new variable sarah as expected.

2.3. Illustrative Example

To better understand, let's look at a more visual example:

Imagine JavaScript as a robot factory. When you use the new keyword, you're telling the factory to create a new robot with the name and functions you specify. But if you forget to use new, instead of creating a new robot, the factory will adjust the sample robot (here, the global object) according to your specifications.

2.4. Analyzing the Initial Code

Now, let's reconsider the initial code:

const lydia = new Person("Lydia", "Hallie");

Here, lydia is an object with firstName as "Lydia" and lastName as "Hallie".

But when we declare:

const sarah = Person("Sarah", "Smith");

We are not actually creating a new sarah object. Instead, we are modifying the global object (window if you're using a browser). As a result, sarah will not contain any values and will return undefined.

2.5. Conclusion

The correct answer to this question is A: Person {firstName: "Lydia", lastName: "Hallie"} and undefined.

A piece of advice: when you write a constructor function like Person and use it without the new keyword, you might encounter subtle bugs like the one above. To avoid this, always use the new keyword, or if you want to be more certain, you can write code checks within the constructor function.

3. Event Propagation

What are the three phases of event propagation?

Choices: A: Target > Capturing > BubblingB: Bubbling > Target > CapturingC: Target > Bubbling > CapturingD: Capturing > Target > Bubbling

Answer: D

3.1. Analyzing Event Propagation in JavaScript

First, you need to know that in JavaScript, when we interact with elements on the webpage (like clicking, pressing keys, etc.), an event is triggered. Interestingly, this event doesn't just affect the element we interact with but also affects many other elements on the page. This is called "Event Propagation." So how does this mechanism work? Let's explain it through its three phases.

3.2. Capturing Phase

This is the first phase in the event propagation process. When an event is triggered, it first propagates from the Window - the browser window, down to the exact element you interacted with (called the target element).

Suppose you have a simple HTML structure like this:

<div id="parent">
  <div id="child">
    <div id="grandchild"></div>
  </div>
</div>

If you click on the element with id child, the click event will propagate from the Window, through the parent element, and finally to the child.

3.3. Target Phase

When the event reaches the target element (in the example above, the child element), it will execute the event handling functions at this point.

3.4. Bubbling Phase

After the event handling at the target element is done, the event will "bubble" through the parent elements. In the example above, after handling the event at the child, the click event will bubble up to the parent and continue bubbling up to the Window.

Thus, through analysis, we see that the correct answer is D: Capturing > Target > Bubbling. As illustrated, the event propagation process occurs from top to bottom (Capturing), then at the target, and finally from bottom to top (Bubbling).

3.5. Visualizing Event Propagation

You can visualize event propagation like a tree where the root is the Window and the leaves are the exact elements you interact with. The event will travel from the root to the leaves (Capturing), interact with the leaves (Target), and then return to the root (Bubbling).

3.6. Conclusion

By understanding event propagation in JavaScript, you can create better event-handling strategies for your web applications. Additionally, it will help you prevent unexpected behaviors when handling events in your app.


Comments


bottom of page