A beginner's guide to essential JavaScript concepts.
A closure is a function that remembers its outer variables, even if it's executed outside its lexical scope. Closures are commonly used for data privacy and maintaining state in JavaScript.
function makeCounter() {
let count = 0; // This variable is closed over by the inner function
return function() {
count++;
return count;
};
}
const counter1 = makeCounter();
console.log(counter1()); // Output: 1
console.log(counter1()); // Output: 2
const counter2 = makeCounter();
console.log(counter2()); // Output: 1 (new closure)
Explanation: Here, count is accessible only within the inner function returned by makeCounter. Each time makeCounter is called, a new closure is created, which maintains its own separate count.
In JavaScript, declarations (variables and functions) are "hoisted" to the top of their scope before the code executes. This means you can use functions and variables before they are declared, but only the declarations are hoisted, not the initializations.
console.log(name); // Output: undefined (declaration hoisted, but not initialization)
var name = "Alice";
console.log(greet()); // Output: "Hello!"
function greet() {
return "Hello!";
}
Explanation: Variable name is hoisted, but only its declaration, not its value, so it outputs undefined. The function greet is fully hoisted, so it can be called before its declaration.
In JavaScript, every object has a prototype, an object it inherits properties from. JavaScript inheritance is prototype-based, allowing one object to "inherit" properties from another.
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + " makes a noise.");
};
const dog = new Animal("Dog");
dog.speak(); // Output: "Dog makes a noise."
Explanation: speak is defined on Animal's prototype, making it available to all Animal instances. dog inherits this method from Animal's prototype.
this KeywordThe this keyword refers to the object that is executing the current function. Its value depends on the context in which it is called (runtime binding).
const person = {
name: "Alice",
greet() {
console.log("Hello, " + this.name);
}
};
person.greet(); // Output: "Hello, Alice"
// Global context
function sayHello() {
console.log("Hello, " + this.name);
}
sayHello(); // Output: "Hello, undefined" in strict mode or "Hello, globalName" in the browser
Explanation: In person.greet(), this refers to the person object. In the global context, this typically refers to the global object (window in browsers).
Scope defines the accessibility of variables and functions. JavaScript has three main types of scope:
{}, for example, within if or for statements (ES6 let and const are block-scoped).
let globalVar = "I am global";
function localScopeExample() {
let localVar = "I am local";
console.log(globalVar); // Output: "I am global"
console.log(localVar); // Output: "I am local"
}
localScopeExample();
// console.log(localVar); // Error: localVar is not defined
if (true) {
let blockScoped = "I am block-scoped";
console.log(blockScoped); // Output: "I am block-scoped"
}
// console.log(blockScoped); // Error: blockScoped is not defined
Explanation:
globalVar is accessible everywhere.localVar is only accessible within localScopeExample.blockScoped is accessible only within the block (if statement) in which it is declared.