javascript - 函数内部命名函数表达式的模式
问题描述
以下代码取自 Jest 源代码:
function _path() {
const data = _interopRequireDefault(require('path'));
_path = function _path() {
return data;
};
return data;
}
为什么我们中间有命名函数表达式?如何以及何时可以使用该模式?
解决方案
调用外部函数_path
。然后在其中,该行用另一个名为 的函数_path = function _path()
覆盖_path
变量(当前分配给_path
函数)_path
。
因此,当执行该函数时,该函数会用一个新函数覆盖自己,该函数将做不同的事情。下面是这个原理的一个简单说明:
function f() {
console.log("outer");
f = function f() {
console.log("inner");
}
}
f(); //outer
f(); //inner
f(); //inner
所以,这就是它正在做的事情。至于它为什么这样做——缓存。它只需要查找/计算一次值,然后将缓存所有其他执行。因此,这是一个示例,其中lookup
是网络操作的模拟替身。
function lookup() {
console.log("making a network call");
return 4;
}
function f() {
var output = lookup();
f = function f() {
return output;
}
return output;
}
console.log(f()); //network call -> 4
console.log(f()); //4
console.log(f()); //4
不需要网络调用的繁重计算也可以做到这一点——而不是每次都重复计算并耗尽 CPU 周期,结果只能计算一次。
最后,为什么调用内部函数_path
- 没有严格的理由来调用它。即使没有名称,该代码也可以正常工作。但是,它确实替换了外部函数,因此保留名称是个好主意。当您看到堆栈跟踪时,它还可以帮助调试。
通常,这种技术称为记忆化。旁注:这是正确的拼写,不是r。虽然我怀疑如果你把它放进去,任何人都会感到困惑。
无论如何,记忆涉及计算一次函数,并且每隔一次才返回结果。一种通用的方法是拥有一个memoize
可以装饰其他功能的功能。这是一个示例实现:
function memoize(func) {
//keep a cache for all results
const cache = {};
//make a new function
const memo = function() {
//get the arguments from the input
var key = JSON.stringify(...arguments);
let result;
if (cache.hasOwnProperty(key)) {
//get result from cache
result = cache[key];
} else {
//calculate the result and put it in the cache
result = func(...arguments);
cache[key] = result;
}
return result;
}
return memo;
}
function lookup(data) {
console.log("network call");
return data + 4;
}
function calculate(data) {
console.log("heavy operation");
return data + 2;
}
let memLookup = memoize(lookup);
console.log(memLookup(4)); //network call -> 8
console.log(memLookup(4)); //8
console.log(memLookup(6)); //network call -> 10
console.log(memLookup(6)); //10
let memCalculate = memoize(calculate);
console.log(memCalculate(4)); //heavy operation -> 6
console.log(memCalculate(4)); //6
console.log(memCalculate(6)); //heavy operation -> 8
console.log(memCalculate(6)); //8
推荐阅读
- javascript - 图的深度优先搜索 (DFS) 中的 for/of 和 forEach 有什么区别?
- python - ImportError:使用 QRTools 时没有名为 zbar 的模块
- c++ - 如何在中使用 setfill()
更流利? - sql - 使用条件创建包含 MAX() 值的 SUM() 的查询
- c++ - 计算可以存储在变量中的计算器程序
- tampermonkey - 铬 | TamperMonkey 脚本 - 在新选项卡中打开所有链接
- python - 在字符串中映射
- reactjs - 使用单独页面上的参数链接到不同的 React 组件
- macos - 无法通过 Pop!_OS / Ubuntu 安装 macOS
- reactjs - 无法从商店获取选择器功能中的任何内容