JavaScript¶
Why using var should be avoided in moder JS?¶
You should avoid var in modern JavaScript because it has confusing scoping rules and behavior that can easily lead to bugs. The introduction of let and const in ES6 provides much safer and more predictable alternatives.
Here are the main reasons why:
1. Function Scope vs. Block Scope¶
This is the most significant difference. Variables declared with let and const have block scope, while var has function scope.
- Block Scope (
let/const): The variable only exists within the block ({...}) it was declared in. This is how most other programming languages work and is generally more intuitive. - Function Scope (
var): The variable exists throughout the entire function in which it was declared, even outside the block.
Example:¶
function scopeTest() {
if (true) {
var myVar = "I am var"; // function-scoped
let myLet = "I am let"; // block-scoped
const myConst = "I am const"; // block-scoped
}
console.log(myVar); // "I am var" -> 'var' leaks out of the if-block
// console.log(myLet); // ReferenceError: myLet is not defined
// console.log(myConst); // ReferenceError: myConst is not defined
}
scopeTest();
Because var "leaks" out of blocks, it can lead to bugs where variables are accidentally overwritten or accessed in places you don't expect.
2. Hoisting¶
In JavaScript, variable declarations are "hoisted" (moved to the top of their scope) before the code is executed. However, var and let/const behave differently.
-
varis hoisted and initialized withundefined. This means you can access avarvariable before its declaration without an error—it will just beundefined. This can hide bugs. -
letandconstare hoisted but not initialized. Accessing them before their declaration results in aReferenceError. The area before the declaration is called the Temporal Dead Zone (TDZ), which prevents you from using a variable before it's declared. This is much safer.
3. Global Object Pollution¶
When used in the global scope (outside of any function), var creates a property on the global object (window in browsers). let and const do not.
This can cause problems by accidentally overwriting global properties defined by the browser or other scripts.
var globalVar = "I'm on the window object";
let globalLet = "I am not on the window object";
console.log(window.globalVar); // "I'm on the window object"
console.log(window.globalLet); // undefined
Conclusion: Use let and const¶
For cleaner, safer, and more predictable code, always use const by default for variables that won't be reassigned, and use let for variables that you intend to reassign. There is no modern use case where var is the better choice.
What are Arrow Functions in JavaScript?¶
Arrow functions are a compact way to write functions in JavaScript. Introduced in ES6, they offer a shorter syntax compared to traditional function expressions and have a special behavior with the this keyword.
Syntax¶
The core of an arrow function is the => "fat arrow," which gives it its name.
- Traditional Function Expression:
- Arrow Function Equivalent:
Arrow functions can be even more concise:
- Implicit Return: If the function has only one expression, you can omit the curly braces
{}and thereturnkeyword. - Single Parameter: If there's only one parameter, you can omit the parentheses
(). - No Parameters: If there are no parameters, you must use empty parentheses.
The 'this' Keyword: The Biggest Difference¶
The most significant difference isn't the syntax but how arrow functions handle the this keyword.
-
Traditional Functions get their own
thisvalue based on how they are called. This can be confusing, asthiscan change depending on the context (e.g., a simple function call, a method call, etc.). -
Arrow Functions do not have their own
this. Instead, they lexically inheritthisfrom their parent scope. This meansthishas the same value inside the arrow function as it does outside of it.
Example¶
Consider an object with a method that uses a timer.
- With a Traditional Function (Problem):
const person = {
name: "Alex",
sayNameAfterDelay: function () {
setTimeout(function () {
// 'this' here is the global window object, not 'person'
console.log(this.name); // Prints 'undefined' or ''
}, 1000);
},
};
person.sayNameAfterDelay();
To fix this, developers historically had to use workarounds like const self = this; or .bind(this).
- With an Arrow Function (Solution):
const person = {
name: "Alex",
sayNameAfterDelay: function () {
setTimeout(() => {
// The arrow function inherits 'this' from sayNameAfterDelay
console.log(this.name); // Correctly prints 'Alex'
}, 1000);
},
};
person.sayNameAfterDelay();
The arrow function "remembers" the this from its surrounding context, making the code much more intuitive.
What is the Event Object is JS?¶
The event object is a special object that's automatically passed to an event handler function whenever an event (like a click, keypress, or mouse movement) occurs. It's packed with information about that specific event.
Think of it as a detailed report about what just happened. If the event is a "click," the event object tells you where the user clicked, what element they clicked on, and more.
How It Works in Code¶
When you write an event listener, you can include a parameter in your callback function. This parameter, conventionally named e, evt, or event, will automatically receive the event object from the browser.
const button = document.getElementById('myButton');
// The 'e' parameter here is the event object
button.addEventListener('click', function(e) {
console.log(e); // Logs the entire MouseEvent object to the console
// You can now access properties of the event
console.log('Event type:', e.type); // "click"
console.log('Target element:', e.target); // <button id="myButton">...</button>
});
When you click the button, the browser creates the event object and passes it to your function.
Common Properties and Methods¶
The event object has many useful properties and methods. The exact ones available depend on the type of event, but here are some of the most common:
-
event.target: The most useful property. It's the element that triggered the event. For example, if you click on a button,event.targetis that button element. -
event.type: A string indicating the type of event that occurred (e.g.,"click","keydown","mouseover"). -
event.preventDefault(): A method that stops the browser's default behavior for that event. For example, calling this on a form's "submit" event will prevent the page from reloading. -
event.stopPropagation(): A method that stops an event from "bubbling up" to parent elements. This prevents event listeners on ancestor elements from also firing. -
event.key: For keyboard events (keydown,keyup), this property tells you which key was pressed (e.g.,"a","Enter","Escape"). -
event.clientXandevent.clientY: For mouse events, these properties give you the horizontal and vertical coordinates of the mouse pointer relative to the visible part of the browser window.
What is an Even Handler Function?¶
An event handler is a JavaScript function that runs in response to a specific event, like a user clicking a button or pressing a key. It's the code that "handles" the event by performing a task.
Think of it as the set of instructions for a fire alarm. The event is smoke being detected. The event handler is the function that runs in response: "sound the alarm, flash the lights, and call the fire department."
How to Assign Event Handlers¶
There are a few ways to attach an event handler to an HTML element, but the modern addEventListener() method is the best practice.
1. Inline HTML Attribute (Old Method - Avoid)¶
You can assign the handler directly in the HTML. This is generally avoided because it mixes your JavaScript logic with your HTML structure.
2. DOM Property¶
You can assign a function to an element's on<event> property (e.g., onclick, onmouseover). This is better, but you can only assign one handler per event.
const button = document.getElementById('myButton');
button.onclick = function() {
console.log('Button was clicked!');
};
3. addEventListener() (Modern & Recommended)¶
This is the standard and most flexible method. It allows you to attach multiple handlers for the same event to a single element.
The event handler function automatically receives the event object as its first argument, providing details about the event.
const button = document.getElementById('myButton');
// The function below is the event handler
const handleClick = (e) => {
// 'e' is the event object
console.log('Button was clicked!');
console.log('Target element:', e.target);
};
// We "listen" for a 'click' event and attach our handler function to it
button.addEventListener('click', handleClick);
In this example, handleClick is the event handler. The addEventListener method is the event listener that waits for the event to happen and then calls the handler.