函数基础

函数声明

// 基本函数声明
function greet(name) {
  return `Hello, ${name}!`;
}

console.log(greet('Alice')); // Hello, Alice!

// 函数声明会被提升(hoisting)
console.log(add(5, 3)); // 8 - 可以在声明前调用

function add(a, b) {
  return a + b;
}

// 带默认参数的函数
function greetWithDefault(name = 'Guest', greeting = 'Hello') {
  return `${greeting}, ${name}!`;
}

console.log(greetWithDefault());           // Hello, Guest!
console.log(greetWithDefault('Bob'));      // Hello, Bob!
console.log(greetWithDefault('Charlie', 'Hi')); // Hi, Charlie!

// 函数参数解构
function createUser({name, age, email = 'unknown'}) {
  return {
    name,
    age,
    email,
    id: Math.random().toString(36).substr(2, 9)
  };
}

const user = createUser({
  name: 'Alice',
  age: 30
});
console.log(user);

// 剩余参数(Rest Parameters)
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15
console.log(sum(10, 20));        // 30

// 混合使用普通参数和剩余参数
function logMessage(level, ...messages) {
  const timestamp = new Date().toISOString();
  console.log(`[${timestamp}] ${level.toUpperCase()}:`, ...messages);
}

logMessage('info', 'User logged in', 'Session started');
logMessage('error', 'Database connection failed');

函数表达式

// 匿名函数表达式
const multiply = function(a, b) {
  return a * b;
};

console.log(multiply(4, 5)); // 20

// 具名函数表达式
const factorial = function fact(n) {
  if (n <= 1) return 1;
  return n * fact(n - 1); // 可以在函数内部使用函数名
};

console.log(factorial(5)); // 120
// console.log(fact(5)); // ReferenceError: fact is not defined

// 立即执行函数表达式(IIFE)
(function() {
  console.log('IIFE executed immediately!');
})();

// 带参数的IIFE
(function(name, age) {
  console.log(`Name: ${name}, Age: ${age}`);
})('Alice', 30);

// 返回值的IIFE
const result = (function(x, y) {
  return x * y + 10;
})(5, 3);
console.log(result); // 25

// 使用IIFE创建模块
const calculator = (function() {
  let history = [];
  
  return {
    add(a, b) {
      const result = a + b;
      history.push(`${a} + ${b} = ${result}`);
      return result;
    },
    
    subtract(a, b) {
      const result = a - b;
      history.push(`${a} - ${b} = ${result}`);
      return result;
    },
    
    getHistory() {
      return [...history]; // 返回副本
    },
    
    clearHistory() {
      history = [];
    }
  };
})();

console.log(calculator.add(5, 3));      // 8
console.log(calculator.subtract(10, 4)); // 6
console.log(calculator.getHistory());   // ['5 + 3 = 8', '10 - 4 = 6']

箭头函数

// 基本箭头函数
const square = x => x * x;
const add = (a, b) => a + b;
const greet = name => `Hello, ${name}!`;

console.log(square(4));        // 16
console.log(add(3, 7));        // 10
console.log(greet('Bob'));     // Hello, Bob!

// 无参数的箭头函数
const getRandom = () => Math.random();
const getCurrentTime = () => new Date().toISOString();

// 多行箭头函数
const processData = data => {
  const processed = data.map(item => item * 2);
  const filtered = processed.filter(item => item > 10);
  return filtered;
};

console.log(processData([1, 5, 8, 12, 3])); // [16, 24]

// 返回对象字面量(需要括号)
const createPoint = (x, y) => ({ x, y });
const createUser = (name, age) => ({
  name,
  age,
  id: Math.random().toString(36).substr(2, 9)
});

console.log(createPoint(3, 4));           // { x: 3, y: 4 }
console.log(createUser('Alice', 25));     // { name: 'Alice', age: 25, id: '...' }

// 箭头函数与this绑定
const obj = {
  name: 'Object',
  
  // 普通函数 - this指向obj
  regularMethod: function() {
    console.log('Regular method this:', this.name);
    
    // 内部普通函数 - this指向全局对象(严格模式下为undefined)
    function innerFunction() {
      console.log('Inner function this:', this?.name || 'undefined');
    }
    innerFunction();
    
    // 内部箭头函数 - this继承外层作用域
    const innerArrow = () => {
      console.log('Inner arrow this:', this.name);
    };
    innerArrow();
  },
  
  // 箭头函数 - this不绑定,继承外层作用域
  arrowMethod: () => {
    console.log('Arrow method this:', this?.name || 'undefined');
  }
};

obj.regularMethod();
obj.arrowMethod();

// 数组方法中的箭头函数
const numbers = [1, 2, 3, 4, 5];

// 使用箭头函数简化数组操作
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);

console.log('Doubled:', doubled);  // [2, 4, 6, 8, 10]
console.log('Evens:', evens);      // [2, 4]
console.log('Sum:', sum);          // 15

// 箭头函数的限制
// 1. 不能用作构造函数
// const Person = (name) => {
//   this.name = name; // TypeError: Person is not a constructor
// };
// const person = new Person('Alice');

// 2. 没有arguments对象
function regularFunc() {
  console.log('Arguments:', arguments);
}

const arrowFunc = (...args) => {
  console.log('Args:', args); // 使用剩余参数替代
};

regularFunc(1, 2, 3);
arrowFunc(1, 2, 3);

作用域

全局作用域

// 全局变量
var globalVar = 'I am global';
let globalLet = 'I am also global';
const globalConst = 'I am global too';

// 在浏览器中,var声明的变量会成为window对象的属性
// console.log(window.globalVar); // 'I am global' (浏览器环境)
// console.log(window.globalLet); // undefined (let和const不会)

function accessGlobal() {
  console.log('Accessing global:', globalVar);
  console.log('Accessing global:', globalLet);
  console.log('Accessing global:', globalConst);
}

accessGlobal();

// 隐式全局变量(不推荐)
function createImplicitGlobal() {
  implicitGlobal = 'I am implicit global'; // 没有声明关键字
}

createImplicitGlobal();
console.log('Implicit global:', implicitGlobal);

// 严格模式下会报错
// 'use strict';
// function strictMode() {
//   strictGlobal = 'This will throw an error'; // ReferenceError
// }

函数作用域

function functionScope() {
  var functionVar = 'I am in function scope';
  let functionLet = 'I am also in function scope';
  const functionConst = 'I am in function scope too';
  
  console.log('Inside function:', functionVar);
  console.log('Inside function:', functionLet);
  console.log('Inside function:', functionConst);
  
  // 内部函数可以访问外部函数的变量
  function innerFunction() {
    console.log('Inner accessing outer:', functionVar);
    
    var innerVar = 'I am in inner function';
    console.log('Inner var:', innerVar);
  }
  
  innerFunction();
  
  // 外部函数不能访问内部函数的变量
  // console.log(innerVar); // ReferenceError
}

functionScope();

// 函数外部不能访问函数内部的变量
// console.log(functionVar); // ReferenceError

// 参数也是函数作用域的一部分
function parameterScope(param1, param2) {
  console.log('Parameters:', param1, param2);
  
  // 参数可以被重新赋值
  param1 = 'modified';
  console.log('Modified param1:', param1);
}

let arg1 = 'original';
parameterScope(arg1, 'second');
console.log('Original arg1 unchanged:', arg1); // 原始值不变

块级作用域

// let和const具有块级作用域
if (true) {
  var varInBlock = 'var has function scope';
  let letInBlock = 'let has block scope';
  const constInBlock = 'const has block scope';
  
  console.log('Inside block:', varInBlock);
  console.log('Inside block:', letInBlock);
  console.log('Inside block:', constInBlock);
}

console.log('Outside block:', varInBlock);     // 可以访问
// console.log('Outside block:', letInBlock);  // ReferenceError
// console.log('Outside block:', constInBlock); // ReferenceError

// for循环中的块级作用域
console.log('\nFor loop scope:');

// 使用var - 所有回调函数共享同一个变量
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log('var i:', i); // 输出: 3, 3, 3
  }, 100);
}

// 使用let - 每次迭代都有独立的变量
for (let j = 0; j < 3; j++) {
  setTimeout(() => {
    console.log('let j:', j); // 输出: 0, 1, 2
  }, 200);
}

// switch语句中的块级作用域
let value = 1;
switch (value) {
  case 1: {
    let caseVar = 'case 1';
    console.log(caseVar);
    break;
  }
  case 2: {
    let caseVar = 'case 2'; // 不同的caseVar
    console.log(caseVar);
    break;
  }
}

// try-catch中的块级作用域
try {
  let tryVar = 'in try block';
  throw new Error('test error');
} catch (error) {
  let catchVar = 'in catch block';
  console.log('Caught:', error.message);
  console.log(catchVar);
  // console.log(tryVar); // ReferenceError
} finally {
  let finallyVar = 'in finally block';
  console.log(finallyVar);
  // console.log(catchVar); // ReferenceError
}

词法作用域(静态作用域)

// JavaScript使用词法作用域
let globalScope = 'global';

function outerFunction() {
  let outerScope = 'outer';
  
  function innerFunction() {
    let innerScope = 'inner';
    
    // 可以访问所有外层作用域的变量
    console.log('Inner can access:', innerScope, outerScope, globalScope);
  }
  
  function anotherInnerFunction() {
    let anotherInnerScope = 'another inner';
    
    // 不能访问同级函数的变量
    console.log('Another inner can access:', anotherInnerScope, outerScope, globalScope);
    // console.log(innerScope); // ReferenceError
  }
  
  innerFunction();
  anotherInnerFunction();
  
  // 外层函数不能访问内层函数的变量
  // console.log(innerScope); // ReferenceError
}

outerFunction();

// 作用域链示例
function createCounter() {
  let count = 0;
  
  return function() {
    count++; // 访问外层函数的变量
    return count;
  };
}

const counter1 = createCounter();
const counter2 = createCounter();

console.log('Counter1:', counter1()); // 1
console.log('Counter1:', counter1()); // 2
console.log('Counter2:', counter2()); // 1 (独立的作用域)
console.log('Counter1:', counter1()); // 3

// 作用域污染示例
function demonstrateScopePollution() {
  // 不好的做法 - 意外创建全局变量
  function badFunction() {
    accidentalGlobal = 'Oops, I am global!';
  }
  
  // 好的做法 - 明确声明变量
  function goodFunction() {
    let localVariable = 'I am properly scoped';
    return localVariable;
  }
  
  badFunction();
  console.log('Accidental global:', accidentalGlobal);
  
  console.log('Good function result:', goodFunction());
}

demonstrateScope Pollution();

闭包

闭包基础

// 基本闭包示例
function createGreeting(greeting) {
  // 外层函数的参数和变量
  return function(name) {
    // 内层函数可以访问外层函数的参数
    return `${greeting}, ${name}!`;
  };
}

const sayHello = createGreeting('Hello');
const sayHi = createGreeting('Hi');

console.log(sayHello('Alice')); // Hello, Alice!
console.log(sayHi('Bob'));      // Hi, Bob!

// 闭包保持对外层变量的引用
function createCounter(initialValue = 0) {
  let count = initialValue;
  
  return {
    increment() {
      count++;
      return count;
    },
    
    decrement() {
      count--;
      return count;
    },
    
    getValue() {
      return count;
    },
    
    reset() {
      count = initialValue;
      return count;
    }
  };
}

const counter = createCounter(10);
console.log('Initial:', counter.getValue());  // 10
console.log('Increment:', counter.increment()); // 11
console.log('Increment:', counter.increment()); // 12
console.log('Decrement:', counter.decrement()); // 11
console.log('Reset:', counter.reset());        // 10

// 多个闭包共享同一个环境
function createSharedCounter() {
  let count = 0;
  
  return {
    counter1: () => ++count,
    counter2: () => ++count,
    getCount: () => count
  };
}

const shared = createSharedCounter();
console.log('Shared counter1:', shared.counter1()); // 1
console.log('Shared counter2:', shared.counter2()); // 2
console.log('Shared count:', shared.getCount());    // 2

闭包的实际应用

// 1. 模块模式
const userModule = (function() {
  // 私有变量
  let users = [];
  let currentId = 1;
  
  // 私有方法
  function generateId() {
    return currentId++;
  }
  
  function validateUser(user) {
    return user && user.name && user.email;
  }
  
  // 公共API
  return {
    addUser(name, email) {
      const user = { id: generateId(), name, email };
      
      if (validateUser(user)) {
        users.push(user);
        return user;
      }
      
      throw new Error('Invalid user data');
    },
    
    getUser(id) {
      return users.find(user => user.id === id);
    },
    
    getAllUsers() {
      return [...users]; // 返回副本
    },
    
    removeUser(id) {
      const index = users.findIndex(user => user.id === id);
      if (index !== -1) {
        return users.splice(index, 1)[0];
      }
      return null;
    },
    
    getUserCount() {
      return users.length;
    }
  };
})();

// 使用模块
const user1 = userModule.addUser('Alice', 'alice@example.com');
const user2 = userModule.addUser('Bob', 'bob@example.com');

console.log('All users:', userModule.getAllUsers());
console.log('User count:', userModule.getUserCount());
console.log('Get user 1:', userModule.getUser(1));

// 2. 函数工厂
function createValidator(rules) {
  return function(data) {
    const errors = [];
    
    for (const [field, rule] of Object.entries(rules)) {
      const value = data[field];
      
      if (rule.required && (value === undefined || value === null || value === '')) {
        errors.push(`${field} is required`);
        continue;
      }
      
      if (value !== undefined && rule.type && typeof value !== rule.type) {
        errors.push(`${field} must be of type ${rule.type}`);
      }
      
      if (value !== undefined && rule.minLength && value.length < rule.minLength) {
        errors.push(`${field} must be at least ${rule.minLength} characters`);
      }
      
      if (value !== undefined && rule.pattern && !rule.pattern.test(value)) {
        errors.push(`${field} format is invalid`);
      }
    }
    
    return {
      isValid: errors.length === 0,
      errors
    };
  };
}

const userValidator = createValidator({
  name: { required: true, type: 'string', minLength: 2 },
  email: { required: true, type: 'string', pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
  age: { type: 'number' }
});

const validationResult1 = userValidator({
  name: 'Alice',
  email: 'alice@example.com',
  age: 30
});

const validationResult2 = userValidator({
  name: 'A',
  email: 'invalid-email',
  age: 'not-a-number'
});

console.log('Validation 1:', validationResult1);
console.log('Validation 2:', validationResult2);

// 3. 缓存函数(记忆化)
function memoize(fn) {
  const cache = new Map();
  
  return function(...args) {
    const key = JSON.stringify(args);
    
    if (cache.has(key)) {
      console.log('Cache hit for:', args);
      return cache.get(key);
    }
    
    console.log('Computing for:', args);
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

// 斐波那契数列(递归版本)
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

const memoizedFibonacci = memoize(fibonacci);

console.log('Fibonacci 10:', memoizedFibonacci(10));
console.log('Fibonacci 10 again:', memoizedFibonacci(10)); // 从缓存获取

// 4. 延迟执行
function delay(ms) {
  return function(fn) {
    return function(...args) {
      setTimeout(() => fn.apply(this, args), ms);
    };
  };
}

const delayedLog = delay(1000)(console.log);
delayedLog('This message will appear after 1 second');

// 5. 部分应用(Partial Application)
function partial(fn, ...presetArgs) {
  return function(...laterArgs) {
    return fn.apply(this, [...presetArgs, ...laterArgs]);
  };
}

function multiply(a, b, c) {
  return a * b * c;
}

const multiplyBy2 = partial(multiply, 2);
const multiplyBy2And3 = partial(multiply, 2, 3);

console.log('Partial 1:', multiplyBy2(3, 4));     // 2 * 3 * 4 = 24
console.log('Partial 2:', multiplyBy2And3(5));    // 2 * 3 * 5 = 30

闭包的注意事项

// 1. 循环中的闭包陷阱
console.log('\n=== 循环中的闭包陷阱 ===');

// 问题:所有函数都引用同一个变量
const functions1 = [];
for (var i = 0; i < 3; i++) {
  functions1.push(function() {
    return i; // 所有函数都引用同一个i
  });
}

functions1.forEach((fn, index) => {
  console.log(`Function ${index} returns:`, fn()); // 都返回3
});

// 解决方案1:使用let
const functions2 = [];
for (let i = 0; i < 3; i++) {
  functions2.push(function() {
    return i; // 每次迭代都有独立的i
  });
}

functions2.forEach((fn, index) => {
  console.log(`Function ${index} returns:`, fn()); // 返回0, 1, 2
});

// 解决方案2:使用IIFE
const functions3 = [];
for (var i = 0; i < 3; i++) {
  functions3.push((function(index) {
    return function() {
      return index;
    };
  })(i));
}

functions3.forEach((fn, index) => {
  console.log(`Function ${index} returns:`, fn()); // 返回0, 1, 2
});

// 解决方案3:使用bind
const functions4 = [];
for (var i = 0; i < 3; i++) {
  functions4.push(function(index) {
    return index;
  }.bind(null, i));
}

functions4.forEach((fn, index) => {
  console.log(`Function ${index} returns:`, fn()); // 返回0, 1, 2
});

// 2. 内存泄漏风险
function createPotentialMemoryLeak() {
  const largeData = new Array(1000000).fill('data');
  
  return function() {
    // 即使不使用largeData,它也会被保留在内存中
    return 'small result';
  };
}

// 改进版本:只保留需要的数据
function createOptimized() {
  const largeData = new Array(1000000).fill('data');
  const summary = largeData.length; // 只保留需要的信息
  
  return function() {
    return `Data length: ${summary}`;
  };
}

// 3. 闭包中的this绑定
const obj = {
  name: 'MyObject',
  
  createMethod() {
    // 普通函数中的this
    return function() {
      console.log('Regular function this:', this?.name || 'undefined');
    };
  },
  
  createArrowMethod() {
    // 箭头函数中的this
    return () => {
      console.log('Arrow function this:', this.name);
    };
  },
  
  createBoundMethod() {
    // 绑定this
    return function() {
      console.log('Bound function this:', this.name);
    }.bind(this);
  }
};

const regularMethod = obj.createMethod();
const arrowMethod = obj.createArrowMethod();
const boundMethod = obj.createBoundMethod();

regularMethod(); // this为undefined(严格模式)或全局对象
arrowMethod();   // this为obj
boundMethod();   // this为obj

高阶函数

函数作为参数

// 基本高阶函数
function operate(a, b, operation) {
  return operation(a, b);
}

const add = (x, y) => x + y;
const multiply = (x, y) => x * y;
const power = (x, y) => x ** y;

console.log(operate(5, 3, add));      // 8
console.log(operate(5, 3, multiply)); // 15
console.log(operate(5, 3, power));    // 125

// 数组处理的高阶函数
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// map - 转换每个元素
const squared = numbers.map(n => n * n);
const doubled = numbers.map(n => n * 2);

console.log('Squared:', squared);
console.log('Doubled:', doubled);

// filter - 过滤元素
const evens = numbers.filter(n => n % 2 === 0);
const greaterThanFive = numbers.filter(n => n > 5);

console.log('Evens:', evens);
console.log('Greater than 5:', greaterThanFive);

// reduce - 累积计算
const sum = numbers.reduce((acc, n) => acc + n, 0);
const product = numbers.reduce((acc, n) => acc * n, 1);
const max = numbers.reduce((acc, n) => Math.max(acc, n), -Infinity);

console.log('Sum:', sum);
console.log('Product:', product);
console.log('Max:', max);

// 复杂的reduce应用
const words = ['hello', 'world', 'javascript', 'is', 'awesome'];

// 统计单词长度
const wordLengths = words.reduce((acc, word) => {
  acc[word] = word.length;
  return acc;
}, {});

// 按长度分组
const groupedByLength = words.reduce((acc, word) => {
  const length = word.length;
  if (!acc[length]) {
    acc[length] = [];
  }
  acc[length].push(word);
  return acc;
}, {});

console.log('Word lengths:', wordLengths);
console.log('Grouped by length:', groupedByLength);

// 自定义高阶函数
function createProcessor(transformFn, filterFn) {
  return function(array) {
    return array
      .filter(filterFn)
      .map(transformFn);
  };
}

const processEvenNumbers = createProcessor(
  n => n * n,        // 平方
  n => n % 2 === 0   // 只处理偶数
);

console.log('Processed evens:', processEvenNumbers(numbers));

// 函数组合
function compose(...functions) {
  return function(value) {
    return functions.reduceRight((acc, fn) => fn(acc), value);
  };
}

function pipe(...functions) {
  return function(value) {
    return functions.reduce((acc, fn) => fn(acc), value);
  };
}

const addOne = x => x + 1;
const multiplyByTwo = x => x * 2;
const square = x => x * x;

// 从右到左执行
const composedFunction = compose(square, multiplyByTwo, addOne);
console.log('Composed (5):', composedFunction(5)); // ((5 + 1) * 2)^2 = 144

// 从左到右执行
const pipedFunction = pipe(addOne, multiplyByTwo, square);
console.log('Piped (5):', pipedFunction(5)); // ((5 + 1) * 2)^2 = 144

函数作为返回值

// 柯里化(Currying)
function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...nextArgs) {
        return curried.apply(this, args.concat(nextArgs));
      };
    }
  };
}

// 原始函数
function add3Numbers(a, b, c) {
  return a + b + c;
}

// 柯里化版本
const curriedAdd = curry(add3Numbers);

console.log('Curried usage:');
console.log(curriedAdd(1)(2)(3));     // 6
console.log(curriedAdd(1, 2)(3));     // 6
console.log(curriedAdd(1)(2, 3));     // 6
console.log(curriedAdd(1, 2, 3));     // 6

// 部分应用的实际例子
const multiply3 = curry((a, b, c) => a * b * c);
const multiplyBy2 = multiply3(2);
const multiplyBy2And3 = multiplyBy2(3);

console.log('Partial application:');
console.log(multiplyBy2And3(4));      // 2 * 3 * 4 = 24

// 创建专用函数
function createLogger(level) {
  return function(message) {
    const timestamp = new Date().toISOString();
    console.log(`[${timestamp}] ${level.toUpperCase()}: ${message}`);
  };
}

const logInfo = createLogger('info');
const logError = createLogger('error');
const logWarning = createLogger('warning');

logInfo('Application started');
logError('Database connection failed');
logWarning('Deprecated API used');

// 创建配置化的函数
function createApiClient(baseUrl, defaultHeaders = {}) {
  return {
    get(endpoint, headers = {}) {
      return fetch(`${baseUrl}${endpoint}`, {
        method: 'GET',
        headers: { ...defaultHeaders, ...headers }
      });
    },
    
    post(endpoint, data, headers = {}) {
      return fetch(`${baseUrl}${endpoint}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...defaultHeaders,
          ...headers
        },
        body: JSON.stringify(data)
      });
    }
  };
}

const apiClient = createApiClient('https://api.example.com', {
  'Authorization': 'Bearer token123'
});

// 使用配置化的客户端
// apiClient.get('/users');
// apiClient.post('/users', { name: 'Alice' });

// 函数装饰器
function timing(fn) {
  return function(...args) {
    const start = performance.now();
    const result = fn.apply(this, args);
    const end = performance.now();
    console.log(`${fn.name} took ${end - start} milliseconds`);
    return result;
  };
}

function retry(maxAttempts) {
  return function(fn) {
    return function(...args) {
      let attempts = 0;
      let lastError;
      
      while (attempts < maxAttempts) {
        try {
          return fn.apply(this, args);
        } catch (error) {
          lastError = error;
          attempts++;
          console.log(`Attempt ${attempts} failed:`, error.message);
        }
      }
      
      throw lastError;
    };
  };
}

// 使用装饰器
function unreliableFunction() {
  if (Math.random() < 0.7) {
    throw new Error('Random failure');
  }
  return 'Success!';
}

const timedFunction = timing(unreliableFunction);
const retriedFunction = retry(3)(unreliableFunction);
const timedAndRetriedFunction = timing(retry(3)(unreliableFunction));

try {
  console.log('Timed and retried result:', timedAndRetriedFunction());
} catch (error) {
  console.log('Final failure:', error.message);
}

递归函数

基本递归

// 阶乘函数
function factorial(n) {
  // 基础情况
  if (n <= 1) {
    return 1;
  }
  
  // 递归情况
  return n * factorial(n - 1);
}

console.log('Factorial 5:', factorial(5)); // 120
console.log('Factorial 0:', factorial(0)); // 1

// 斐波那契数列
function fibonacci(n) {
  if (n <= 1) {
    return n;
  }
  
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log('Fibonacci sequence:');
for (let i = 0; i <= 10; i++) {
  console.log(`F(${i}) = ${fibonacci(i)}`);
}

// 优化的斐波那契(记忆化)
function fibonacciMemo() {
  const memo = {};
  
  return function fib(n) {
    if (n in memo) {
      return memo[n];
    }
    
    if (n <= 1) {
      return memo[n] = n;
    }
    
    return memo[n] = fib(n - 1) + fib(n - 2);
  };
}

const fastFibonacci = fibonacciMemo();
console.log('Fast Fibonacci 40:', fastFibonacci(40));

// 数组求和
function sumArray(arr) {
  // 基础情况:空数组
  if (arr.length === 0) {
    return 0;
  }
  
  // 递归情况:第一个元素 + 剩余元素的和
  return arr[0] + sumArray(arr.slice(1));
}

console.log('Array sum:', sumArray([1, 2, 3, 4, 5])); // 15

// 数组最大值
function findMax(arr) {
  // 基础情况:只有一个元素
  if (arr.length === 1) {
    return arr[0];
  }
  
  // 递归情况:比较第一个元素和剩余元素的最大值
  const maxOfRest = findMax(arr.slice(1));
  return Math.max(arr[0], maxOfRest);
}

console.log('Array max:', findMax([3, 7, 2, 9, 1])); // 9

树形结构递归

// 树节点定义
class TreeNode {
  constructor(value, children = []) {
    this.value = value;
    this.children = children;
  }
  
  addChild(child) {
    this.children.push(child);
  }
}

// 创建示例树
const root = new TreeNode('root');
const child1 = new TreeNode('child1');
const child2 = new TreeNode('child2');
const grandchild1 = new TreeNode('grandchild1');
const grandchild2 = new TreeNode('grandchild2');
const grandchild3 = new TreeNode('grandchild3');

root.addChild(child1);
root.addChild(child2);
child1.addChild(grandchild1);
child1.addChild(grandchild2);
child2.addChild(grandchild3);

// 深度优先遍历
function traverseDepthFirst(node, visit) {
  // 访问当前节点
  visit(node);
  
  // 递归访问所有子节点
  for (const child of node.children) {
    traverseDepthFirst(child, visit);
  }
}

console.log('\nDepth-first traversal:');
traverseDepthFirst(root, node => console.log(node.value));

// 计算树的深度
function getTreeDepth(node) {
  // 基础情况:叶子节点
  if (node.children.length === 0) {
    return 1;
  }
  
  // 递归情况:1 + 最深子树的深度
  const childDepths = node.children.map(child => getTreeDepth(child));
  return 1 + Math.max(...childDepths);
}

console.log('Tree depth:', getTreeDepth(root)); // 3

// 查找节点
function findNode(node, value) {
  // 基础情况:找到目标节点
  if (node.value === value) {
    return node;
  }
  
  // 递归情况:在子节点中查找
  for (const child of node.children) {
    const found = findNode(child, value);
    if (found) {
      return found;
    }
  }
  
  // 未找到
  return null;
}

const foundNode = findNode(root, 'grandchild2');
console.log('Found node:', foundNode?.value); // grandchild2

// 收集所有叶子节点
function collectLeaves(node) {
  // 基础情况:叶子节点
  if (node.children.length === 0) {
    return [node.value];
  }
  
  // 递归情况:收集所有子树的叶子节点
  const leaves = [];
  for (const child of node.children) {
    leaves.push(...collectLeaves(child));
  }
  return leaves;
}

console.log('Leaf nodes:', collectLeaves(root)); // ['grandchild1', 'grandchild2', 'grandchild3']

尾递归优化

// 普通递归(可能导致栈溢出)
function factorialNormal(n) {
  if (n <= 1) return 1;
  return n * factorialNormal(n - 1);
}

// 尾递归版本
function factorialTail(n, accumulator = 1) {
  if (n <= 1) return accumulator;
  return factorialTail(n - 1, n * accumulator);
}

// 蹦床函数(Trampoline)- 避免栈溢出
function trampoline(fn) {
  return function(...args) {
    let result = fn.apply(this, args);
    
    while (typeof result === 'function') {
      result = result();
    }
    
    return result;
  };
}

// 使用蹦床的阶乘
function factorialTrampoline(n, acc = 1) {
  if (n <= 1) {
    return acc;
  }
  
  return () => factorialTrampoline(n - 1, n * acc);
}

const safeFactorial = trampoline(factorialTrampoline);

console.log('Normal factorial 10:', factorialNormal(10));
console.log('Tail factorial 10:', factorialTail(10));
console.log('Trampoline factorial 10:', safeFactorial(10));

// 相互递归示例
function isEven(n) {
  if (n === 0) return true;
  return isOdd(n - 1);
}

function isOdd(n) {
  if (n === 0) return false;
  return isEven(n - 1);
}

// 使用蹦床的相互递归
function isEvenTrampoline(n) {
  if (n === 0) return true;
  return () => isOddTrampoline(n - 1);
}

function isOddTrampoline(n) {
  if (n === 0) return false;
  return () => isEvenTrampoline(n - 1);
}

const safeIsEven = trampoline(isEvenTrampoline);
const safeIsOdd = trampoline(isOddTrampoline);

console.log('Is 100 even?', safeIsEven(100)); // true
console.log('Is 99 odd?', safeIsOdd(99));     // true

本章总结

本章深入探讨了JavaScript的函数和作用域:

  1. 函数基础:学习了函数声明、函数表达式、箭头函数等不同的函数定义方式
  2. 作用域:理解了全局作用域、函数作用域、块级作用域和词法作用域的概念
  3. 闭包:掌握了闭包的原理、应用场景和注意事项
  4. 高阶函数:学习了函数作为参数和返回值的高级用法
  5. 递归函数:了解了递归的基本概念、树形结构处理和尾递归优化

这些概念是JavaScript编程的核心,理解它们对于编写高质量的JavaScript代码至关重要。函数和作用域的掌握将为后续学习对象、异步编程等高级特性打下坚实的基础。

下一章我们将学习JavaScript的对象和原型。