应放弃块级函数声明,改用函数表达式+let/const、IIFE、顶层函数+条件调用等标准方案,并通过严格模式和ESLint拦截。

直接在 if 等块级语句中写函数声明(如 if (x) { function foo() {} })不是可靠的“条件式定义”,而是被规范明确禁止的非标准用法。它在不同浏览器中行为分裂——Chrome/Firefox 严格模式报语法错误,IE 全局提升且无视条件真假,Safari 表现不稳定。所谓“规避差异”,关键不是绕开规则去适配各引擎,而是**放弃这种写法本身**,改用语义清晰、行为确定的替代方案。
用函数表达式 + 块作用域变量替代
这是最直接、最推荐的方式。函数表达式不会被提升,let 或 const 保证作用域边界清晰,行为在所有现代引擎中完全一致:
if (condition) { const handler = () => console.log('yes'); handler(); }- 若需在块外使用,提前声明变量:
let action; if (condition) action = () => 'A'; else action = () => 'B'; - 注意:不能在声明前调用,这反而是优点——避免了因提升导致的逻辑错乱
用立即执行函数(IIFE)封装条件逻辑
当条件分支内需要一组私有逻辑(含多个函数或变量),IIFE 能天然隔离作用域,不污染外部,且无兼容性问题:
if (isModern) { (function initModern() { /* 多行逻辑 */ })(); }if (needPolyfill) { (function patchAPI() { window.fetch = customFetch; })(); }- 它不产生命名,不依赖提升,执行完即释放,适合一次性初始化场景
提前声明函数,运行时做条件调用
把函数定义提到顶层(符合 ES 规范),用 if 控制执行路径。逻辑更易读,调试更直观,也便于单元测试:
function loadFromCache() { /* ... */ }function fetchFromNetwork() { /* ... */ }if (hasCachedData) loadFromCache(); else fetchFromNetwork();- 这种方式还天然支持函数复用、参数传递和返回值处理
用严格模式 + ESLint 从源头拦截
即使团队有人误写块级函数声明,也能被工具链快速捕获:
- 在文件顶部加
'use strict';,让 Chrome/Firefox 在解析阶段就抛出SyntaxError - 配置 ESLint 规则
no-inner-declarations,CI 流程中自动拒绝含该写法的代码提交 - Webpack/Vite 等构建工具默认启用严格模式,相当于为旧代码加了一道防护墙


















