JavaScript 函数深入解析
核心概念速览
- 函数是JS中可重复调用的代码片段,用于执行任务或计算值。
- 定义方式包括声明式(
function fn() {})和表达式式(const fn = function() {})。 - 支持默认参数、剩余参数及箭头函数语法。
- 函数拥有独立作用域,内部声明的变量外部无法访问。
- 闭包机制使函数能"记住"并访问其外部作用域的变量。
- 箭头函数语法简洁,且不绑定自身的
this。
如何定义函数
在JavaScript中,函数是一等公民,意味着它们可以像变量一样被传递、赋值和返回。主要有三种定义方式:
1. 函数声明
最常见的写法,使用 function 关键字。
function square(number) {
return number * number;
}
特性:会被提升(hoisting),可以在声明前调用。例如:
console.log(square(5)); // 输出 25
function square(n) { return n * n; }
2. 函数表达式
将函数赋值给一个变量。可以是匿名函数,也可以有名字(用于递归)。
const square = function(n) {
return n * n;
};
// 命名函数表达式
const factorial = function fact(n) {
return n < 2 ? 1 : n * fact(n - 1);
};
特性:不会被提升,必须在定义之后才能调用。
3. 自执行函数 (IIFE)
定义后立即执行的函数表达式,常用于创建独立作用域。
(function() {
var message = "Hello, IIFE!";
})();
参数与返回值
参数传递规则
基础类型(string, number, boolean)按值传递;对象和数组按引用传递,修改会影响原数据。
function changeObj(obj) {
obj.brand = "Toyota";
}
var mycar = { brand: "Honda" };
changeObj(mycar);
console.log(mycar.brand); // 输出 "Toyota"
默认参数 (ES6)
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5)); // 5
剩余参数 (Rest Parameters)
function sum(...args) {
return args.reduce((acc, cur) => acc + cur, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
返回值
使用 return 语句返回结果。如果没有 return,函数默认返回 undefined。
function noOp() {}
console.log(noOp()); // undefined
作用域与闭包
作用域
函数内部的变量是局部变量,外部无法访问。
function showCar() {
var car = "Volvo";
console.log(car); // "Volvo"
}
showCar();
// console.log(car); // 报错:car is not defined
闭包
闭包是函数与其词法环境的组合。内部函数可以访问外部函数的变量,即使外部函数已经执行完毕。
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
闭包常用于数据封装和保持状态。
箭头函数 (Arrow Functions)
ES6 引入的简洁语法,特别是对于简单操作和回调函数。箭头函数没有自己的 this,它会捕获所在上下文的 this 值。
// 单参数,省略括号
const double = x => x * 2;
// 无参数,需要空括号
const sayHello = () => console.log("Hello");
// 多参数,需要括号
const add = (a, b) => a + b;
// 函数体多行,需要花括号和 return
const getPerson = (name, age) => {
return { name: name, age: age };
};
箭头函数不能被用作构造函数,也没有 arguments 对象(可使用剩余参数替代)。
高级特性
函数作为一等公民
函数可以被赋值给变量、作为参数传递、作为返回值返回。
function operate(a, b, callback) {
return callback(a, b);
}
const result = operate(5, 3, (x, y) => x + y);
console.log(result); // 8
递归
函数调用自身,常用于解决树形结构、阶乘等问题。
function factorial(n) {
if (n === 0) return 1;
return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
注意:深度递归可能导致栈溢出,本文未讨论尾调用优化等优化手段。
内置全局函数
JavaScript 提供了一些内置函数,例如 parseInt(), isNaN(), encodeURI(), eval() 等。需要注意的是,eval() 有安全风险,应避免使用。
总结对比
| 特性 | 函数声明 | 函数表达式 | 箭头函数 |
|---|---|---|---|
| 提升 | 是 | 否 | 否 |
| this 绑定 | 动态 | 动态 | 静态(词法) |
| 作为构造函数 | 可以 | 可以 | 不可以 |
| arguments 对象 | 有 | 有 | 无(可用 rest) |
| 语法简洁度 | 标准 | 标准 | 简洁 |