JavaScript函数精讲:从基础用法到高级应用
一、函数的基本概念
1.1 什么是函数?
函数是JavaScript中的一等公民,是一段可重复使用的代码块,用于执行特定任务。函数可以接收输入(参数),并返回输出(返回值)。
// 简单的函数示例
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet('Alice')); // 输出: Hello, Alice!
1.2 为什么需要函数?
代码复用:避免重复编写相同代码模块化:将复杂问题分解为小功能单元可维护性:便于调试和修改抽象:隐藏实现细节,暴露清晰接口
二、函数的多种定义方式
2.1 函数声明(Function Declaration)
function sum(a, b) {
return a + b;
}
特点:
存在函数提升(可以在声明前调用)必须有函数名
2.2 函数表达式(Function Expression)
const multiply = function(a, b) {
return a * b;
};
特点:
不存在提升可以是匿名函数更灵活,可作为参数传递
2.3 箭头函数(Arrow Function,ES6+)
const divide = (a, b) => a / b;
特点:
更简洁的语法没有自己的this、arguments、super或new.target适合简单的回调函数
2.4 立即执行函数表达式(IIFE)
(function() {
console.log('立即执行');
})();
应用场景:
创建独立作用域模块化开发(在ES6模块之前)避免污染全局命名空间
三、函数参数详解
3.1 参数传递机制
JavaScript采用按值传递,但对于对象类型,传递的是引用的副本。
function updateName(person) {
person.name = 'Alice';
}
const bob = { name: 'Bob' };
updateName(bob);
console.log(bob.name); // 输出: Alice
3.2 默认参数(ES6+)
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
3.3 剩余参数(Rest Parameters)
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
3.4 参数解构
function printUser({ name, age }) {
console.log(`${name} is ${age} years old`);
}
printUser({ name: 'Bob', age: 25 });
四、作用域与闭包
4.1 作用域链
JavaScript采用词法作用域(静态作用域),函数的作用域在定义时确定。
let global = 'global';
function outer() {
let outerVar = 'outer';
function inner() {
let innerVar = 'inner';
console.log(global); // 可以访问
console.log(outerVar); // 可以访问
console.log(innerVar); // 可以访问
}
inner();
}
outer();
4.2 闭包(Closure)
闭包是指函数能够记住并访问其词法作用域,即使函数在其词法作用域之外执行。
function createCounter() {
let count = 0;
return {
increment() {
return ++count;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
4.3 闭包的实际应用
数据私有化:实现私有变量函数工厂:创建特定功能的函数模块模式:组织代码结构记忆化:缓存计算结果
五、this关键字
5.1 this的绑定规则
默认绑定:全局对象(严格模式下为undefined)隐式绑定:调用上下文对象显式绑定:call/apply/bindnew绑定:构造函数调用
const person = {
name: 'Alice',
greet: function() {
console.log(`Hello, ${this.name}`);
}
};
person.greet(); // Hello, Alice
5.2 箭头函数的this
箭头函数没有自己的this,它继承自外层函数作用域。
const timer = {
seconds: 0,
start() {
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
};
六、高阶函数
6.1 什么是高阶函数?
接收函数作为参数或返回函数作为结果的函数。
// 接收函数作为参数
function operate(a, b, operation) {
return operation(a, b);
}
// 返回函数
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
6.2 常见的高阶函数模式
回调函数:异步编程基础函数组合:将多个函数组合成一个柯里化:将多参数函数转换为一系列单参数函数装饰器:增强函数功能
七、递归函数
7.1 基本概念
函数调用自身的过程。
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
7.2 尾调用优化(Tail Call Optimization)
ES6规范中提出,但浏览器实现有限。
function factorial(n, acc = 1) {
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}
八、最佳实践
单一职责原则:一个函数只做一件事合理命名:使用动词+名词形式,如calculateTotal控制函数长度:一般不超过20行避免副作用:纯函数更易于测试和维护适当注释:解释复杂逻辑
九、常见问题解答
Q1: 箭头函数和普通函数有什么区别?
箭头函数没有自己的this、arguments箭头函数不能用作构造函数箭头函数没有prototype属性箭头函数不能用作生成器函数
Q2: 什么时候该用闭包?
需要私有变量时需要保持状态时需要延迟执行时需要函数工厂时
Q3: 如何避免this的绑定问题?
使用箭头函数使用bind明确绑定使用类字段语法(ES2022+)
十、实战练习
实现一个记忆化函数
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(...args);
cache.set(key, result);
return result;
};
}
实现简单的函数组合
function compose(...fns) {
return function(initialValue) {
return fns.reduceRight((value, fn) => fn(value), initialValue);
};
}
总结
函数是JavaScript编程的核心概念,掌握函数的各种特性和用法对于写出高质量的代码至关重要。从基础的函数定义到高级的闭包应用,理解这些概念将大大提升你的编程能力。
