JavaScript函数是一等公民,可赋值、传参、返回、存储、动态创建并拥有属性方法;支持匿名使用、高阶函数、闭包封装及对象式扩展,需注意调用与引用区别、this绑定和闭包陷阱。

JavaScript 中的函数是真正的一等公民——这不是比喻,而是语言层面的硬性能力:它能被赋值、传参、返回、存储、动态创建,还能拥有属性和方法。
函数能像数字一样被赋值和存储
你不需要给函数起名就能用它;赋值时写 fn,不是 fn()——后者是调用,前者才是把函数当值来对待。
- 存进变量:
const log = (msg) => console.log(msg) - 塞进对象:
const api = { get: fetch, post: (url, body) => fetch(url, { method: 'POST', body }) } - 放进数组:
const steps = [validate, transform, save],后续可统一遍历执行
常见错误是误把执行结果当函数传:比如 arr.map(handler()) 会立即执行并传回 undefined,正确写法是 arr.map(handler)。
函数能作为参数传入,支撑回调与高阶函数
这是事件处理、异步控制、数组操作的底层机制。只要一个函数接受另一个函数作参数,它就是高阶函数——map、filter、setTimeout 全部属于这一类。
立即学习“Java免费学习笔记(深入)”;
- 注意
this绑定问题:对象方法传入map时容易丢失上下文,obj.method.bind(obj)或箭头函数封装更安全 - 避免在循环中现场定义匿名函数(如
for (let i = 0; i alert(i)),闭包捕获的是同一份i引用,最终全弹出3;改用let声明或提取到外部函数
函数能被返回,实现闭包与行为定制
返回函数不是炫技,而是封装状态和复用逻辑最自然的方式。比如日志前缀、重试策略、权限校验,都适合用工厂函数生成。
-
const withPrefix = (prefix) => (msg) => console.log(`[${prefix}] ${msg}`),调用withPrefix('ERROR')('file not found')输出带标记的日志 -
const retry = (fn, max) => async (...args) => { /* 封装重试逻辑 */ },业务层只管传fetch,不操心失败怎么兜底 - React 的
useCallback本质也是返回记忆化函数,防止子组件因引用变化而重复渲染
函数是对象,可以挂属性、动态扩展
这常被忽略,但很实用:比如给工具函数加版本号、缓存标记、调试描述,甚至挂测试用的 mock 方法。
-
function debounce(fn, ms) { const debounced = ...; debounced.cancel = () => {...}; return debounced; }—— 返回的函数自带cancel方法 -
myApi.get.description = 'Fetch user profile';,配合文档生成或 DevTools 可读性增强 - 注意:普通函数声明(
function foo(){})和箭头函数(() => {})都是一等公民,但箭头函数没有prototype和arguments,不能用作构造函数
真正难的不是记住“一等公民”这个说法,而是习惯把函数当作数据来流转——什么时候该传,什么时候该返,什么时候该缓存,什么时候该绑定,这些判断才决定代码是否松耦、可测、可维护。











