函数是 JavaScript 的核心组成部分,是实现代码复用、逻辑封装的基础,也是构建复杂应用的基石。从简单的工具函数到异步编程中的回调、Promise,函数贯穿了 JavaScript 开发的全场景。本文将系统梳理 JavaScript 函数的核心概念、分类方式,并结合实战案例讲解不同类型函数的使用场景与注意事项。
一、函数的核心概念
在 JavaScript 中,函数是 "一等公民"------ 它可以作为变量赋值、作为参数传递、作为返回值返回,也可以作为对象的属性(方法)。本质上,函数是一段可重复执行的代码块,可接收输入参数、处理逻辑并返回结果。
函数的基本结构
一个完整的 JavaScript 函数通常包含:
- 函数名(可选,匿名函数无名称);
- 参数列表(可选,形参);
- 函数体(执行逻辑);
- 返回值(可选,无 return 则返回 undefined)。
javascript
运行
// 基础函数示例
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // 输出:3
二、JavaScript 函数的分类
根据定义方式、使用场景、特性等维度,JavaScript 函数可分为多种类型,以下是最常用的分类方式:
1. 按定义方式分类
这是最基础的分类维度,核心区分 "如何创建函数"。
(1)声明式函数(函数声明)
通过function关键字声明,具有函数提升特性(在代码执行前被解析,可在声明前调用)。
javascript
运行
// 函数声明
console.log(multiply(3, 4)); // 输出:12(提升特性)
function multiply(a, b) {
return a * b;
}
特点:
- 必须有函数名;
- 提升至当前作用域顶部,可先调用后声明;
- 作用域为函数作用域(ES6 前)/ 块级作用域(ES6 后配合 let/const)。
(2)表达式函数(函数表达式)
将函数赋值给变量 / 常量,分为命名函数表达式 和匿名函数表达式,无函数提升(仅变量提升,赋值后才可调用)。
javascript
运行
// 匿名函数表达式
const subtract = function(a, b) {
return a - b;
};
console.log(subtract(5, 2)); // 输出:3
// 命名函数表达式(名称仅在函数内部可用)
const divide = function divideFn(a, b) {
console.log(divideFn.name); // 输出:divideFn
return a / b;
};
console.log(divide(10, 2)); // 输出:5
// console.log(divideFn); // 报错:divideFn is not defined
特点:
- 可匿名,也可命名(命名仅内部可见);
- 无函数提升,需先定义后调用;
- 更灵活,适合作为参数 / 返回值。
(3)箭头函数(ES6+)
ES6 引入的简洁语法,本质是特殊的函数表达式,无自己的this、arguments等。
javascript
运行
// 基础箭头函数
const pow = (x) => x * x;
console.log(pow(4)); // 输出:16
// 多参数+多行函数体
const sum = (a, b, c) => {
const total = a + b + c;
return total;
};
特点:
- 语法简洁,省略
function和return(单行体); - 绑定外层作用域的
this,无法通过call/apply/bind修改; - 无
arguments对象(可改用剩余参数...args); - 不能作为构造函数(无法 new);
- 无原型(prototype)属性。
2. 按调用方式分类
根据函数的执行场景,可分为普通函数、构造函数、方法等。
(1)普通函数
直接调用的函数,无特殊上下文,this默认指向全局对象(浏览器中为window,Node 中为global),严格模式下为undefined。
javascript
运行
function sayHi() {
console.log(this); // 浏览器中输出window
}
sayHi();
// 严格模式
'use strict';
function strictFn() {
console.log(this); // undefined
}
strictFn();
(2)构造函数
通过new关键字调用的函数,用于创建对象实例,默认返回实例(手动 return 对象会覆盖)。
javascript
运行
function Person(name, age) {
this.name = name;
this.age = age;
}
const person1 = new Person('张三', 20);
console.log(person1); // { name: '张三', age: 20 }
构造函数规范:
- 函数名首字母大写(约定);
- 内部通过
this绑定实例属性; - 无需手动 return(return 基本类型无影响,return 对象会替换实例)。
(3)方法
作为对象属性的函数,调用时this指向所属对象。
javascript
运行
const user = {
name: '李四',
greet: function() {
console.log(`Hello, ${this.name}`);
}
};
user.greet(); // 输出:Hello, 李四
(4)立即执行函数(IIFE)
定义后立即执行的函数,用于创建独立作用域,避免变量污染。
javascript
运行
// 经典写法
(function() {
const privateVar = '私有变量';
console.log(privateVar);
})();
// ES6简化(块级作用域替代)
{
const privateVar = '私有变量';
console.log(privateVar);
}
3. 按特性 / 用途分类
(1)纯函数
输入相同则输出相同,无副作用(不修改外部变量、不依赖外部状态),是函数式编程的核心。
javascript
运行
// 纯函数
function square(x) {
return x * x;
}
// 非纯函数(依赖外部变量)
let base = 2;
function multiplyByBase(x) {
return x * base; // base变化会导致输出变化
}
(2)高阶函数
接收函数作为参数,或返回函数的函数,如map、filter、reduce等数组方法。
javascript
运行
// 高阶函数示例:接收函数参数
function operate(arr, fn) {
return arr.map(fn);
}
const nums = [1, 2, 3];
const doubled = operate(nums, (x) => x * 2);
console.log(doubled); // [2,4,6]
// 高阶函数示例:返回函数
function createAdder(num) {
return (x) => x + num;
}
const add5 = createAdder(5);
console.log(add5(3)); // 8
(3)异步函数
处理异步逻辑的函数,包括回调函数、Promise 函数、async/await 函数。
javascript
运行
// 回调函数
function fetchData(callback) {
setTimeout(() => {
callback('异步数据');
}, 1000);
}
fetchData((data) => console.log(data));
// Promise函数
function fetchPromise() {
return new Promise((resolve) => {
setTimeout(() => resolve('Promise数据'), 1000);
});
}
fetchPromise().then(data => console.log(data));
// async/await函数
async function fetchAsync() {
const data = await fetchPromise();
console.log(data);
}
fetchAsync();
三、不同类型函数的使用场景
| 函数类型 | 核心优势 | 适用场景 |
|---|---|---|
| 声明式函数 | 函数提升,代码可读性高 | 全局工具函数、简单逻辑封装 |
| 表达式函数 | 灵活,可匿名 | 作为参数传递(如回调)、局部函数 |
| 箭头函数 | 语法简洁,绑定外层 this | 回调函数、无 this 修改的简单逻辑 |
| 构造函数 | 批量创建对象实例 | 自定义对象类型(如类的替代,ES6 前) |
| 纯函数 | 可预测、无副作用 | 函数式编程、状态管理(如 Redux) |
| 异步函数 | 处理非阻塞逻辑 | 网络请求、定时器、文件操作 |
四、常见坑点与注意事项
- this 指向问题 :箭头函数的
this绑定外层作用域,切勿用于对象方法 / 构造函数; - 函数提升差异:声明式函数提升完整,表达式函数仅提升变量;
- 参数处理 :
arguments是类数组,箭头函数无,可改用...args; - 构造函数返回值:手动 return 对象会覆盖实例,return 基本类型无影响;
- 立即执行函数 :ES6 后可改用块级作用域(
{})替代,更简洁。
五、总结
函数是 JavaScript 的灵魂,不同类型的函数适用于不同场景:声明式函数适合简单逻辑,表达式函数更灵活,箭头函数简化回调,构造函数用于对象创建,高阶函数赋能函数式编程,异步函数处理非阻塞逻辑。
掌握函数的分类与特性,不仅能写出更优雅、高效的代码,更能深刻理解 JavaScript 的执行机制与设计思想。在实际开发中,应根据场景选择合适的函数类型,规避this、提升等坑点,充分发挥函数的威力。