简体   繁体   English

Javascript unshift(),递归和制作数组

[英]Javascript unshift(), recursion and making an array

function countdown(n) {
  if (n < 1) {
    return [];
  } else {
    const arr = countdown(n - 1);
    arr.unshift(n);
    return arr;
  }
}

I found the above code in freeCodeCamp.我在 freeCodeCamp 中找到了上面的代码。 I ran it on VS code.我在 VS 代码上运行它。 It works, but I don't understand how.它有效,但我不明白如何。 Here is my question: How can you unshift() onto a variable that has not yet been declared as an array such as [] ?这是我的问题:如何将unshift()移到尚未声明为数组(例如[] unshift()的变量上? It just says that const arr = countdown(n-1) .它只是说const arr = countdown(n-1) It does not say that const arr is an array such as " [] ".它并没有说const arr是一个数组,例如“ [] ”。 If I try to unshift() integers onto a variable that has been declared as just " arr " without any " [] ", it runs as an error.如果我尝试将unshift()整数移到已声明为“ arr ”而没有任何“ [] ”的变量上,它将作为错误运行。 However, in this code that I found on freeCodeCamp, it works.但是,在我在 freeCodeCamp 上找到的这段代码中,它可以工作。 Why?为什么?

substitution代换

If I say x = 5 and then ask "What is x + 3 ?"如果我说x = 5然后问x + 3什么?” . . Without much help one can answer, 8 .无需太多帮助即可回答, 8 When you are asked how you arrived at your answer, you explain that you substituted x with its value, five, and then added plus three.当您被问及如何得出答案时,您解释说您x的值 5替换了x ,然后加上了 3。

If given a function f(x) = 3 * x + 2 or max(a,b) = a > b ? a : b如果给定函数f(x) = 3 * x + 2max(a,b) = a > b ? a : b max(a,b) = a > b ? a : b , I can ask you other questions like what is f(4) or max(9,7) ? max(a,b) = a > b ? a : b ,我可以问你其他问题,比如什么是f(4)max(9,7) And you'll arrive at the answer the same way:你会以同样的方式得出答案:

  • What is f(4) ?什么是f(4)
    • What is f ?什么是f f is x -> 3 * x + 2 fx -> 3 * x + 2
    • What is x ? x是什么? x is 4 x4
    • What is 3 * 4 + 2 ?什么是3 * 4 + 2
      • What is 3 * 4 ?什么是3 * 4 → The answer is 12 → 答案是12
      • What is 12 + 2 ?什么是12 + 2 → The answer is 14 → 答案是14
      • The answer is 14答案是14
    • The answer is 14答案是14
  • The answer is 14答案是14

  • What is max(9,7) ?什么是max(9,7)
    • What is max ?什么是max max is (a,b) => a > b ? a : b max(a,b) => a > b ? a : b (a,b) => a > b ? a : b
    • What are a and b ?什么是ab a is 9 and b is 7 a9b7
    • What is 9 > 7 ? 9 : 7什么是9 > 7 ? 9 : 7 9 > 7 ? 9 : 7 ? 9 > 7 ? 9 : 7
      • What is 9 > 7 ?什么是9 > 7 → The answer is true → 答案是true
      • What is true ? 9 : 7什么是true ? 9 : 7 true ? 9 : 7 ? true ? 9 : 7 → The answer is 9 → 答案是9
      • The answer is 9答案是9
    • The answer is 9答案是9
  • The answer is 9答案是9

And so with a recursive function, we can use substitution to answer these questions所以使用递归函数,我们可以使用替换来回答这些问题

  • What is countdown(5) ?什么是countdown(5)
    • What is countdown ?什么是countdown
      • countdown is countdown
        function countdown(n) { if (n < 1) { return []; } else { const arr = countdown(n - 1); arr.unshift(n); return arr; } }
    • What is n ?什么是n n is 5 n5
    • What is ...?什么是 ...?
       if (5 < 1) { return []; } else { const arr = countdown(5 - 1); arr.unshift(5); return arr; }
      • What is 5 < 1 .什么是5 < 1 → The answer is false → 答案是false
      • What is ...?什么是 ...?
         if (false) { return []; } else { const arr = countdown(5 - 1); arr.unshift(5); return arr; }
        • The answer is答案是
          const arr = countdown(5 - 1); arr.unshift(5); return arr;
        • What is arr ?什么是arr
          • The answer is countdown(5 - 1)答案是countdown(5 - 1)
          • What is 5 - 1 ?什么是5 - 1 → The answer is 4 → 答案是4
          • What is countdown(4) ?什么是countdown(4)

so what is arr ?那么什么是arr

Using substitution to compute countdown(5) leads us to compute countdown(4) , where again we can use substitution.使用替换来计算countdown(5)导致我们计算countdown(4) ,我们可以再次使用替换。 countdown(4) will look almost exactly the same as before, and as you continue on with countdown(3) and countdown(2) we notice the n - 1 pattern play out. countdown(4)看起来几乎和以前一样,当你继续countdown(3)countdown(2)我们注意到n - 1模式出现了。 Until finally n = 0 and the conditional n < 1 is now true ...直到最后n = 0并且条件n < 1现在为true ...

  • What is countdown(0) ?什么是countdown(0)
    • The answer is []答案是[]

We can use substitution all the way -我们可以一直使用替换——

  • What is countdown(3) ?什么是countdown(3)
    • What is arr ?什么是arr
    • arr is countdown(3 - 1) arrcountdown(3 - 1)
    • What is countdown(2) ?什么是countdown(2)
      • What is arr ?什么是arr
      • arr is countdown(2 - 1) arrcountdown(2 - 1)
      • What is countdown(1) ?什么是countdown(1)
        • What is arr ?什么是arr
        • arr is countdown(1 - 1) arrcountdown(1 - 1)
        • What is countdown(0) ?什么是countdown(0)
          • The answer is []答案是[]
        • arr is [] arr[]
        • What is arr.unshift(1) ?什么是arr.unshift(1) → * The answer is [1] → * 答案是[1]
        • The answer is [1]答案是[1]
      • arr is [1] arr[1]
      • What is arr.unshift(2) ?什么是arr.unshift(2) → The answer is [2,1] → 答案是[2,1]
      • The answer is [2,1]答案是[2,1]
    • arr is [2,1] arr[2,1]
    • What is arr.unshift(3) ?什么是arr.unshift(3) → The answer is [3,2,1] → 答案是[3,2,1]
    • The answer is [3,2,1]答案是[3,2,1]
  • The answer is [3,2,1]答案是[3,2,1]

one caveat一个警告

Recursion is a functional heritage and so using it with functional discipline yields the best results.递归是一种函数式遗产,因此将它与函数式学科结合使用会产生最好的结果。 This means avoiding things like mutation, variable reassignment, and other side effects.这意味着避免诸如突变、变量重新分配和其他副作用之类的事情。 Above we can use substitution because countdown has referential transparency .上面我们可以使用替换,因为countdown具有参考透明度 That's a fancy way to say that the function always returns the same result if the same inputs were given.这是一种奇特的说法,如果给出相同的输入,函数总是返回相同的结果。 In functional discipline you always design functions in this way, so your programs can be assembled and combined, like formulas in an evolving system of equations.在函数式学科中,您总是以这种方式设计函数,因此您的程序可以组装和组合,就像不断发展的方程系统中的公式一样。

there is no arr没有arr

JavaScript has strong support for functional style and so our programs can be written with rich expressions. JavaScript 对函数式风格有很强的支持,所以我们的程序可以用丰富的表达式来编写。 Program semantics are undisturbed by intermediate assignments like arr and syntax boilerplate like if , else , return , and {...} lying about.程序语义不受中间赋值(如arr和语法样板(如ifelsereturn{...}干扰。

 const countdown = n => n < 1 ? [] : [ n, ...countdown(n - 1) ] console.log(countdown(5))

[5,4,3,2,1]

This works because arr is actually declared as an array.这是有效的,因为arr实际上被声明为一个数组。 This is because when arr is declared it is declared as the output of countdown(n -1) .这是因为在声明 arr 时,它被声明为countdown(n -1)的输出。 Since countdown has an exit condition that returns a new array [] which will eventually be reached because n is decreasing every time its called.由于countdown有一个退出条件,它返回一个新的数组[] ,它最终会被到达,因为每次调用n都会减少。 This is a basic example of recursion, a goog way to find out how it works is to step through the code in you mind or a debugger.这是递归的一个基本示例,找出它是如何工作的一种goog 方法是单步执行您脑海中的代码或调试器。

According to its definition, the function countdown satisfies the equations根据其定义,函数countdown满足方程

.....
countdown(-2) = []
countdown(-1) = []
countdown(0) = []
countdown(1) = { const arr = countdown(0);
                 arr.unshift(1);
                 return arr;  }
             = countdown(0).unshift(1);        // countdown(0)=[]
             = [].unshift(1);
             = [1]
countdown(2) = countdown(1).unshift(2);        // countdown(1)=[1]
             = [1].unshift(2);
             = [2,1]
countdown(3) = countdown(2).unshift(3);        // countdown(2)=[2,1]
             = [2,1].unshift(3);
             = [3,2,1]
.....

so actually everything is defined quite alright.所以实际上一切都定义得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM