JavaScript函数是一等公民,需明确输入、输出和边界;应主动防御异常输入,避免闭包陷阱,导出时用命名函数表达式以保障调试与稳定性。

JavaScript 函数就是可被多次调用的命名代码块
它不是语法糖,也不是“封装概念”的抽象说法——function 是 JavaScript 中的一等公民,能赋值给变量、作为参数传入、从函数里返回。所谓“可复用”,本质是:同一段逻辑,不靠复制粘贴,而是通过 call 或 apply 触发执行,且每次可接收不同输入、产生对应输出。
写函数前先问三个问题:它要处理什么数据?返回什么?边界在哪?
跳过这步直接写,大概率写出带隐式依赖、副作用或类型假设的“脆函数”。比如:
function formatDate(date) {
return new Date(date).toLocaleDateString();
}
这段代码在 date 是字符串时能跑,但传入 null、undefined 或无效格式字符串(如 "2024-13-01")就会静默失败或抛错。可复用函数得主动防御:
- 用
typeof或instanceof检查输入类型,必要时用String()或Number()做安全转换 - 明确返回值类型,避免有时返回
string、有时返回undefined - 对空值、NaN、非日期字符串等常见异常输入,统一返回
null或抛出带上下文的Error
避免闭包陷阱:别让函数意外捕获外部变量
闭包本身不是问题,但当函数被导出、传递到其他模块或异步回调中时,捕获的外部变量可能已变更或销毁。典型错误:
function createHandlers() {
const items = ['a', 'b', 'c'];
return items.map((item, i) => () => console.log(i, item));
}
const handlers = createHandlers();
handlers[0](); // 输出 "2 c" —— 因为循环结束时 i=2,item='c'
修复方式很简单:用参数绑定当前值,而不是依赖闭包捕获的循环变量:
技术上面应用了三层结构,AJAX框架,URL重写等基础的开发。并用了动软的代码生成器及数据访问类,加进了一些自己用到的小功能,算是整理了一些自己的操作类。系统设计上面说不出用什么模式,大体设计是后台分两级分类,设置好一级之后,再设置二级并选择栏目类型,如内容,列表,上传文件,新窗口等。这样就可以生成无限多个二级分类,也就是网站栏目。对于扩展性来说,如果有新的需求可以直接加一个栏目类型并新加功能操作
- 改用
for...of+let(块级作用域) - 或显式传参:
() => handler(i, item) - 或用
bind:handler.bind(null, i, item)
导出函数时优先用命名函数表达式而非箭头函数
箭头函数没有 name 属性,堆栈追踪时只显示 ;调试、监控、性能分析都变困难。尤其当函数被框架或工具链重命名(如 Webpack 的 function-inlining)后,问题更隐蔽。
正确写法:
export const validateEmail = function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
};
这样既保留了 validateEmail.name === "validateEmail",又支持具名递归和清晰的 devtools 显示。
真正难的从来不是“怎么写一个函数”,而是判断这个函数是否该存在、它的输入输出契约是否稳定、以及它被调用十次后,第十一次会不会因为某个没料到的参数而崩掉。










