ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

递归那点事

2020-08-26 17:04:21  阅读:251  来源: 互联网

标签:return 递归 那点 num fibonacci callee arguments


直接进入正题,什么是递归?——简单来说,递归就是函数内部调用自己。

几个简单的面试题,大家可尝试一做,再看我写的参考代码

1.求1-n的和。(如求1到100的和)

2.阶乘

3.数组扁平化,去重,并排序。( [2,[1,2],[0,9,5],[15,[[4]]]] )

4.斐波那契数列

 

问题很简单,多想想多做做就出来了。

1.求1-n的和。(如求1到100的和)

function sum (num){
    if (num===1) {
        return 1
    } else {
        return sum(num-1) + num
    }
}
console.log(sum(100))   //5050

2.阶乘

function factorial(x){
    if (x===1) {
        return 1
    } else {
        return factorial(x-1) * x
    }
}
console.log('factorial',factorial(3))

 3.数组扁平化,去重,并排序

const arr = [2,[1,2],[0,9,5],[15,[[4]]]]
let result = []
function flat (arr){
    arr.forEach(item => {
        if (Array.isArray(item)) {
            flat(item)
        } else {
            result.push(item)
        }
    })
}
flat(arr)
result = [...new Set(result.sort((x,y) => x-y))]
console.log('递归',result)  //递归 (7) [0, 1, 2, 4, 5, 9, 15 

上面的方法是用递归的方法实现的,补充一提,可以用数组的方法更简单,如下

const flatArr = [...new Set(arr.flat(3).sort((x,y) => x-y))]
console.log('数组方法flat',flatArr);    //数组方法flat (7) [0, 1, 2, 4, 5, 9, 15]

4.斐波那契数列

function fibonacci (num){
    if (num===0) {
        return 0
    }else if (num===1) {
        return 1
    }else {
        return fibonacci(num-1) + fibonacci(num-2)
        // return arguments.callee(num-1) + arguments.callee(num-2)
    }
}
  console.log(fibonacci(6));  //8

 

有细心的朋友,可能会看到我上面的一段注释,用到了arguments.callee,这就是要引出一个递归的一个相关问题了。

当我们拷贝了这个fibonacci函数后,又将该fibonacci函数重新赋值,会报错 fibonacci is not a function,递归调用失败,如下代码

const copyFibonacci = fibonacci
fibonacci = null
console.log('copyFibonacci',copyFibonacci(6));

原因也很简单,报错信息也很明确指出来了,fibonacci不是一个函数,因为已经被我们设为null了。

要解决这一问题,有两种方法

1. 使用arguments.calllee替代fibonacci这个名字进行递归调用,如上注释 

return arguments.callee(num-1) + arguments.callee(num-2)

   arguments指的是实参列表,但是它有一个属性callee,代表的是所处的函数本身

2. 使用命名函数表达式

let fibonacci = function f (num){
    if (num===0) {
        return 0
    }else if (num===1) {
        return 1
    }else {
        return f(num-1) + f(num-2)
    }
}

这样无论fibonacci怎么被赋值改变,函数f并没有改变,这样就不会报错了。

虽然两种方法都能解决这一问题,但是目前我们推荐使用的是第二种方法,因为方法一中的arguments.callee在严格模式中不允许使用。

同时其存在一些缺点:

  1.arguments是一个很大的对象,每次调用都要重新创建,影响浏览器性能   2.递归中的this会不一样,如下代码。(参考自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee)
var global = this;
var sillyFunction = function(recursed) {
    if (!recursed) { return arguments.callee(true); }
    if (this !== global) {
        // 会输出 This is: [object Arguments]
        console.log('This is: ' + this);
    } else {
        console.log('This is the global');
    }
}
sillyFunction();

 

标签:return,递归,那点,num,fibonacci,callee,arguments
来源: https://www.cnblogs.com/nys013/p/13566151.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有