JavaScript 中的列表分配如何工作?

How does list assignment work in JavaScript?

我正在阅读 Eloquent JavaScript 练习部分,我遇到了书中以下代码的问题:

function arrayToList(array) {
  let list = null;
  for (let i = array.length - 1; i >= 0; i--) {
    list = {value: array[i], rest: list};
  }
  return list;
}
console.log(arrayToList([10, 20]));
// → {value: 10, rest: {value: 20, rest: null}}

首先,我不明白console.log 怎么会有那个输出。我对 list = {value: array[i], rest: list}; 部分特别困惑。我知道在第一次迭代中,array[i] 等于 20,因此列表现在是 {value: 20, rest: null}。在第二次迭代中,array[i]10,因此列表现在是 {value: 10, rest: list},而 list 指的是 {value: 20, rest: null},因此我们有 list = {value: 10, rest: {value: 20, rest: null}}。我的理解正确吗?如果是,我觉得很困惑,list 在被赋值时如何仍然记得它之前包含的值,即 {value: 20, rest: null}。有人可以解释一下吗?

其次,我不明白为什么会提到:

'Building up a list is easier when done back to front. So arrayToList could iterate over the array backwards (see the previous exercise) and, for each element, add an object to the list. You can use a local binding to hold the part of the list that was built so far and use an assignment like list = {value: X, rest: list} to add an element.'

为什么从前到后更容易建立列表?但是,从前到后完成后是否可以构建列表?

第三,当我尝试将上面的代码更改为以下代码时:

function arrayToList(...array) { //Only change is from array to ...array
  let list = null;
  for (let i = array.length - 1; i >= 0; i--) {
    list = {value: array[i], rest: list};
  }
  return list;
}
console.log(arrayToList([10, 20]));
// → {value: [10, 20], rest: null} Why did the output change?

当您在第二个版本中使用扩展语法时,您是在说您希望将函数的所有参数收集到一个数组中(称为 "array")。当您实际 调用 函数时,您传递了一个 单个 参数:数组 [10, 20]。因此,在函数中,array 将是 [[10, 20]] — 一个以该数组作为其单个元素的数组。因此,循环只会进行一次迭代。

如果你用

调用第二个版本的函数
console.log(arrayToList(10, 20))

您会得到更像您在第一个代码示例中得到的结果。函数中的 "array" 参数将是 两个 值的数组,1020.

至于 "expression" 是什么的问题,这是一种语法结构,直观上很容易 "get",但(尤其是 JavaScript)非常复杂细节。基本上,类似于数学(代数)构造或比较,甚至单个变量引用或函数调用之类的东西都是表达式。 语句只能由一个(可能很大的)表达式组成,但语句也可以是for循环、varlet 声明,一个 return 声明,以及其他各种东西。 JavaScript 语法通常会引入带有特定关键字的语句,except 用于表达式语句。