A function is a reusable block of code designed to perform a specific task. You define the function once and can then "call" (or invoke) it whenever you need it.
Function Declarations
This is the classic way to define a function. They are "hoisted," meaning they can be called before they are defined in the code.
JavaScript
// Defining the function
function greet(name) {
  return `Hello, ${name}!`;
}
// Calling the function
const greeting = greet("Alice");
console.log(greeting); // "Hello, Alice!"
Function Expressions
Here, a function is assigned to a variable. They are not hoisted.
JavaScript
const add = function(a, b) {
  return a + b;
};
const sum = add(5, 3);
console.log(sum); // 8
Arrow Functions (ES6)
Arrow functions provide a more concise syntax and have a different behavior for the this keyword. They are a modern and widely-used feature.
Code Snippet: Comparing Syntax
JavaScript
// Traditional Function Expression
const square = function(x) {
  return x * x;
};
// Arrow Function (concise body)
const squareArrow = x => x * x; // Implicit return for single expressions
// Arrow Function (block body)
const subtract = (a, b) => {
  const result = a - b;
  return result;
};
console.log(square(4));      // 16
console.log(squareArrow(4)); // 16
console.log(subtract(10, 3)); // 7
The this Keyword
The this keyword refers to the context in which a function is executed. Its value can change depending on how a function is called, which can be confusing.
- In a regular function: this is often the object that called the function (e.g., the object before the dot). In the global scope, it can be the window object in browsers.
- In an arrow function: this is lexically scoped. This means it takes its value from the surrounding code where it was defined, not where it was called. This behavior is often more predictable and desirable.
Code Snippet: this in Action
JavaScript
const user = {
  name: "Bob",
  sayHi: function() {
    // 'this' refers to the 'user' object because user called the function.
    console.log(`Hi, my name is ${this.name}.`); 
  },
  
  greet: () => {
    // Arrow functions don't have their own 'this'. They inherit it.
    // In this context, 'this' would likely be the global 'window' object,
    // which doesn't have a 'name' property.
    console.log(`Hi, my name is ${this.name}.`);
  },
  waitAndGreet: function() {
    setTimeout(function() {
      // In this REGULAR function callback, 'this' loses its context and
      // refers to the 'window' object.
      console.log(`(Waited) Hi, my name is ${this.name}.`); // Will be undefined
    }, 1000);
    setTimeout(() => {
      // In this ARROW function callback, 'this' is inherited from the
      // surrounding 'waitAndGreet' function, so it correctly refers to 'user'.
      console.log(`(Waited) Hi, my name is ${this.name}.`); // Will be "Bob"
    }, 1000);
  }
};
user.sayHi();        // "Hi, my name is Bob."
user.greet();        // "Hi, my name is undefined."
user.waitAndGreet(); // Demonstrates the key difference in callbacks.