Javascript为什么我没有得到名称已经存在错误

问题描述 投票:2回答:3

我试图理解Javascript和递归编程的行为。

Npw,我是初学者,所以我需要理解为什么我已经被声明错误,当我没有得到已经声明错误

考虑一下这段代码,我试图理解这将如何执行..

 let company = { // the same object, compressed for brevity
      sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 600 }],
      development: {
        sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
        internals: [{name: 'Jack', salary: 1300}]
      }
    };
    
    // The function to do the job
    function sumSalaries(department) {
      if (Array.isArray(department)) {
        return department.reduce((prev, current) => prev + current.salary, 0);
      } else { // case (2)
        let sum = 0;
        for (let subdep of Object.values(department)) {
          sum = sum + sumSalaries(subdep); 
        }
        return sum;
      }
    }
    
   console.log(sumSalaries(company));// 6700

打破上面代码的执行(如果我理解这个错误,请更正)

  1. 我们正在通过公司作为sumSalaries的论据
  2. 在sumSalaries中,我们正在检查它是否是一个数组

最初它不是一个数组,因为公司是上面的一个对象。

  1. 我们将通过let sum = 0的声明传递它的其他条件
  2. object.values将为我们提供两个数组(基于公司)
  3. let subdep of Object.values(department的第一次迭代中,我们将得到[{…}, {…}] inside which we have following object {name: "John", salary: 1000}
  4. 这里我们的总和= 0,我们将加上我们传递给sumSalaries(subdep);的返回值
  5. 现在,因为我们传递数组,它将转到以下函数 if(Array.isArray(department)){return department.reduce((prev,current)=> prev + current.salary,0); }
  6. 她在我们之前的传递中传递了0并将其与current.salary一起添加。
  7. 由于我们使用reduce,因此它将首先添加0 + 1000然后它将添加1000 + 600
  8. 这将使我们返回1600,因此我们的sum将为0 + 1600
  9. 现在我们的循环将进行第二次迭代,这给了我们一个由两个数组组成的对象......
  10. 由于它是一个物体,它不会传递到if (Array.isArray(department)) {而是转而去else

问题+问题虽然,我正在完成十三点,但我意识到我们的第二个声明让sum = 0

所以,有两件事

  1. 因为我们有let sum = 0,所以不应该有一个错误,说让sum已经存在了
  2. 无论哪种方式,我们都在做sum = 0,这是否意味着sum数组中我们先前的值(1600)消失了(换句话说,重置为零?
javascript arrays
3个回答
4
投票

let是块作用域,这意味着在多个块中有多个声明是可以的。每次调用sumSalaries()时,sum都将重置为零。它不需要记住以前的调用,因为如果找到此调用,它将返回总和,当递归展开时,它将被添加到调用递归函数的父级。

通过策略性放置,console.log()调用或使用调试器来观察递归是有益的。例如,您可以观看总和加起来:

 let company = { // the same object, compressed for brevity
      sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 600 }],
      development: {
        sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
        internals: [{name: 'Jack', salary: 1300}]
      }
    };
    
    // The function to do the job
    function sumSalaries(department) {
      if (Array.isArray(department)) {
        return department.reduce((prev, current) => prev + current.salary, 0);
      } else { // case (2)
        console.log("starting new object")
        let sum = 0;
        for (let subdep of Object.values(department)) {
          let subsum =  sumSalaries(subdep)
          console.log("subsum = ", subsum)
          sum = sum + subsum; 
        }
        console.log("current sum:", sum)
        return sum;
      }
    }
    
   console.log(sumSalaries(company));// 6700

1
投票

每次调用函数时,它都会创建一个新空间(通常称为“范围”或“堆栈框架”)来保存在其中声明的所有变量。

只有在同一空间中声明两次相同的变量时,才会显示变量已声明的错误

因为在第一次调用sumSalaries和第二次(递归)调用时创建的“sum”变量位于不同的空格中,所以不会出现错误。


0
投票

在javascript中,函数本质上是一个范围。

相同函数的递归调用也将是独立的范围。在前一个递归函数调用中声明的变量sum与在下一个函数调用中声明的变量不同。

你只会得到

Identifier has already been declared

如果在同一范围内声明变量两次。

© www.soinside.com 2019 - 2024. All rights reserved.