JavaScript 函数基础

概述

函数是JavaScript中的基本构建块,用于封装可重用的代码逻辑。JavaScript中函数是一等公民,可以作为值传递、存储和操作。

函数声明

基本语法

function functionName(parameters) {
    // 函数体
    return value; // 可选
}

函数声明示例

// 基本函数声明
function greet(name) {
    return `Hello, ${name}!`;
}
 
// 多参数函数
function add(a, b) {
    return a + b;
}
 
// 无返回值函数
function logMessage(message) {
    console.log(message);
}
 
// 默认参数(ES6+)
function greetWithDefault(name = "World") {
    return `Hello, ${name}!`;
}

函数提升

// 函数声明会被提升,可以在声明前调用
console.log(sum(1, 2)); // 3 - 正常工作
 
function sum(a, b) {
    return a + b;
}

函数表达式

基本语法

const functionName = function(parameters) {
    // 函数体
    return value;
};

函数表达式示例

// 匿名函数表达式
const multiply = function(a, b) {
    return a * b;
};
 
// 具名函数表达式(便于调试)
const divide = function divide(a, b) {
    if (b === 0) {
        throw new Error('Division by zero');
    }
    return a / b;
};
 
// 立即执行函数表达式(IIFE)
const result = (function(x, y) {
    return x + y;
})(5, 3);

函数表达式的提升

// 错误:函数表达式不会提升
console.log(subtract(5, 3)); // TypeError: subtract is not a function
 
const subtract = function(a, b) {
    return a - b;
};

箭头函数(ES6+)

基本语法

const functionName = (parameters) => {
    // 函数体
    return value;
};
 
// 简写形式
const functionName = parameter => expression;
const functionName = (a, b) => a + b;

箭头函数示例

// 基本箭头函数
const square = x => x * x;
 
// 多参数箭头函数
const add = (a, b) => a + b;
 
// 无参数箭头函数
const getCurrentTime = () => new Date().getTime();
 
// 返回对象的箭头函数(需要括号)
const createUser = (name, age) => ({ name, age });
 
// 多行箭头函数
const processData = data => {
    const processed = data.map(item => item * 2);
    return processed.filter(item => item > 10);
};

箭头函数的限制

// 1. 没有自己的this
const obj = {
    name: 'Object',
    regularMethod: function() {
        console.log(this.name); // 'Object'
    },
    arrowMethod: () => {
        console.log(this.name); // undefined(或全局对象的name)
    }
};
 
// 2. 不能作为构造函数
const Person = (name) => {
    this.name = name; // 错误用法
};
// new Person('John'); // TypeError
 
// 3. 没有arguments对象
function regularFunc() {
    console.log(arguments); // Arguments对象
}
 
const arrowFunc = () => {
    console.log(arguments); // ReferenceError
};
 
// 使用剩余参数替代
const arrowWithRest = (...args) => {
    console.log(args); // 数组
};

参数处理

默认参数

// ES6之前的方法
function greetOld(name) {
    name = name || 'World';
    return `Hello, ${name}!`;
}
 
// ES6默认参数
function greet(name = 'World') {
    return `Hello, ${name}!`;
}
 
// 复杂默认值
function createUser(name, age = 18, active = true) {
    return { name, age, active };
}
 
// 使用函数作为默认值
function log(message, timestamp = Date.now()) {
    console.log(`[${timestamp}] ${message}`);
}

剩余参数

// 收集多余参数
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}
 
console.log(sum(1, 2, 3, 4, 5)); // 15
 
// 与普通参数结合
function introduce(name, ...hobbies) {
    console.log(`我是${name}`);
    if (hobbies.length > 0) {
        console.log(`我的爱好是:${hobbies.join('、')}`);
    }
}
 
introduce('张三', '阅读', '游泳', '编程');

参数解构

// 对象参数解构
function createUser({ name, age = 18, email }) {
    return { name, age, email };
}
 
createUser({ name: '张三', email: 'zhang@example.com' });
 
// 数组参数解构
function getCoordinates([x, y, z = 0]) {
    return { x, y, z };
}
 
getCoordinates([1, 2]); // { x: 1, y: 2, z: 0 }

返回值

基本返回值

// 明确返回值
function add(a, b) {
    return a + b;
}
 
// 条件返回
function getAbsoluteValue(num) {
    if (num >= 0) {
        return num;
    } else {
        return -num;
    }
}
 
// 早期返回
function validateUser(user) {
    if (!user) return { valid: false, error: '用户不存在' };
    if (!user.name) return { valid: false, error: '姓名为空' };
    if (!user.email) return { valid: false, error: '邮箱为空' };
    
    return { valid: true };
}

隐式返回

// 函数没有return语句,隐式返回undefined
function logMessage(msg) {
    console.log(msg);
    // 隐式返回undefined
}
 
// 箭头函数的隐式返回
const double = x => x * 2; // 隐式返回x * 2
 
// 返回对象需要括号
const createPoint = (x, y) => ({ x, y });

作用域和闭包

函数作用域

function outerFunction(x) {
    const outerVariable = x;
    
    function innerFunction(y) {
        const innerVariable = y;
        console.log(outerVariable); // 可以访问外部变量
        console.log(innerVariable);
    }
    
    innerFunction(20);
    // console.log(innerVariable); // 错误:不能访问内部变量
}
 
outerFunction(10);

闭包

// 基本闭包
function createCounter() {
    let count = 0;
    
    return function() {
        count++;
        return count;
    };
}
 
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
 
// 闭包的实际应用:模块模式
function createCalculator() {
    let result = 0;
    
    return {
        add: (x) => { result += x; return result; },
        subtract: (x) => { result -= x; return result; },
        multiply: (x) => { result *= x; return result; },
        divide: (x) => { result /= x; return result; },
        clear: () => { result = 0; return result; },
        getResult: () => result
    };
}
 
const calc = createCalculator();
calc.add(10).multiply(2).subtract(5); // 链式调用
console.log(calc.getResult()); // 15

高阶函数

函数作为参数

// 基本示例
function processArray(arr, callback) {
    const result = [];
    for (const item of arr) {
        result.push(callback(item));
    }
    return result;
}
 
const numbers = [1, 2, 3, 4, 5];
const doubled = processArray(numbers, x => x * 2);
 
// 内置高阶函数
const evenNumbers = numbers.filter(x => x % 2 === 0);
const squared = numbers.map(x => x * x);
const sum = numbers.reduce((acc, x) => acc + x, 0);

函数作为返回值

// 函数工厂
function createValidator(min, max) {
    return function(value) {
        return value >= min && value <= max;
    };
}
 
const ageValidator = createValidator(18, 65);
console.log(ageValidator(25)); // true
console.log(ageValidator(15)); // false
 
// 偏函数应用
function multiply(a, b) {
    return a * b;
}
 
function partial(fn, ...args1) {
    return function(...args2) {
        return fn(...args1, ...args2);
    };
}
 
const double = partial(multiply, 2);
console.log(double(5)); // 10

递归函数

基本递归

// 计算阶乘
function factorial(n) {
    if (n <= 1) {
        return 1; // 基础情况
    }
    return n * factorial(n - 1); // 递归调用
}
 
// 斐波那契数列
function fibonacci(n) {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}
 
// 优化的斐波那契(避免重复计算)
function fibonacciOptimized(n, memo = {}) {
    if (n in memo) {
        return memo[n];
    }
    
    if (n <= 1) {
        return n;
    }
    
    memo[n] = fibonacciOptimized(n - 1, memo) + fibonacciOptimized(n - 2, memo);
    return memo[n];
}

递归遍历

// 遍历嵌套对象
function traverse(obj, callback) {
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            callback(key, obj[key]);
            
            if (typeof obj[key] === 'object' && obj[key] !== null) {
                traverse(obj[key], callback);
            }
        }
    }
}
 
const data = {
    name: 'root',
    children: {
        child1: { value: 1 },
        child2: { value: 2, nested: { deep: 'value' } }
    }
};
 
traverse(data, (key, value) => {
    console.log(`${key}: ${value}`);
});

最佳实践

1. 函数命名

// 使用动词开头的描述性名称
function calculateTotalPrice(items) { /* ... */ }
function validateEmailAddress(email) { /* ... */ }
function renderUserProfile(user) { /* ... */ }
 
// 布尔返回值函数使用is/has/can开头
function isValidUser(user) { /* ... */ }
function hasPermission(user, permission) { /* ... */ }
function canEdit(user, document) { /* ... */ }

2. 函数长度和职责

// 好:单一职责
function calculateTax(amount, rate) {
    return amount * rate;
}
 
function formatCurrency(amount) {
    return `$${amount.toFixed(2)}`;
}
 
function calculateTotalWithTax(amount, taxRate) {
    const tax = calculateTax(amount, taxRate);
    const total = amount + tax;
    return formatCurrency(total);
}
 
// 避免:过长的函数
function processOrder(order) {
    // 100+ 行代码处理订单的各个方面
    // 应该拆分成多个小函数
}

3. 纯函数

// 纯函数:相同输入总是产生相同输出,无副作用
function add(a, b) {
    return a + b;
}
 
function multiply(arr, factor) {
    return arr.map(x => x * factor);
}
 
// 避免副作用
// 不好:修改外部状态
let globalCount = 0;
function incrementCount() {
    globalCount++; // 副作用
}
 
// 好:返回新值
function increment(count) {
    return count + 1;
}

4. 错误处理

// 输入验证
function divide(a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        throw new TypeError('参数必须是数字');
    }
    
    if (b === 0) {
        throw new Error('除数不能为零');
    }
    
    return a / b;
}
 
// 优雅的错误处理
function safeJsonParse(jsonString) {
    try {
        return { success: true, data: JSON.parse(jsonString) };
    } catch (error) {
        return { success: false, error: error.message };
    }
}

上一篇:循环语句