递归调用的函数中内部函数idGenerator是否每次调用都会重新定义?
关于递归函数内部
idGenerator重复定义的问题解答 明确结论
是的,每次调用recursively_add_id(包括递归过程中的每一次调用)时,内部的idGenerator箭头函数都会被重新定义。
运行机制解释
在JavaScript中,函数每被调用一次,就会创建一个全新的执行上下文。函数内部通过let/const声明的变量(包括函数表达式),都会在这个新的执行上下文中完成初始化。
你的代码里,idGenerator是myself(即recursively_add_id)函数的局部变量,所以每一次触发myself调用——不管是外部首次调用,还是递归过程中调用自身——都会重新生成一个idGenerator箭头函数的实例。
开销与优化建议
你猜测的没错,这种重复创建的开销确实极小。现代JavaScript引擎(如Chrome的V8)对这类短生命周期的小型函数有成熟的优化策略,不会对性能造成可感知的影响。
不过如果想彻底避免重复创建,也可以把idGenerator移到递归函数外部,只初始化一次:
方案1:挂载到模块作为私有工具函数
MyModule._idGenerator = () => '_' + (Math.random() * 0x1000000000000000); MyModule.recursively_add_id = function myself(arg) { if (arg === null) return; else if (Array.isArray(arg)) arg.forEach(element => myself(element)); else if (typeof arg === 'object') { for (let key in arg) myself(arg[key]); arg.id = MyModule._idGenerator(); } else // number, string... return; };
方案2:用闭包封装,避免污染模块命名空间
MyModule.recursively_add_id = (function() { // 只在闭包初始化时创建一次 const idGenerator = () => '_' + (Math.random() * 0x1000000000000000); return function myself(arg) { if (arg === null) return; else if (Array.isArray(arg)) arg.forEach(element => myself(element)); else if (typeof arg === 'object') { for (let key in arg) myself(arg[key]); arg.id = idGenerator(); } else // number, string... return; }; })();
内容的提问来源于stack exchange,提问作者Francesco Marchetti-Stasi
相关产品推荐
相关产品推荐

