Skip to content

JavaScript 函数

函数的概念

函数是一段可重用的代码块,用于执行特定的任务。函数可以接受输入参数,执行操作,并返回结果。

函数的定义

JavaScript 中有多种定义函数的方式:

1. 函数声明

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

console.log(add(5, 10)); // 输出: 15

2. 函数表达式

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

console.log(add(5, 10)); // 输出: 15

3. 箭头函数

javascript
const add = (a, b) => a + b;

console.log(add(5, 10)); // 输出: 15

// 单个参数可以省略括号
const square = x => x * x;
console.log(square(5)); // 输出: 25

// 无参数
const greet = () => 'Hello, World!';
console.log(greet()); // 输出: Hello, World!

// 多行函数体需要使用花括号和 return
const multiply = (a, b) => {
  const result = a * b;
  return result;
};
console.log(multiply(5, 10)); // 输出: 50

4. 函数构造函数

javascript
const add = new Function('a', 'b', 'return a + b');
console.log(add(5, 10)); // 输出: 15

函数的参数

1. 普通参数

javascript
function greet(name, age) {
  return `Hello, ${name}! You are ${age} years old.`;
}

console.log(greet('John', 30)); // 输出: Hello, John! You are 30 years old.

2. 默认参数

javascript
function greet(name = 'Guest', age = 25) {
  return `Hello, ${name}! You are ${age} years old.`;
}

console.log(greet()); // 输出: Hello, Guest! You are 25 years old.
console.log(greet('John')); // 输出: Hello, John! You are 25 years old.
console.log(greet('John', 30)); // 输出: Hello, John! You are 30 years old.

3. 剩余参数

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

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

4. 解构参数

javascript
function greet({name, age}) {
  return `Hello, ${name}! You are ${age} years old.`;
}

const person = {name: 'John', age: 30};
console.log(greet(person)); // 输出: Hello, John! You are 30 years old.

// 数组解构
function getFirstTwo([first, second]) {
  return [first, second];
}

const numbers = [1, 2, 3, 4, 5];
console.log(getFirstTwo(numbers)); // 输出: [1, 2]

函数的返回值

1. return 语句

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

console.log(add(5, 10)); // 输出: 15

2. 没有 return 语句

如果函数没有 return 语句,它会返回 undefined:

javascript
function greet() {
  console.log('Hello, World!');
}

console.log(greet()); // 输出: Hello, World! 然后输出: undefined

3. return 语句后的代码

return 语句后的代码不会执行:

javascript
function add(a, b) {
  return a + b;
  console.log('This code will not execute'); // 不会执行
}

console.log(add(5, 10)); // 输出: 15

函数的调用

1. 直接调用

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

console.log(greet()); // 输出: Hello, World!

2. 作为对象方法调用

javascript
const person = {
  name: 'John',
  greet() {
    return `Hello, ${this.name}!`;
  }
};

console.log(person.greet()); // 输出: Hello, John!

3. 作为构造函数调用

javascript
function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person = new Person('John', 30);
console.log(person.name); // 输出: John
console.log(person.age); // 输出: 30

4. 使用 call() 方法调用

javascript
function greet(greeting) {
  return `${greeting}, ${this.name}!`;
}

const person = {name: 'John'};
console.log(greet.call(person, 'Hello')); // 输出: Hello, John!

5. 使用 apply() 方法调用

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

console.log(sum.apply(null, [1, 2, 3])); // 输出: 6

6. 使用 bind() 方法调用

javascript
function greet() {
  return `Hello, ${this.name}!`;
}

const person = {name: 'John'};
const greetPerson = greet.bind(person);
console.log(greetPerson()); // 输出: Hello, John!

函数的作用域

1. 全局作用域

在函数外部声明的变量具有全局作用域:

javascript
let globalVar = 'Global';

function myFunction() {
  console.log(globalVar); // 可以访问全局变量
}

myFunction(); // 输出: Global

2. 函数作用域

在函数内部声明的变量具有函数作用域:

javascript
function myFunction() {
  let localVar = 'Local';
  console.log(localVar); // 可以访问局部变量
}

myFunction(); // 输出: Local
// console.log(localVar); // 错误:无法访问局部变量

3. 块级作用域

在 ES6+ 中,使用 let 或 const 声明的变量具有块级作用域:

javascript
if (true) {
  let blockVar = 'Block';
  console.log(blockVar); // 可以访问块级变量
}

// console.log(blockVar); // 错误:无法访问块级变量

函数的闭包

闭包是指函数能够访问其词法作用域之外的变量:

javascript
function outer() {
  let count = 0;
  
  function inner() {
    count++;
    return count;
  }
  
  return inner;
}

const counter = outer();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 2
console.log(counter()); // 输出: 3

函数的递归

递归是指函数调用自身的过程:

javascript
function factorial(n) {
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

console.log(factorial(5)); // 输出: 120

函数的立即执行表达式 (IIFE)

IIFE 是一种立即执行的函数表达式:

javascript
(function() {
  console.log('This function executes immediately');
})();

// 带参数的 IIFE
(function(name) {
  console.log(`Hello, ${name}!`);
})('John');

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

函数的方法

1. toString() 方法

返回函数的字符串表示:

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

console.log(add.toString()); // 输出: function add(a, b) { return a + b; }

2. length 属性

返回函数参数的数量:

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

console.log(add.length); // 输出: 3

3. name 属性

返回函数的名称:

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

console.log(add.name); // 输出: add

const multiply = function(a, b) {
  return a * b;
};

console.log(multiply.name); // 输出: multiply

函数的最佳实践

1. 函数命名

  • 函数名应该具有描述性
  • 使用驼峰命名法
  • 动词开头表示动作
javascript
// 好的函数名
function calculateSum(a, b) {
  return a + b;
}

function getUserData(id) {
  // 代码
}

// 不好的函数名
function foo(a, b) {
  return a + b;
}

2. 函数长度

  • 函数应该保持简短
  • 一个函数应该只做一件事
  • 通常不超过 20-30 行

3. 参数数量

  • 函数参数数量应该合理
  • 过多的参数会使函数难以理解和使用
  • 可以使用对象来传递多个参数
javascript
// 好的做法
function createUser({name, email, age}) {
  // 代码
}

createUser({name: 'John', email: 'john@example.com', age: 30});

// 不好的做法
function createUser(name, email, age, address, phone) {
  // 代码
}

4. 错误处理

  • 函数应该处理可能的错误
  • 使用 try/catch 语句
  • 返回适当的错误信息
javascript
function divide(a, b) {
  if (b === 0) {
    throw new Error('Division by zero');
  }
  return a / b;
}

try {
  console.log(divide(10, 0));
} catch (error) {
  console.error(error.message);
}

5. 文档

  • 为函数添加注释
  • 说明函数的用途、参数和返回值
  • 使用 JSDoc 格式
javascript
/**
 * 计算两个数的和
 * @param {number} a - 第一个数
 * @param {number} b - 第二个数
 * @returns {number} 两个数的和
 */
function add(a, b) {
  return a + b;
}

小结

函数是 JavaScript 中的核心概念之一,它允许我们将代码组织成可重用的块。JavaScript 提供了多种定义函数的方式,包括函数声明、函数表达式、箭头函数等。理解函数的参数、返回值、作用域和调用方式,是学习 JavaScript 的基础。在实际开发中,应该遵循最佳实践,编写清晰、简洁、可维护的函数。