JavaScript 函数
函数是 JavaScript 中的基本构建块,用于封装可重复使用的代码。函数可以接收输入参数,执行特定任务,并返回结果。理解函数的概念和使用方法对于编写模块化、可维护的 JavaScript 代码至关重要。在本章节中,我们将深入学习 JavaScript 中的函数。
什么是函数
函数是一段可重复使用的代码块,用于执行特定任务。函数可以接收输入(参数),处理数据,并返回结果。函数的主要优势包括:
- 代码重用:避免重复编写相同代码
- 模块化:将复杂问题分解为小的、可管理的部分
- 可维护性:集中修改,影响所有调用点
- 可读性:通过函数名表达代码意图
函数的定义方式
1. 函数声明(Function Declaration)
javascript
function greet(name) {
return "你好," + name + "!";
}
// 调用函数
console.log(greet("张三")); // "你好,张三!"2. 函数表达式(Function Expression)
javascript
const greet = function(name) {
return "你好," + name + "!";
};
// 调用函数
console.log(greet("李四")); // "你好,李四!"3. 箭头函数(Arrow Function)- ES6
javascript
const greet = (name) => {
return "你好," + name + "!";
};
// 简化写法
const greetSimple = (name) => "你好," + name + "!";
// 单参数可省略括号
const greetMinimal = name => "你好," + name + "!";
// 调用函数
console.log(greet("王五")); // "你好,王五!"4. 构造函数方式
javascript
const greet = new Function("name", "return '你好,' + name + '!';");
console.log(greet("赵六")); // "你好,赵六!"函数的组成部分
函数名
函数名用于标识和调用函数:
javascript
function calculateSum(a, b) {
return a + b;
}
// 函数名应具有描述性
function getUserInfo() { /* ... */ }
function validateForm() { /* ... */ }
function formatDate() { /* ... */ }参数(Parameters)
参数是函数接收的输入值:
javascript
// 单个参数
function square(x) {
return x * x;
}
// 多个参数
function add(a, b) {
return a + b;
}
// 无参数
function getCurrentTime() {
return new Date();
}返回值(Return Value)
函数可以返回值给调用者:
javascript
function multiply(a, b) {
return a * b; // 返回计算结果
}
function greet(name) {
console.log("你好," + name + "!"); // 无返回值,返回 undefined
}
const result = multiply(5, 3); // 15
const greeting = greet("张三"); // undefined函数调用
基本调用
javascript
function sayHello() {
return "Hello!";
}
const message = sayHello(); // 调用函数
console.log(message); // "Hello!"带参数调用
javascript
function add(a, b) {
return a + b;
}
const sum = add(5, 3); // 传递参数
console.log(sum); // 8方法调用
javascript
const calculator = {
add: function(a, b) {
return a + b;
},
multiply(a, b) { // ES6 简写
return a * b;
}
};
const result1 = calculator.add(5, 3); // 8
const result2 = calculator.multiply(4, 2); // 8参数处理
默认参数(ES6)
javascript
function greet(name = "朋友") {
return "你好," + name + "!";
}
console.log(greet()); // "你好,朋友!"
console.log(greet("张三")); // "你好,张三!"剩余参数(Rest Parameters)- ES6
javascript
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15参数解构
javascript
// 对象解构参数
function createUser({ name, age, email }) {
return {
name: name,
age: age,
email: email,
createdAt: new Date()
};
}
const user = createUser({
name: "张三",
age: 25,
email: "zhangsan@example.com"
});
// 数组解构参数
function processCoordinates([x, y]) {
return {
x: x,
y: y,
distance: Math.sqrt(x * x + y * y)
};
}
const point = processCoordinates([3, 4]);
console.log(point.distance); // 5函数作用域
全局作用域
javascript
const globalVar = "全局变量";
function example() {
console.log(globalVar); // 可以访问全局变量
}
example();函数作用域
javascript
function outer() {
const outerVar = "外部变量";
function inner() {
const innerVar = "内部变量";
console.log(outerVar); // 可以访问外部变量
console.log(innerVar); // 可以访问内部变量
}
inner();
// console.log(innerVar); // 错误:无法访问内部变量
}
outer();块级作用域(ES6)
javascript
function example() {
if (true) {
const blockVar = "块级变量";
let blockLet = "块级 let 变量";
var functionVar = "函数变量"; // 函数作用域
}
// console.log(blockVar); // 错误:无法访问
// console.log(blockLet); // 错误:无法访问
console.log(functionVar); // 可以访问
}闭包(Closure)
闭包是指函数可以访问其外部作用域中的变量:
javascript
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// 每个闭包都有独立的作用域
const counter2 = createCounter();
console.log(counter2()); // 1
console.log(counter()); // 4闭包的实际应用
javascript
// 模块模式
const userManager = (function() {
let users = [];
return {
addUser: function(user) {
users.push(user);
},
getUsers: function() {
return users;
},
getUserCount: function() {
return users.length;
}
};
})();
userManager.addUser("张三");
userManager.addUser("李四");
console.log(userManager.getUsers()); // ["张三", "李四"]
console.log(userManager.getUserCount()); // 2高阶函数
高阶函数是接收函数作为参数或返回函数的函数:
接收函数作为参数
javascript
function calculate(a, b, operation) {
return operation(a, b);
}
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
console.log(calculate(5, 3, add)); // 8
console.log(calculate(5, 3, multiply)); // 15返回函数
javascript
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15立即执行函数表达式(IIFE)
IIFE 是定义后立即执行的函数:
javascript
// 基本形式
(function() {
console.log("IIFE 执行了");
})();
// 带参数的 IIFE
(function(name) {
console.log("你好," + name + "!");
})("张三");
// 返回值的 IIFE
const result = (function(a, b) {
return a + b;
})(5, 3);
console.log(result); // 8递归函数
递归函数是调用自身的函数:
javascript
// 计算阶乘
function factorial(n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
// 斐波那契数列
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10)); // 55函数的 this 关键字
[this](file:///C:/Workspace/Coding/WebProjects/tutorials-web/node_modules/typescript/lib/lib.es5.d.ts#L78-L82) 关键字的值取决于函数的调用方式:
全局上下文
javascript
console.log(this); // 浏览器中是 window,Node.js 中是 global对象方法
javascript
const person = {
name: "张三",
greet: function() {
return "你好,我是" + this.name;
}
};
console.log(person.greet()); // "你好,我是张三"箭头函数中的 this
javascript
const person = {
name: "李四",
greet: function() {
// 普通函数
console.log("普通函数:" + this.name);
// 箭头函数
const arrowFunction = () => {
console.log("箭头函数:" + this.name);
};
arrowFunction();
}
};
person.greet();
// 输出:
// 普通函数:李四
// 箭头函数:李四函数方法
call() 方法
javascript
function greet(greeting, punctuation) {
return greeting + ",我是" + this.name + punctuation;
}
const person = { name: "张三" };
const result = greet.call(person, "你好", "!");
console.log(result); // "你好,我是张三!"apply() 方法
javascript
function sum(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
const result = sum.apply(null, numbers);
console.log(result); // 6bind() 方法
javascript
function greet(greeting) {
return greeting + ",我是" + this.name;
}
const person = { name: "李四" };
const boundGreet = greet.bind(person);
console.log(boundGreet("你好")); // "你好,我是李四"函数的最佳实践
1. 函数命名
javascript
// 好的命名:动词开头,描述性
function calculateTotal() { /* ... */ }
function validateForm() { /* ... */ }
function getUserInfo() { /* ... */ }
function formatDate() { /* ... */ }
// 不好的命名
function doIt() { /* ... */ }
function process() { /* ... */ }
function handle() { /* ... */ }2. 函数长度控制
javascript
// 保持函数简短,单一职责
function calculateTax(income) {
if (income <= 5000) return 0;
if (income <= 10000) return (income - 5000) * 0.1;
return 500 + (income - 10000) * 0.2;
}
// 复杂逻辑分解为多个函数
function processOrder(order) {
validateOrder(order);
calculateTotal(order);
applyDiscount(order);
saveOrder(order);
}3. 参数处理
javascript
// 使用对象参数处理多个参数
function createUser({ name, age, email, phone }) {
// 参数验证
if (!name || !email) {
throw new Error("姓名和邮箱是必需的");
}
return {
name,
age: age || 0,
email,
phone: phone || "",
createdAt: new Date()
};
}4. 错误处理
javascript
function divide(a, b) {
if (b === 0) {
throw new Error("除数不能为零");
}
return a / b;
}
try {
const result = divide(10, 0);
} catch (error) {
console.log("错误:" + error.message);
}实际应用示例
事件处理函数
javascript
// 通用事件处理函数
function createEventHandler(handler, context = null) {
return function(event) {
try {
handler.call(context, event);
} catch (error) {
console.error("事件处理错误:", error);
}
};
}
// 使用示例
const button = document.getElementById("myButton");
const handleClick = createEventHandler(function(event) {
console.log("按钮被点击了");
}, this);
button.addEventListener("click", handleClick);数据处理函数
javascript
// 通用数据处理管道
function createPipeline(...functions) {
return function(data) {
return functions.reduce((result, func) => func(result), data);
};
}
// 数据处理函数
function validate(data) {
if (!data || typeof data !== "object") {
throw new Error("无效数据");
}
return data;
}
function transform(data) {
return {
...data,
processedAt: new Date(),
processed: true
};
}
function log(data) {
console.log("处理数据:", data);
return data;
}
// 创建处理管道
const processData = createPipeline(validate, transform, log);
// 使用示例
try {
const result = processData({ name: "张三", age: 25 });
console.log("处理结果:", result);
} catch (error) {
console.error("处理失败:", error.message);
}函数式编程工具
javascript
// 函数式编程工具函数
const utils = {
// 映射函数
map: function(array, transform) {
const result = [];
for (let i = 0; i < array.length; i++) {
result.push(transform(array[i], i));
}
return result;
},
// 过滤函数
filter: function(array, predicate) {
const result = [];
for (let item of array) {
if (predicate(item)) {
result.push(item);
}
}
return result;
},
// 归约函数
reduce: function(array, reducer, initialValue) {
let accumulator = initialValue;
for (let item of array) {
accumulator = reducer(accumulator, item);
}
return accumulator;
}
};
// 使用示例
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbers = utils.filter(numbers, n => n % 2 === 0);
console.log("偶数:", evenNumbers); // [2, 4, 6, 8, 10]
const squares = utils.map(numbers, n => n * n);
console.log("平方:", squares); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
const sum = utils.reduce(numbers, (acc, n) => acc + n, 0);
console.log("总和:", sum); // 55总结
JavaScript 函数的核心要点:
- 定义方式:函数声明、函数表达式、箭头函数、构造函数
- 组成部分:函数名、参数、返回值、函数体
- 调用方式:基本调用、方法调用、构造调用
- 参数处理:默认参数、剩余参数、参数解构
- 作用域:全局作用域、函数作用域、块级作用域
- 高级特性:闭包、高阶函数、递归、IIFE
- this 关键字:不同调用方式下的 this 值
- 函数方法:call()、apply()、bind()
- 最佳实践:命名规范、长度控制、错误处理
函数是 JavaScript 编程的核心,掌握函数的使用对于编写高质量的 JavaScript 代码至关重要。在下一章节中,我们将学习 JavaScript 的作用域。