函数基础

函数定义

函数是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对比

// arguments对象
function oldWay() {
    console.log(arguments);  // 类数组对象
    console.log(arguments.length);
}

// 剩余参数(推荐)
function newWay(...args) {
    console.log(args);  // 真正的数组
    console.log(args.length);
}
特性 arguments 剩余参数 东巴文建议
类型 类数组 真数组 -
箭头函数 -
灵活性 固定 可命名 用剩余参数
可读性 较差 -

arguments对象

函数内部可访问arguments对象。

基本用法

function showArguments() {
    console.log(arguments.length);  // 参数个数
    console.log(arguments[0]);      // 第一个参数
    console.log(arguments[1]);      // 第二个参数
}

showArguments("东", "巴", "文");  // 3 "东" "巴"

遍历arguments

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;
}

箭头函数没有arguments

const arrow = () => {
    console.log(arguments);  // ReferenceError 或 外层arguments
};

// 使用剩余参数替代
const arrow2 = (...args) => {
    console.log(args);  // 正常工作
};

下一步

掌握了函数基础后,让我们继续学习:

  1. 箭头函数 - 学习箭头函数
  2. 作用域与闭包 - 学习作用域
  3. 高阶函数 - 学习高阶函数

东巴文(db-w.cn) - 让编程学习更简单

🎯 东巴文寄语:函数是JavaScript的核心,理解函数的定义、调用、参数和返回值是掌握JavaScript的基础。在 db-w.cn,我们帮你打好坚实的基础!