Console.log() Tricks

The console.log() method is great for debugging, but here are some advanced techniques to enhance its usage:

  • Styled Logs: Use %c for custom styling:

    js
    console.log("%cHello, world!", "color: blue; font-size: 20px; font-weight: bold;");
    
  • Grouped Logs: Organize related logs using console.group():

    js
    console.group("Debug Info");
    console.log("Variable:", myVar);
    console.log("Function Result:", myFunc());
    console.groupEnd();
    
  • Logging Objects in a Table Format:

    js
    console.table([{ name: "Alice", age: 25 }, { name: "Bob", age: 30 }]);
    
  • Tracking Execution Time:

    js
    console.time("Process");
    for (let i = 0; i < 1000000; i++) {} // Simulated workload
    console.timeEnd("Process");
    

Arrow Functions vs. Regular Functions

Arrow functions (=>) provide a more concise syntax but behave differently from regular functions.

FeatureArrow FunctionRegular Function
this BindingInherits from the surrounding scopeBound to the function itself
SyntaxMore compact (const add = (a, b) => a + b;)More verbose (function add(a, b) { return a + b; })
arguments ObjectNot availableAvailable
Constructor UsageCannot be used as a constructorCan be used with new

Arrow functions are great for short callbacks and functional programming, while regular functions are better when using this explicitly.

Avoiding Callback Hell: Promises & Async/Await

Nested callbacks can become hard to read and maintain. Here’s how to simplify them:

Using Promises: Instead of deeply nested callbacks:

js
fetchData()
  .then(processData)
  .then(saveData)
  .catch(handleError);

Using Async/Await for Cleaner Syntax:

js
async function fetchAndProcess() {
  try {
    const data = await fetchData();
    const processed = await processData(data);
    await saveData(processed);
  } catch (error) {
    handleError(error);
  }
}

Async/Await makes asynchronous code look synchronous, improving readability.