函数基础
函数声明
// 基本函数声明
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的函数和作用域:
- 函数基础:学习了函数声明、函数表达式、箭头函数等不同的函数定义方式
- 作用域:理解了全局作用域、函数作用域、块级作用域和词法作用域的概念
- 闭包:掌握了闭包的原理、应用场景和注意事项
- 高阶函数:学习了函数作为参数和返回值的高级用法
- 递归函数:了解了递归的基本概念、树形结构处理和尾递归优化
这些概念是JavaScript编程的核心,理解它们对于编写高质量的JavaScript代码至关重要。函数和作用域的掌握将为后续学习对象、异步编程等高级特性打下坚实的基础。
下一章我们将学习JavaScript的对象和原型。