You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

复现lodash _.once函数需至少2次调用才生效的问题排查与求解

_.once 函数复现问题修复

问题根因

你当前的实现错误嵌套了两层返回函数,把「存储参数」的逻辑和「执行目标函数」的逻辑拆到了不同的函数调用层级,没有在闭包内维护执行状态标记,导致需要3次调用才能触发目标函数执行,完全不符合once的调用链路。

现有错误实现

function onceCopy (testFunc) {
  const copyFunc = (a) => {
    const copyFunc2 = (b) => {
      return testFunc(a);
    };    
    return copyFunc2;
  };
  return copyFunc;
};

这段代码的执行链路问题:

  • 调用onceCopy(testFunc)仅返回第一层函数copyFunc,没有初始化执行状态、结果缓存
  • 第一次调用copyFunc(a)时不会执行目标函数,只会返回新的嵌套函数copyFunc2
  • 直到第三次调用(拿到copyFunc2后传参调用)才会执行testFunc,且仅能拿到第二次调用传入的参数a

标准_.once的预期逻辑

  • 接收目标函数后,在闭包内维护两个私有状态:函数是否已执行的标记、第一次执行的返回结果缓存
  • 第一次调用返回的包装函数时,透传参数、绑定正确的this指向执行目标函数,缓存结果、标记为已执行
  • 后续所有对包装函数的调用,直接返回缓存的结果,目标函数全程仅执行1次

正确实现代码

function onceCopy(testFunc) {
  let called = false;
  let cachedResult;
  return function(...args) {
    if (!called) {
      cachedResult = testFunc.apply(this, args);
      called = true;
    }
    return cachedResult;
  };
}

效果验证

用给出的测试场景验证:

function multiplyBy3 (a) {
  console.log('目标函数执行');
  return a * 3;
}
const actualFunction = onceCopy(multiplyBy3);

console.log(actualFunction(1)); 
// 输出:目标函数执行、3
console.log(actualFunction(66));
// 输出:3,不会再次触发目标函数执行
console.log(actualFunction(100, '无关参数'));
// 输出:3,目标函数全程仅执行1次

实现中使用apply绑定this、透传剩余参数,是为了和lodash官方_.once行为对齐,避免包装函数丢失上下文、漏传参数的边界问题。

内容的提问来源于stack exchange,提问作者Yassmine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:54:24