JavaScript 中参数值在运行时发生变化

1 javascript

请考虑以下代码:

function func1(a, b) {
  let args = arguments;
  console.log(args);

  return function() {
    for (let i in args) {
      console.log(args[i], a, b)
      args[i] += (a + b);
      console.log("|")
      console.log(args[i], a, b);
      console.log("end")
    }
  }
}

func1(2, 4)();
Run Code Online (Sandbox Code Playgroud)

这给出了以下输出

2 2 4
|
8 8 4
end
4 8 4
|
16 8 16
end
Run Code Online (Sandbox Code Playgroud)

这里的值如何a, b变化?

T.J*_*der 5

在松散模式下,\xc2\xb9arguments伪数组具有到函数形式参数的实时链接。这是一个更简单的例子:

\n

\r\n
\r\n
function example(a) {\n    console.log("before, a = " + a);\n    ++arguments[0];\n    console.log("after, a = " + a);\n}\n\nexample(1);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

如您所见,++arguments[0] 修改了 的值a

\n

这个令人毛骨悚然的链接在严格模式下被删除,所有新代码都应该使用它(明确地,或通过使用模块):

\n

\r\n
\r\n
"use strict";\nfunction example(a) {\n    console.log("before, a = " + a);\n    ++arguments[0];\n    console.log("after, a = " + a);\n}\n\nexample(1);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n


\n

在评论中,您问:

\n
\n

因此,即使我们克隆参数,它仍然具有与其克隆的实时链接?

\n
\n

问题中的代码中没有任何内容克隆该arguments对象。let args = arguments;只是指向args对象,而不是复制它。你从以下开始:

\n
\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92+\参数:\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92>| (参数对象) |\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92 \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2 \x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88 \x92\xe2\x88\x92\xe2\x88\x92+\n | (到a、b的幽灵链接)|\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2 \x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88 \x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92 \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92+\n
\n

然后let args = arguments;就这样做:

\n
\n \参数:\xe2\x88\x92\xe2\x88\x92+\n | \n | +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92+\n +\xe2\x88\x92\xe2\x88\x92>| (参数对象)|\n | +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92+\n | | (到a、b的幽灵链接)|\nargs:\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2 \x88\x92+ +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92+\n\n\n
\n

它仍然是同一个对象。

\n

如果你复制它(只是浅拷贝就可以了),那么你可以修改副本而不影响aand b

\n
let args = [...arguments]; // Or `= Array.prototype.slice.call(arguments);`\n
Run Code Online (Sandbox Code Playgroud)\n

然后你得到:

\n
\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92+\参数:\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92>| (参数对象) |\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92 \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2 \x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88 \x92\xe2\x88\x92\xe2\x88\x92+\n | (到a、b的幽灵链接)|\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2 \x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88 \x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92 \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92+\n\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92+\nargss:\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92 \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92>| (数组) |\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\ xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\ x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\ x92\xe2\x88\x92\xe2\x88\x92+\n | 0:从 `a` 复制的值 |\n | 1: 从 `b` 复制的值 |\n +\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2 \x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88 \x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92 \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92+\n
\n

...并且更改为args不显示在a和中b

\n
\n

\xc2\xb9 松散模式,遗憾的是,通常被称为“草率”模式

\n