Day 5: 函数入门
🎯 学习目标
- 理解函数的概念和作用
- 掌握函数的声明、调用和参数传递
- 学会使用返回值和作用域
- 理解回调函数的应用
💡 核心概念
什么是函数?
函数是一段可以重复使用的代码块,它接收输入(参数),进行处理,然后返回输出(返回值)。函数是编程中最基本的代码组织方式。
为什么需要函数?
1. 代码复用
// ❌ 重复代码
console.log("Hello, Alice!");
console.log("Hello, Bob!");
console.log("Hello, Charlie!");
// ✅ 使用函数
function greet(name) {
console.log(`Hello, ${name}!`);
}
greet("Alice");
greet("Bob");
greet("Charlie");
2. 逻辑封装
将复杂的操作封装成函数,提高代码可读性。
3. 模块化开发
将程序分解为多个小函数,便于开发和维护。
📝 函数基础
1. 函数声明
// 函数声明(Function Declaration)
function functionName(parameter1, parameter2) {
// 函数体
return result;
}
// 示例
function add(a, b) {
return a + b;
}
2. 函数表达式
// 函数表达式(Function Expression)
const functionName = function(parameter1, parameter2) {
// 函数体
return result;
};
// 示例
const multiply = function(a, b) {
return a * b;
};
3. 箭头函数(ES6)
// 箭头函数(Arrow Function)
const functionName = (parameter1, parameter2) => {
// 函数体
return result;
};
// 简写(单行返回)
const subtract = (a, b) => a - b;
// 无参数
const sayHello = () => console.log("Hello!");
// 单参数(括号可省略)
const square = x => x * x;
🎮 参数详解
1. 默认参数
// 设置默认值
function greet(name = "World") {
console.log(`Hello, ${name}!`);
}
greet(); // "Hello, World!"
greet("Alice"); // "Hello, Alice!"
2. 剩余参数(Rest Parameters)
// 使用 ... 收集所有参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3); // 6
sum(1, 2, 3, 4, 5); // 15
3. 解构参数
// 对象解构
function createUser({name, age, city}) {
console.log(`${name}, ${age}岁,来自${city}`);
}
createUser({name: "张三", age: 25, city: "北京"});
// 数组解构
function swap([first, second]) {
return [second, first];
}
🔄 返回值
1. return 语句
function calculate(price, quantity) {
const total = price * quantity;
return total; // 返回结果
}
const result = calculate(10, 5); // 50
2. 早期返回
// ✅ 好的实践:早期返回
function getUserRole(user) {
if (!user) {
return "Guest"; // 未登录返回 Guest
}
if (user.isAdmin) {
return "Admin";
}
return "User";
}
// ❌ 不好的实践:深层嵌套
function getUserRole(user) {
if (user) {
if (user.isAdmin) {
return "Admin";
} else {
return "User";
}
} else {
return "Guest";
}
}
3. 返回多个值
// 返回数组
function getMinMax(numbers) {
return [Math.min(...numbers), Math.max(...numbers)];
}
const [min, max] = getMinMax([1, 2, 3, 4, 5]);
// 返回对象(更清晰)
function getPersonInfo(name) {
return {
firstName: name.split(" ")[0],
lastName: name.split(" ")[1],
length: name.length
};
}
📦 作用域
1. 全局作用域 vs 局部作用域
const globalVar = "全局变量";
function testScope() {
const localVar = "局部变量";
console.log(globalVar); // ✅ 可以访问
console.log(localVar); // ✅ 可以访问
}
console.log(globalVar); // ✅ 可以访问
console.log(localVar); // ❌ 报错:未定义
2. 变量遮蔽
const x = 10; // 全局变量
function example() {
const x = 20; // 局部变量,遮蔽全局变量
console.log(x); // 20
}
example();
console.log(x); // 10
3. 块级作用域(let 和 const)
function test() {
if (true) {
const blockScoped = "块级变量";
let blockLet = "也是块级变量";
var functionScoped = "函数级变量";
}
// console.log(blockScoped); // ❌ 报错
// console.log(blockLet); // ❌ 报错
console.log(functionScoped); // ✅ 可以访问
}
🎯 实战示例
示例 1:表单验证函数
// 验证邮箱
function validateEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
// 验证密码强度
function validatePassword(password) {
if (password.length < 8) {
return {valid: false, message: "密码至少8位"};
}
if (!/[A-Z]/.test(password)) {
return {valid: false, message: "需要包含大写字母"};
}
if (!/[0-9]/.test(password)) {
return {valid: false, message: "需要包含数字"};
}
return {valid: true, message: "密码强度合格"};
}
// 使用
const email = "user@example.com";
if (validateEmail(email)) {
console.log("邮箱格式正确");
}
示例 2:DOM 操作封装
// 创建元素的辅助函数
function createElement(tag, options = {}) {
const element = document.createElement(tag);
// 设置属性
if (options.id) element.id = options.id;
if (options.className) element.className = options.className;
if (options.text) element.textContent = options.text;
if (options.html) element.innerHTML = options.html;
// 添加事件监听
if (options.onClick) {
element.addEventListener('click', options.onClick);
}
return element;
}
// 使用
const button = createElement('button', {
text: '点击我',
className: 'btn btn-primary',
onClick: () => alert('被点击了!')
});
document.body.appendChild(button);
示例 3:数据转换函数
// 格式化货币
function formatCurrency(amount, currency = 'CNY') {
const symbols = {
'CNY': '¥',
'USD': '$',
'EUR': '€'
};
return `${symbols[currency]}${amount.toFixed(2)}`;
}
// 格式化日期
function formatDate(date, format = 'YYYY-MM-DD') {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day);
}
// 使用
console.log(formatCurrency(99.9)); // "¥99.90"
console.log(formatDate(new Date())); // "2026-03-07"
🔄 回调函数
什么是回调函数?
回调函数是作为参数传递给另一个函数的函数,在特定事件发生时被调用。
// 定时器回调
setTimeout(() => {
console.log("1秒后执行");
}, 1000);
// 数组方法回调
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]
// 事件监听回调
button.addEventListener('click', function() {
console.log("按钮被点击");
});
自定义回调函数
// 数据加载函数(模拟异步)
function loadData(callback) {
console.log("开始加载数据...");
setTimeout(() => {
const data = {name: "张三", age: 25};
callback(data); // 数据加载完成后调用回调
}, 1000);
}
// 使用
loadData(function(data) {
console.log("数据加载完成:", data);
});
⚠️ 常见错误
1. 忘记 return
// ❌ 错误:没有 return
function add(a, b) {
a + b;
}
console.log(add(2, 3)); // undefined
// ✅ 正确:加上 return
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
2. 修改全局变量
// ❌ 不好:修改全局变量
let count = 0;
function increment() {
count++;
}
// ✅ 更好:使用参数和返回值
function increment(count) {
return count + 1;
}
3. 参数过多
// ❌ 参数太多,难以维护
function createUser(name, age, email, phone, address, city) {
// ...
}
// ✅ 使用对象参数
function createUser(options) {
const {name, age, email, phone, address, city} = options;
// ...
}
✍️ 练习任务
练习 1:基础函数
创建以下函数:
celsiusToFahrenheit(celsius)– 摄氏度转华氏度calculateTriangleArea(base, height)– 计算三角形面积isEven(number)– 判断数字是否为偶数
练习 2:数组处理函数
创建以下函数:
findMax(numbers)– 找出数组最大值filterPositive(numbers)– 过滤出正数reverseArray(arr)– 反转数组(不使用 reverse())
练习 3:字符串处理函数
创建以下函数:
capitalize(str)– 首字母大写truncate(str, length)– 截断字符串并添加 "…"countWords(str)– 统计单词数量
🎓 今日挑战
项目:简易计算器
创建一个网页计算器,实现以下功能:
-
基本运算
- 加法:
add(a, b) - 减法:
subtract(a, b) - 乘法:
multiply(a, b) - 除法:
divide(a, b)
- 加法:
-
高级运算
- 幂运算:
power(base, exponent) - 平方根:
sqrt(number) - 取余:
modulo(a, b)
- 幂运算:
-
辅助函数
- 输入验证:
validateInput(value) - 格式化结果:
formatResult(number) - 错误处理:处理除零错误
- 输入验证:
-
UI 界面
- 创建按钮和显示区域
- 绑定点击事件
- 显示计算结果
提示:
- 使用函数封装每个运算
- 使用对象存储计算历史
- 使用回调函数处理按钮点击
💡 最佳实践
1. 单一职责原则
每个函数只做一件事,做好一件事。
2. 函数命名
- 使用动词开头:
getUser(),calculateTotal() - 命名要清晰:
x→userData,temp→temperature
3. 参数数量
- 最好不超过 3-4 个参数
- 参数过多时使用对象
4. 纯函数优先
纯函数:相同输入总是得到相同输出,无副作用。
// ✅ 纯函数
function add(a, b) {
return a + b;
}
// ❌ 非纯函数(有副作用)
function addAndLog(a, b) {
const result = a + b;
console.log(result); // 副作用
return result;
}
📚 知识拓展
高阶函数
高阶函数是接收函数作为参数或返回函数的函数。
// 接收函数作为参数
function calculate(operation, a, b) {
return operation(a, b);
}
calculate((x, y) => x + y, 2, 3); // 5
calculate((x, y) => x * y, 2, 3); // 6
// 返回函数
function createMultiplier(multiplier) {
return function(x) {
return x * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
double(5); // 10
triple(5); // 15
递归函数
函数调用自身。
// 计算阶乘
function factorial(n) {
if (n <= 1) return 1; // 基准情况
return n * factorial(n - 1); // 递归调用
}
factorial(5); // 120
学习时间: 2026-03-07 13:05
难度: ⭐⭐⭐☆☆
预计用时: 2-3 小时
关键词: 函数, 参数, 返回值, 作用域, 回调函数, 箭头函数
相关标签: #04-函数