函数是JavaScript中的一等公民,可以像其他值一样使用。
函数是一段可重复使用的代码块,接收输入、执行操作、返回输出。
// 函数的基本组成
function functionName(parameters) {
// 函数体
return value;
}
// 代码复用
function greet(name) {
console.log(`你好,${name}!`);
}
greet("东巴文"); // 你好,东巴文!
greet("JavaScript"); // 你好,JavaScript!
// 抽象和封装
function calculateTotal(items) {
let total = 0;
for (let item of items) {
total += item.price * item.quantity;
}
return total;
}
函数声明是最常见的定义函数的方式。
function functionName(parameters) {
// 函数体
}
// 示例
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // 3
函数声明会被提升到作用域顶部。
// 可以在声明前调用
console.log(add(1, 2)); // 3
function add(a, b) {
return a + b;
}
// 动词开头,描述行为
function getUser() { }
function calculateTotal() { }
function validateEmail() { }
// 布尔值返回用is/has/can开头
function isValid() { }
function hasPermission() { }
function canEdit() { }
// 事件处理用handle前缀
function handleClick() { }
function handleSubmit() { }
函数表达式将函数赋值给变量。
const functionName = function(parameters) {
// 函数体
};
// 示例
const add = function(a, b) {
return a + b;
};
console.log(add(1, 2)); // 3
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1); // 内部递归使用
};
console.log(factorial(5)); // 120
// 函数声明:提升
console.log(declared()); // "declared"
function declared() {
return "declared";
}
// 函数表达式:不提升
console.log(expressed); // undefined
// expressed(); // TypeError
var expressed = function() {
return "expressed";
};
| 特性 | 函数声明 | 函数表达式 | 东巴文建议 |
|---|---|---|---|
| 提升 | 是 | 否 | - |
| 使用时机 | 声明前可用 | 声明后可用 | - |
| 匿名 | 不可以 | 可以 | - |
| 适用场景 | 通用函数 | 回调、闭包 | 按需选择 |
函数定义后需要调用才能执行。
function greet(name) {
console.log(`你好,${name}!`);
}
greet("东巴文"); // 直接调用
// 作为函数调用
function add(a, b) {
return a + b;
}
add(1, 2);
// 作为方法调用
const obj = {
name: "东巴文",
greet() {
console.log(`你好,${this.name}!`);
}
};
obj.greet();
// 使用call调用
function showThis() {
console.log(this);
}
showThis.call({ name: "东巴文" });
// 使用apply调用
showThis.apply({ name: "JavaScript" });
// 使用bind创建新函数
const bound = showThis.bind({ name: "绑定" });
bound();
// IIFE (Immediately Invoked Function Expression)
(function() {
console.log("立即执行");
})();
// 带参数
(function(name) {
console.log(`你好,${name}!`);
})("东巴文");
// 箭头函数IIFE
(() => {
console.log("箭头函数IIFE");
})();
函数可以使用return返回值。
function add(a, b) {
return a + b;
}
const result = add(1, 2);
console.log(result); // 3
function greet(name) {
console.log(`你好,${name}!`);
// 没有return语句,返回undefined
}
console.log(greet("东巴文")); // undefined
// 返回数组
function getCoords() {
return [10, 20];
}
const [x, y] = getCoords();
// 返回对象
function getUser() {
return {
name: "东巴文",
age: 1
};
}
const { name, age } = getUser();
function divide(a, b) {
if (b === 0) {
return "除数不能为零"; // 提前返回
}
return a / b;
}
// 卫语句模式
function processUser(user) {
if (!user) return null;
if (!user.name) return "缺少姓名";
if (!user.email) return "缺少邮箱";
return processValidUser(user);
}
函数可以接收参数作为输入。
function greet(name, message) {
console.log(`${message},${name}!`);
}
greet("东巴文", "欢迎"); // 欢迎,东巴文!
function add(a, b) {
console.log(a, b);
}
add(1); // 1 undefined
add(1, 2); // 1 2
add(1, 2, 3); // 1 2 (第三个参数被忽略)
function greet(name) {
if (name === undefined) {
name = "访客";
}
console.log(`你好,${name}!`);
}
// 更简洁的写法
function greet(name = "访客") {
console.log(`你好,${name}!`);
}
ES6支持参数默认值。
function greet(name = "访客") {
console.log(`你好,${name}!`);
}
greet(); // 你好,访客!
greet("东巴文"); // 你好,东巴文!
// 默认值可以是表达式
function getValue(value = getDefault()) {
return value;
}
function getDefault() {
return "默认值";
}
// 默认值可以是其他参数
function greet(name, message = `你好,${name}`) {
console.log(message);
}
greet("东巴文"); // 你好,东巴文
// 对象参数默认值
function createUser({ name = "匿名", age = 0 } = {}) {
return { name, age };
}
createUser(); // { name: "匿名", age: 0 }
createUser({ name: "东巴文" }); // { name: "东巴文", age: 0 }
// 数组参数默认值
function getFirst([first = "默认"] = []) {
return first;
}
// 默认值参数应该在后面
function api(path, method = "GET", timeout = 5000) {
console.log(path, method, timeout);
}
api("/users"); // /users GET 5000
api("/users", "POST"); // /users POST 5000
api("/users", "POST", 3000); // /users POST 3000
剩余参数收集多余的参数。
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(1, 2, 3, 4, 5); // 15
function log(level, ...messages) {
console.log(`[${level}]`, ...messages);
}
log("INFO", "用户登录", "ID: 123"); // [INFO] 用户登录 ID: 123
// arguments对象
function oldWay() {
console.log(arguments); // 类数组对象
console.log(arguments.length);
}
// 剩余参数(推荐)
function newWay(...args) {
console.log(args); // 真正的数组
console.log(args.length);
}
| 特性 | arguments | 剩余参数 | 东巴文建议 |
|---|---|---|---|
| 类型 | 类数组 | 真数组 | - |
| 箭头函数 | 无 | 有 | - |
| 灵活性 | 固定 | 可命名 | 用剩余参数 |
| 可读性 | 较差 | 好 | - |
函数内部可访问arguments对象。
function showArguments() {
console.log(arguments.length); // 参数个数
console.log(arguments[0]); // 第一个参数
console.log(arguments[1]); // 第二个参数
}
showArguments("东", "巴", "文"); // 3 "东" "巴"
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
sum(1, 2, 3, 4, 5); // 15
function toArray() {
// Array.from
const arr1 = Array.from(arguments);
// 展开运算符
const arr2 = [...arguments];
// slice
const arr3 = Array.prototype.slice.call(arguments);
return arr1;
}
const arrow = () => {
console.log(arguments); // ReferenceError 或 外层arguments
};
// 使用剩余参数替代
const arrow2 = (...args) => {
console.log(args); // 正常工作
};
掌握了函数基础后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:函数是JavaScript的核心,理解函数的定义、调用、参数和返回值是掌握JavaScript的基础。在 db-w.cn,我们帮你打好坚实的基础!