Skip to content

JavaScript 函数

JavaScript 函数 (function) 是一个可重复使用的代码块,用于执行特定的任务。函数在被“某物”调用 (invoke/call) 时执行。

函数是 JavaScript 中基础的构建块,实现了模块化 (modularity)、代码重用 (reusability) 和抽象 (abstraction)。

在 JavaScript 中定义函数有几种方式:

1. 函数声明 (Function Declaration 或 Function Statement):

Section titled “1. 函数声明 (Function Declaration 或 Function Statement):”

使用 function 关键字定义,后跟函数名、一对圆括号 () 包含的参数列表,以及一对花括号 {} 包含的代码块。

function greet(name) {
return `Hello, ${name}!`;
}
// 函数声明存在变量提升 (hoisting),意味着它们可以在代码中定义之前被调用。

2. 函数表达式 (Function Expression):

Section titled “2. 函数表达式 (Function Expression):”

函数也可以定义为表达式的一部分,通常是将其赋值给一个变量。函数可以有名 (named) 或匿名 (anonymous)。

// 匿名函数表达式
const add = function(a, b) {
return a + b;
};
// 命名函数表达式('multiply' 这个名称主要用于函数内部的调试或递归)
const multiply = function multiply(x, y) {
return x * y;
};
// 函数表达式不像函数声明那样存在变量提升。
// 你必须在调用它们之前定义它们。

3. 箭头函数 (Arrow Functions) (ES6+):

Section titled “3. 箭头函数 (Arrow Functions) (ES6+):”

ES6 引入了一种更简洁的函数书写语法,称为箭头函数 (arrow functions)。

const subtract = (a, b) => {
return a - b;
};
// 如果函数体只有一条语句且返回一个值,可以省略花括号和 'return' 关键字
const square = x => x * x;
// 如果没有参数,使用空括号 ()
const sayHi = () => console.log("Hi!");
// 箭头函数与传统函数有一些关键区别,
// 特别是它们对 'this' 关键字和 'arguments' 对象的处理方式(它们没有自己的这些对象)。

函数参数 (Parameters) 和实参 (Arguments):

  • 参数 (Parameters) 是函数定义中列出的名称(例如,greet(name) 中的 name)。
  • 实参 (Arguments) 是函数被调用时传递给函数的实际值(例如,greet("Alice") 中的 “Alice” 就是实参)。

在函数内部,参数 behave (表现得) 就像局部变量 (local variables)。

函数调用 (Invocation / Calling a Function)

Section titled “函数调用 (Invocation / Calling a Function)”

函数内部的代码在函数被调用 (invoked) 时执行。这通常通过使用函数名后跟包含任何实参的圆括号 () 来实现。

console.log(greet("Bob")); // 调用 greet 函数,输出:“Hello, Bob!”
console.log(add(5, 3)); // 调用 add 函数,输出:8
square(4); // 调用 square 函数,返回 16

函数可以在多种上下文中被调用:

  • 直接在代码中。
  • 当某个事件发生时(例如,用户点击一个按钮)。
  • 自动地(自执行函数)。
  • 作为对象的方法。

当 JavaScript 执行到 return 语句时,函数将停止执行。

return 后面指定的值会被“返回”给调用者。如果 return 没有指定值,或者函数执行到末尾都没有遇到 return 语句,函数会隐式地返回 undefined。

function calculateArea(width, height) {
if (width <= 0 || height <= 0) {
console.error("Width and height must be positive.");
return; // 隐式返回 undefined
}
return width * height; // 返回计算出的面积
}
let area1 = calculateArea(10, 5); // area1 将是 50
let area2 = calculateArea(-2, 5); // area2 将是 undefined,同时 logged 错误
  • 代码重用 (Code Reusability): 只定义一次代码,然后在多个地方使用。
  • 模块化 (Modularity): 将复杂的问题分解成更小、更易于管理的部分。
  • 抽象 (Abstraction): 隐藏复杂的实现细节,提供一个简单的接口。
  • 组织性 (Organization): 使代码更易于阅读、理解和维护。

示例:将华氏温度转换为摄氏温度。

function toCelsius(fahrenheit) {
return (5 / 9) * (fahrenheit - 32);
}
let temp1 = toCelsius(32); // 0
let temp2 = toCelsius(212); // 100
// document.getElementById("demo").innerHTML = `32°F is ${temp1}°C`;

访问一个函数名而不加 () 引用的是函数对象本身。加上 () 则会调用 (invoke) 它。

function toCelsius(fahrenheit) {
return (5 / 9) * (fahrenheit - 32);
}
// 引用函数对象
// const converter = toCelsius;
// document.getElementById("output1").innerHTML = converter;
// 输出将显示函数的字符串表示形式,例如:“function toCelsius(fahrenheit) { ... }”
// 调用函数
// const tempInCelsius = toCelsius(68);
// document.getElementById("output2innerHTML = tempInCelsius;
// 输出将是结果,例如 20

函数作为一等公民 (First-Class Citizens)

Section titled “函数作为一等公民 (First-Class Citizens)”

在 JavaScript 中,函数是“一等公民 (first-class citizens)”。这意味着它们可以像其他任何值一样被对待:

  • 赋值给变量(如函数表达式所示)。
  • 作为实参传递给其他函数(回调函数 / callbacks)。
  • 作为值从其他函数返回(高阶函数 / higher-order functions)。

这种灵活性是 JavaScript 的一个强大特性。

function applyOperation(a, b, operation) {
return operation(a, b);
}
const sumResult = applyOperation(5, 2, add); // 'add' 函数作为实参传递
console.log(sumResult); // 输出:7
const productResult = applyOperation(5, 2, (x, y) => x * y); // 箭头函数作为实参传递
console.log(productResult); // 输出:10

闭包 (closure) 是一个函数,它可以访问其外部(封闭)函数的范围 (scope),即使在外部函数已经返回之后。这意味着闭包可以“记住”并访问其外部函数的变量和实参。

function createGreeter(greeting) {
return function(name) { // 这个内部函数就是一个闭包
console.log(`${greeting}, ${name}!`);
};
}
const greetHello = createGreeter("Hello");
const greetHi = createGreeter("Hi");
greetHello("Alice"); // 输出:Hello, Alice!
greetHi("Bob"); // 输出:Hi, Bob!

闭包是一个强大的概念,用于数据隐私、创建工厂函数以及许多高级的 JavaScript 模式中。(更多详细信息请参阅专门的闭包章节)。