Skip to content

函数

函数是 JavaScript 中的核心概念,用于封装可重复使用的代码块。

函数定义

函数声明

javascript
function greet(name) {
    return 'Hello, ' + name + '!';
}

console.log(greet('张三')); // Hello, 张三!

函数表达式

javascript
const greet = function(name) {
    return 'Hello, ' + name + '!';
};

console.log(greet('李四')); // Hello, 李四!

箭头函数(ES6)

javascript
// 基本语法
const greet = (name) => {
    return 'Hello, ' + name + '!';
};

// 简写:单个参数可省略括号
const greet = name => 'Hello, ' + name + '!';

// 无参数
const sayHello = () => console.log('Hello!');

// 返回对象字面量
const createPerson = (name, age) => ({ name, age });

函数构造器(不推荐)

javascript
const add = new Function('a', 'b', 'return a + b');
console.log(add(1, 2)); // 3

参数

默认参数

javascript
function greet(name = 'Guest') {
    return 'Hello, ' + name + '!';
}

console.log(greet());       // Hello, Guest!
console.log(greet('张三')); // Hello, 张三!

剩余参数

javascript
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15

参数解构

javascript
function printUser({ name, age, city = '未知' }) {
    console.log(`姓名: ${name}, 年龄: ${age}, 城市: ${city}`);
}

printUser({ name: '张三', age: 25 });
// 姓名: 张三, 年龄: 25, 城市: 未知

arguments 对象

javascript
function showArguments() {
    console.log(arguments);
    console.log(arguments.length);
}

showArguments(1, 2, 3); // [1, 2, 3], 3

注意

箭头函数没有 arguments 对象。

返回值

return 语句

javascript
function add(a, b) {
    return a + b;
}

let result = add(1, 2);
console.log(result); // 3

提前返回

javascript
function divide(a, b) {
    if (b === 0) {
        return '除数不能为0';
    }
    return a / b;
}

console.log(divide(10, 2)); // 5
console.log(divide(10, 0)); // 除数不能为0

返回多个值

javascript
function getMinMax(numbers) {
    return {
        min: Math.min(...numbers),
        max: Math.max(...numbers)
    };
}

const { min, max } = getMinMax([1, 5, 3, 9, 2]);
console.log(min, max); // 1, 9

作用域

全局作用域

javascript
let globalVar = '全局变量';

function showGlobal() {
    console.log(globalVar);
}

函数作用域

javascript
function test() {
    var functionVar = '函数变量';
    console.log(functionVar);
}

test();
// console.log(functionVar); // 错误:未定义

块级作用域

javascript
if (true) {
    let blockVar = '块级变量';
    const blockConst = '块级常量';
    var functionVar = '函数变量';
}

// console.log(blockVar);   // 错误
// console.log(blockConst); // 错误
console.log(functionVar);    // 函数变量

作用域链

javascript
let a = 1;

function outer() {
    let b = 2;
    
    function inner() {
        let c = 3;
        console.log(a, b, c); // 1, 2, 3
    }
    
    inner();
}

outer();

闭包

闭包是指函数可以访问其词法作用域,即使该函数在其词法作用域之外执行。

javascript
function createCounter() {
    let count = 0;
    
    return {
        increment() {
            count++;
            return count;
        },
        decrement() {
            count--;
            return count;
        },
        getCount() {
            return count;
        }
    };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1

闭包应用

javascript
// 私有变量
function createPerson(name) {
    let _name = name;
    
    return {
        getName() {
            return _name;
        },
        setName(newName) {
            _name = newName;
        }
    };
}

const person = createPerson('张三');
console.log(person.getName()); // 张三
person.setName('李四');
console.log(person.getName()); // 李四

高阶函数

高阶函数是指接收函数作为参数或返回函数的函数。

函数作为参数

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)

javascript
(function() {
    console.log('立即执行');
})();

// 带参数
(function(name) {
    console.log('Hello, ' + name);
})('张三');

// 箭头函数形式
(() => {
    console.log('箭头函数 IIFE');
})();

this 关键字

普通函数中的 this

javascript
const person = {
    name: '张三',
    greet: function() {
        console.log('Hello, ' + this.name);
    }
};

person.greet(); // Hello, 张三

call、apply、bind

javascript
const person1 = { name: '张三' };
const person2 = { name: '李四' };

function greet(greeting) {
    console.log(greeting + ', ' + this.name);
}

// call - 逐个传参
greet.call(person1, '你好'); // 你好, 张三

// apply - 数组传参
greet.apply(person2, ['你好']); // 你好, 李四

// bind - 返回新函数
const greetPerson1 = greet.bind(person1);
greetPerson1('你好'); // 你好, 张三

箭头函数中的 this

javascript
const person = {
    name: '张三',
    greet: function() {
        const arrowGreet = () => {
            console.log('Hello, ' + this.name);
        };
        arrowGreet();
    }
};

person.greet(); // Hello, 张三

注意

箭头函数没有自己的 this,它会捕获定义时所在上下文的 this 值。

递归函数

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

实践示例

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>JavaScript 函数示例</title>
</head>
<body>
    <h1>JavaScript 函数示例</h1>
    <script>
        // 工具函数
        const utils = {
            // 防抖
            debounce(fn, delay) {
                let timer = null;
                return function(...args) {
                    clearTimeout(timer);
                    timer = setTimeout(() => fn.apply(this, args), delay);
                };
            },
            
            // 节流
            throttle(fn, delay) {
                let lastTime = 0;
                return function(...args) {
                    const now = Date.now();
                    if (now - lastTime >= delay) {
                        lastTime = now;
                        fn.apply(this, args);
                    }
                };
            },
            
            // 柯里化
            curry(fn) {
                return function curried(...args) {
                    if (args.length >= fn.length) {
                        return fn.apply(this, args);
                    }
                    return function(...moreArgs) {
                        return curried.apply(this, args.concat(moreArgs));
                    };
                };
            }
        };
        
        // 示例:柯里化
        function add(a, b, c) {
            return a + b + c;
        }
        
        const curriedAdd = utils.curry(add);
        console.log(curriedAdd(1)(2)(3));     // 6
        console.log(curriedAdd(1, 2)(3));     // 6
        console.log(curriedAdd(1)(2, 3));     // 6
        
        // 示例:计数器(闭包)
        function createCounter(initial = 0) {
            let count = initial;
            return {
                increment: () => ++count,
                decrement: () => --count,
                getValue: () => count,
                reset: () => { count = initial; return count; }
            };
        }
        
        const counter = createCounter(10);
        console.log(counter.increment()); // 11
        console.log(counter.increment()); // 12
        console.log(counter.decrement()); // 11
        console.log(counter.getValue());  // 11
        console.log(counter.reset());     // 10
        
        // 示例:高阶函数
        const numbers = [1, 2, 3, 4, 5];
        
        const doubled = numbers.map(n => n * 2);
        const evens = numbers.filter(n => n % 2 === 0);
        const sum = numbers.reduce((acc, n) => acc + n, 0);
        
        console.log('原数组:', numbers);
        console.log('翻倍:', doubled);
        console.log('偶数:', evens);
        console.log('求和:', sum);
    </script>
</body>
</html>