JS中的惰性函数基本介绍

JS中的惰性函数(Lazy Function)其实是一种非常巧妙的性能优化设计模式,也就是利用js的动态重写函数 的思想,用第一次调用时微乎其微的代价,换取了后续所有调用的极致性能,它的核心思想非常直白:让函数在第一次执行时"记住"环境特性或计算结果,并在后续调用中直接走捷径,不再做无意义的重复判断或计算。

你可以把它想象成下班回家认路:第一天到一个新小区,你需要停下来辨认方向、确认门牌号(这是第一次执行的"脏活累活");但如果你住了十年,每天回家还在每个路口重新认路就太荒谬了。惰性函数就是让你"第一次辛苦认路,以后闭着眼走直线"。

核心原理:函数自我重写

在 JavaScript 中,函数是一等公民,这意味着函数可以在运行时被重新赋值和修改。惰性函数正是利用了这一特性,在函数内部将自己重写为一个优化后的"精简版"函数。

在 JS 中,实现惰性函数主要有以下两种经典写法:

1. 函数内直接重写(延迟执行版)

这种写法在第一次调用时才进行环境检测和函数重写。

javascript 复制代码
function createXHR() {
  // 第一次进入这里,做繁重的环境检测
  if (window.XMLHttpRequest) {
    // 如果是标准浏览器,将 createXHR 重写为直接返回新对象的函数
    createXHR = function () {
      return new XMLHttpRequest();
    };
  } else {
    // 如果是古董 IE,重写为兼容版本
    createXHR = function () {
      return new ActiveXObject("Microsoft.XMLHTTP");
    };
  }
  // 重写完后,手动调用一次新函数,保证第一次调用也能拿到正确的结果
  return createXHR();
}

运行流程: 第一次调用 createXHR() 时,它进入原函数体做判断,把全局的 createXHR 指针指向新函数,然后返回结果。以后再调用 createXHR(),它就已经是那个精简版的新函数了,直接返回结果,完全跳过了 if/else 判断。

2. 闭包 + 立即执行(立即执行版)

这种写法在代码加载阶段(函数被赋值时)就立刻执行判断,并返回最终的函数形态。

javascript 复制代码
const addEvent = (function () {
  // 这个外层自执行函数只跑一遍
  if (document.addEventListener) {
    // 标准浏览器,直接返回优化后的函数
    return function (el, type, handler) {
      el.addEventListener(type, handler, false);
    };
  } else if (document.attachEvent) {
    // 古董 IE,返回兼容版函数
    return function (el, type, handler) {
      el.attachEvent("on" + type, handler);
    };
  }
})();

运行流程: addEvent 在定义时,外层函数就立即执行并根据环境返回了最终形态。后续无论调用多少次 addEvent,它都是最终那个没有判断逻辑的函数。

经典应用场景

  1. 浏览器兼容性检测 :比如检测 addEventListenerlocalStorageIntersectionObserver 等 API 是否存在。因为浏览器的运行环境在页面打开那一刻就已经确定了,不会中途改变,完全没必要每次调用都去扫描一遍。
  2. 单次初始化逻辑 :比如生成一次性的复杂正则表达式、拉取远程配置后把 init 函数替换成空函数(防止重复初始化)。
  3. 复杂计算或资源加载缓存:对于一些第一次计算非常耗时的操作,可以在第一次算出结果后缓存起来,后续直接返回缓存值。

概念辨析:惰性函数 vs 惰性求值

在学习过程中,你可能会遇到另一个相似的概念叫**"惰性求值(Lazy Evaluation)"**。这两者虽然都带"惰性",但解决的问题完全不同:

  • 惰性函数(Lazy Function) :侧重于一次判断,终身受益。通过重写函数来消除重复的条件判断,提升高频调用时的执行效率。
  • 惰性求值(Lazy Evaluation) :侧重于按需计算,节省资源。通常利用 ES6 的生成器来实现,推迟昂贵计算或处理无限数据流,只有当真正需要某个值时才去计算它(例如处理超大数组的过滤和映射)。

掌握惰性函数,能让你在处理跨浏览器兼容或高频工具函数时,写出性能更极致、逻辑更优雅的代码。

相关推荐
To_OC7 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
To_OC7 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic7 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy8 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志8 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble9 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长9 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯10 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜11 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司11 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能