Skip to content

Latest commit

Β 

History

History
347 lines (282 loc) Β· 7.71 KB

File metadata and controls

347 lines (282 loc) Β· 7.71 KB

🎯 JavaScript Functions & Scope: Production-Ready Guide

πŸ“š Table of Contents

  1. Introduction
  2. Function Types & Patterns
  3. Scope & Closures
  4. Higher-Order Functions
  5. Projects
  6. Best Practices
  7. Performance Considerations

🎯 Introduction

This repository provides production-ready implementations of JavaScript functions, scope management, closures, and higher-order functions. Each module includes practical examples, performance considerations, and real-world use cases.

Key Concepts Covered:

  • Function declarations vs expressions
  • Arrow functions and this binding
  • IIFE patterns for scope isolation
  • Lexical scope vs dynamic scope
  • Closure patterns and memory management
  • Module patterns for encapsulation
  • Higher-order function composition
  • Functional programming principles

πŸš€ Quick Start

# Clone repository
git clone https://github.com/yourusername/js-functions-scope.git

# Navigate to directory
cd 01-functions-scope

# Run examples
node functions/function-declarations.js

# Run tests (if available)
npm test

πŸ”§ Prerequisites

  • Node.js β‰₯ 14.0.0
  • Understanding of basic JavaScript syntax
  • Modern code editor (VS Code recommended)

πŸ“– Learning Path

  1. Start with functions/README.md
  2. Practice with scope-closures/
  3. Master higher-order/
  4. Build projects/

πŸ—οΈ Project Structure

Each directory contains:

  • README.md: Comprehensive guide
  • .js files: Production-ready code with error handling
  • Examples: Real-world use cases
  • Performance tips: Optimization strategies

πŸ“ˆ Advanced Topics

  • Memory management with closures
  • Debouncing and throttling patterns
  • Currying and partial application
  • Module federation patterns
  • Tree-shaking optimizations

πŸ§ͺ Testing

Each module includes testable patterns. Use Jest or Mocha for comprehensive testing.

πŸ“ License

MIT - See LICENSE file for details

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add comprehensive tests
  4. Submit a pull request

---

## πŸ“ functions/

### πŸ“„ functions/README.md
```markdown
# πŸ”§ JavaScript Function Types: Production Patterns

## πŸ“‹ Overview
Comprehensive guide to JavaScript function types with production-ready patterns, performance considerations, and best practices.

## 🎯 Function Declarations vs Expressions

### Declaration (Hoisted)
```javascript
// βœ… Use for main logic, reusable functions
function calculateTotal(price, tax) {
  return price * (1 + tax);
}

Expression (Not Hoisted)

// βœ… Use for conditional assignments, callbacks
const calculateTotal = function(price, tax) {
  return price * (1 + tax);
};

🏹 Arrow Functions

When to Use:

// βœ… Short callbacks, array methods
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

// βœ… Lexical `this` binding
const user = {
  name: 'John',
  tasks: ['task1', 'task2'],
  getTasks: function() {
    return this.tasks.map(task => `${this.name}: ${task}`);
  }
};

When NOT to Use:

// ❌ Methods requiring `this` binding
const obj = {
  value: 10,
  // Avoid - no own `this`
  increment: () => this.value++ 
};

// ❌ Constructors
const Person = (name) => {
  this.name = name; // Error: arrow functions can't be constructors
};

πŸ”’ Immediately Invoked Function Expressions (IIFE)

Classic IIFE

// βœ… Isolate scope, avoid polluting global namespace
(function() {
  const privateVar = 'secret';
  // Logic here
})();

Modern Module Pattern

// βœ… Module with public API
const UserModule = (function() {
  let users = [];
  
  const addUser = (user) => {
    users.push(user);
    return users;
  };
  
  const getUsers = () => [...users];
  
  return { addUser, getUsers };
})();

// Usage
UserModule.addUser({ id: 1, name: 'John' });

Async IIFE

// βœ… Async initialization
(async function() {
  const data = await fetchData();
  initializeApp(data);
})();

🎭 Function Methods

call(), apply(), bind()

// Production pattern with error handling
const logger = {
  log: function(level, message, metadata = {}) {
    console[level](`[${new Date().toISOString()}] ${message}`, metadata);
  }
};

// Context borrowing with safety
function safeLog(level, message) {
  if (typeof console[level] !== 'function') {
    level = 'log';
  }
  logger.log.call(logger, level, message, { context: this });
}

// Currying with bind
const logError = logger.log.bind(logger, 'error');
logError('Database connection failed');

πŸ—οΈ Factory Functions

// βœ… Factory with validation
function createUser({ id, name, email }) {
  if (!id || !name || !email) {
    throw new Error('Missing required user properties');
  }
  
  if (!isValidEmail(email)) {
    throw new Error('Invalid email format');
  }
  
  return {
    id,
    name,
    email,
    getProfile() {
      return `${this.name} <${this.email}>`;
    },
    updateEmail(newEmail) {
      if (isValidEmail(newEmail)) {
        this.email = newEmail;
        return true;
      }
      return false;
    }
  };
}

// Usage
const user = createUser({
  id: 1,
  name: 'Jane Doe',
  email: 'jane@example.com'
});

🎯 Generator Functions

// βœ… Lazy evaluation, memory efficient
function* paginate(items, pageSize = 10) {
  for (let i = 0; i < items.length; i += pageSize) {
    yield items.slice(i, i + pageSize);
  }
}

// Usage with large datasets
const largeDataset = Array.from({ length: 10000 }, (_, i) => i);
const paginator = paginate(largeDataset, 100);

for (const page of paginator) {
  processPage(page); // Processes 100 items at a time
}

πŸš€ Performance Patterns

Memoization

function memoize(fn) {
  const cache = new Map();
  
  return function(...args) {
    const key = JSON.stringify(args);
    
    if (cache.has(key)) {
      return cache.get(key);
    }
    
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

// Usage
const expensiveCalculation = memoize(function(n) {
  console.log('Calculating...');
  return n * 2;
});

Debouncing

function debounce(func, wait, immediate = false) {
  let timeout;
  
  return function executedFunction(...args) {
    const context = this;
    const later = () => {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    
    if (callNow) func.apply(context, args);
  };
}

// Usage
const handleResize = debounce(() => {
  updateLayout();
}, 250);

πŸ“Š Comparison Table

Feature Declaration Expression Arrow
Hoisting βœ… Yes ❌ No ❌ No
this binding Dynamic Dynamic Lexical
Arguments object βœ… Yes βœ… Yes ❌ No
Constructor βœ… Yes βœ… Yes ❌ No
Implicit return ❌ No ❌ No βœ… Yes

πŸ”§ Production Checklist

  • Use function declarations for main logic
  • Use arrow functions for short callbacks
  • Implement proper error handling
  • Add input validation
  • Consider memory usage with closures
  • Add JSDoc comments for TypeScript
  • Write unit tests for edge cases

πŸ§ͺ Testing Strategy

  • Test all function types
  • Validate this context
  • Check error handling
  • Verify return values
  • Test with different inputs

🚨 Common Pitfalls

  1. Arrow functions in constructors
  2. Memory leaks with closures
  3. Incorrect this binding
  4. Overuse of IIFEs
  5. Missing error handling