JS递归--你不知道的匿名递归函数细节

递归

  • 递归函数必须能够引用它本身
  • 递归是函数自己调用自己
  • 一般都需要一个结束的条件

递归的认识

  • 写出一个数的阶乘
function fn(n){
		if(n===1){
			return 1
		}
		return n*fn(n-1)
	}
	console.log(fn(4)) //4的阶乘
  • 递归的报错
    一般没有写结束条件(如上面的if(n===1){return 1})的情况下报错
    Uncaught RangeError: Maximum call stack size exceeded
    即内存溢出:超过了最大的堆栈大小

匿名递归函数(jQuery下个知识点)

  • 很典型的,函数通过自己的名字调用自己(如上面的案例)
  • 然而,匿名函数是没有名称。因此如果没有可访问的变量指向该函数,唯一能引用它的方式就是通过 arguments.callee
function createFn(){
		return function(n){
			if(n===1){
				return 1
			}
			return n*arguments.callee(n-1)
		}
	}
	var f1 = createFn()
	console.log(f1(4))

然而,这实际上是一个非常糟糕的解决方案,另外,递归调用在一些情况会获取到一个不同的this值

var global = this;
	function createFn(){
		return function(n){
			if(n===1){
				if (this !== global) {
        			alert("This is: " + this); //执行
    			} else {
        			alert("This is the global");
    			}
				return 1
			}
			return n*arguments.callee(n-1)
		}
	}
	var f1 = createFn()
	console.log(f1(4))

jQuery匿名递归函数

  1. 我们在使用 jQuery大部分都会使用到回调函数
  2. jQ除了兼容性好,主要突出的两个特点就是链式编程和隐式迭代
  3. 那么 arguments.callee就显得很有必要
  4. 我们通过案例说明;准备四张图片,并给它设置大小,引入jquery.js
<input type="button" value="隐藏动画" id="btn1"/>
<input type="button" value="显示动画" id="btn2"/>
<div>
    <img src="images/1.jpg"/>
    <img src="images/2.jpg"/>
    <img src="images/3.jpg"/>
    <img src="images/4.jpg"/>
</div>

效果如下:
图片设置宽高即可


接下来需求是:我们点击隐藏动画从最后一张图片在一定时间开始隐藏完毕后,在隐藏倒数第三张,倒数第三张图片隐藏完毕后,在隐藏第二张…
很累赘的代码演示(记得引入jQuery)

$('#btn1').on('click',function(){
			$('img').eq(3).hide(1000,function(){
				$(this).prev().hide(800,function(){
					$(this).prev().hide(800,function(){
						$(this).prev().hide(800)
					})
				})
			})
		})

虽然能解决问题,但是是一百张图片,或则其它情况呢?这样的代码大量重复,冗余和累赘,不是良好的代码风格,封装起来一层嵌套一层,会极大影响代码可读性和逻辑


从上面可以看出,匿名函数自己调用自己,正好符合递归,但是封装成一个命名函数,影响代码可读性和逻辑,这个时候arguments.callee就是很好的解决方案

$('#btn1').on('click',function(){
			$('img').eq(3).hide(1000,function(){
				$(this).prev().hide(800,arguments.callee);
			})
		})

这样代码量少,看起来高大上了很多,具有可读性和逻辑性

如何使用递归

  1. 两个必要条件: 递归方程,递归结束条件
  2. 一般递归是从后往前推,可以根据结束条件和函数参数的变化来死开
  3. 递归是函数体调用自己,一般都是在特定的情况下使用:
    案例:求菲波那切数列的第n个数是多少
function Fibonacci(n){
		if(n==1 || n==2){
			return 1
		}
		return Fibonacci(n-1) + Fibonacci(n-2)
	}
	console.log(Fibonacci(5))

猜你喜欢

转载自blog.csdn.net/weixin_41105030/article/details/85224641