Javascript为什么我不知道名字已经存在错误

时间:2018-12-16 20:01:11

标签: javascript arrays

我试图理解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中,我们正在检查它是否为数组

从本质上讲,它不是数组,因为company是上面的对象。

  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,所以应该没有错误说明 let sum 已经存在

  2. 无论哪种方式,我们都执行sum = 0,这是否意味着sum数组中的先前值(1600)消失了(换句话说,重置为零?

3 个答案:

答案 0 :(得分: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 :(得分:1)

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

仅当您在同一空间两次声明同一变量

时,才会显示变量已声明的错误。

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

答案 2 :(得分:0)

在javascript中,函数本质上是一个作用域。

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

您只会得到

Identifier has already been declared

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