我在逆向工程一些JavaScript时遇到了这个函数:
function fun1() { const arr = ["a", "b", "c", "d", "e"]; fun1 = function () { return arr; }; return fun1(); }
对我来说,它看起来是多余的。这段代码似乎:
arr
。arr
。return fun1()
返回函数本身的结果,现在已经重新定义为返回arr
,所以这似乎返回arr
。因此,我重写了这个函数,消除了所有多余的代码:
function fun2() { const arr = ["a", "b", "c", "d", "e"]; return arr; }
然而,我惊讶地发现这两个函数的行为完全不同。
fun1()
似乎返回对arr
的引用,而fun2()
似乎返回arr
的副本。
这里有一个可运行的最小可复现示例来说明差异:
// This function is redefined inside itself to return arr function fun1() { const arr = ["a", "b", "c", "d", "e"]; fun1 = function() { return arr; }; return fun1(); } // Why not return arr directly? function fun2() { const arr = ["a", "b", "c", "d", "e"]; return arr; } // But the result is different... let test_fun_1 = fun1(); test_fun_1.pop(); test_fun_1 = fun1(); console.log("Logging test_fun_1"); console.log(test_fun_1); // ["a", "b", "c", "d"] let test_fun_2 = fun2(); test_fun_2.pop(); test_fun_2 = fun2(); console.log("Logging test_fun_2"); console.log(test_fun_2); // ["a", "b", "c", "d", "e"] // What is this magic?
看起来像是发生了魔法...
fun1()
和fun2()
之间有什么区别?
当第一次调用时,您的
fun1()
函数重新定义了(相对)全局的fun1
符号。它将原始函数更改为局部内部函数,该函数关闭了数组。因此,只涉及一个数组,即第一次调用fun1()
时创建的数组。另一方面,您的
fun2()
每次调用时都会创建一个全新的数组。如果您将
fun1()
更改为将内部函数分配给一个局部声明的fun1
变量,它将与fun2()
的行为相同。