Introduction
In JavaScript, the this keyword is a fundamental concept that can be confusing to first-term students.
It refers to the context in which the current code is executing, and its value can change based on how and where a function is called.
Understanding this is crucial for effectively managing and manipulating both the HTML Document Object Model (DOM) and the JavaScript Browser Object Model (BOM).
What is this?
In JavaScript, this refers to the object that the function is a method of. The value of this is determined at runtime, depending on the execution context:
Global context: In the global execution context (outside of any function), this refers to the global object whether in strict mode or not. Function context: Inside a function, the value of this depends on how the function was called. If it was called as a method of an object, this is set to the object the method is called on. Examples Demonstrating this in Different Contexts
1. Global Context
javascript
Copy code
console.log(this.document === document); // true
console.log(this); // Logs global object (window in browser)
Here, this refers to the global window object, under which all global variables and browser-specific objects reside.
2. Function Context
javascript
Copy code
function show() {
console.log(this);
}
show(); // In a browser, this will log the Window object.
In non-strict mode, a regular function call like this has this pointing to the global object (window). In strict mode, this would be undefined.
3. Object Method
javascript
Copy code
const person = {
firstName: "James",
lastName: "T. Kirk",
fullName: function() {
return `${this.firstName} ${this.lastName}`;
}
};
console.log(person.fullName()); // James T. Kirk
In the method call of an object, this refers to the object the method is called on.
How Arrow Functions Affect this
Arrow functions do not have their own this context; instead, they inherit this from the surrounding code where they are defined, which is known as lexical scoping.
Example with DOM
javascript
Copy code
document.getElementById('btn').addEventListener('click', () => {
console.log(this); // Logs the window object, not the button
});
Here, the arrow function inherits this from its surrounding scope, which is the global window object in a browser, unlike a regular function which would have this set to the element that triggered the event (e.g., the button).
Example with BOM
javascript
Copy code
setTimeout(() => {
console.log(this); // Still window object
}, 1000);
Even inside a setTimeout (which is part of BOM), the arrow function keeps this from its lexical context, unlike a regular function which would have this set to the global object (or undefined in strict mode).
Conclusion
Understanding how this works in different contexts is crucial for programming effectively in JavaScript, especially when manipulating the DOM and handling events in the BOM. By using arrow functions, you can avoid common pitfalls related to this, making your code cleaner and more intuitive. Now, let's practice what we've learned with some exercises that reinforce these concepts.
Let's practice what we've learned with some exercises that reinforce these concepts => present 10 drills with HTML DOM and JavaScript BOM
Practical Drills: Reinforcing the Concepts of this and Arrow Functions in DOM and BOM
These exercises are designed to help first-term students deepen their understanding of the this keyword in various contexts, specifically in interactions with the HTML DOM and JavaScript BOM. The exercises will also incorporate the use of arrow functions to highlight their behavior in these contexts.
Drill 1: DOM Button Click
Objective: Understand how this behaves in event handlers.
Task:
Create an HTML button with the text "Click Me". Attach an event listener using a regular function and log this. Repeat with an arrow function and compare the outputs. html
Copy code
<button id="clickMe">Click Me</button>
<script>
document.getElementById('clickMe').addEventListener('click', function() {
console.log(this); // Button object
});
document.getElementById('clickMe').addEventListener('click', () => {
console.log(this); // Window object
});
</script>
Drill 2: Modifying Element Styles
Objective: Manipulate CSS styles using this.
Task:
Set up an event where clicking an item changes its color using this. html
Copy code
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script>
document.querySelectorAll('li').forEach(item => {
item.addEventListener('click', function() {
this.style.color = 'red';
});
});
</script>
Drill 3: Using setTimeout in Methods
Objective: Observe how this behaves in BOM methods.
Task:
Define an object with a method that sets its property after a delay. Use both traditional and arrow functions to see the difference. javascript
Copy code
const timerObj = {
message: 'Hello',
startTimer: function() {
setTimeout(function() {
console.log(this.message); // undefined
}, 1000);
setTimeout(() => {
console.log(this.message); // Hello
}, 1000);
}
};
timerObj.startTimer();
Drill 4: Event Delegation
Objective: Apply event delegation with this.
Task:
Create a container with multiple buttons. Use event delegation on the container to log the text of the button clicked. html
Copy code
<div id="buttonContainer">
<button>One</button>
<button>Two</button>
<button>Three</button>
</div>
<script>
document.getElementById('buttonContainer').addEventListener('click', function(e) {
if(e.target.tagName === 'BUTTON') {
console.log(this); // Container div
console.log(e.target.innerHTML); // Button text
}
});
</script>
Drill 5: Manipulating Classes
Objective: Toggle classes using this in an event.
Task:
Create several div elements. Set up an event to toggle a class active on click using this. html
Copy code
<div>Click to toggle</div>
<div>Click to toggle</div>
<div>Click to toggle</div>
<script>
document.querySelectorAll('div').forEach(div => {
div.addEventListener('click', function() {
this.classList.toggle('active');
});
});
</script>
Drill 6: Dynamic Element Creation
Objective: Use this to handle dynamically created elements.
Task:
Create a button that when clicked, creates a new button. New buttons, when clicked, should log a message using this. html
Copy code
<button id="createButton">Create Button</button>
<script>
document.getElementById('createButton').addEventListener('click', function() {
const newButton = document.createElement('button');
newButton.textContent = 'New Button';
newButton.addEventListener('click', function() {
console.log(this.textContent); // Logs 'New Button'
});
document.body.appendChild(newButton);
});
</script>
Drill 7: Integrating Arrow Functions in Callbacks
Objective: Use arrow functions in API callbacks to preserve this.
Task:
Define an object that fetches data and logs it using this. Use an arrow function in the fetch callback. javascript
Copy code
const apiCaller = {
dataUrl: 'https://api.example.com/data',
fetchData: function() {
fetch(this.dataUrl).then(response => response.json()).then(data => {
console.log(this); // apiCaller object
console.log(data);
});
}
};
apiCaller.fetchData();
Drill 8: Handling Mouse Over Events
Objective: Understand event handling and this with mouse events.