发布网友 发布时间:2022-05-10 17:30
共6个回答
懂视网 时间:2022-05-12 13:09
我们之前给大家介绍过关于php中的递归函数、其实递归函数通常在后端用的比较多。对于后端开发人员来说,递归应该是小菜一碟,很简单的事情,但是很多前端确对这个不是很了解。其实,前端中也是经常用递归的,今天我们就给大家解析下JavaScript中的递归函数!js递归调用
// 一个简单的阶乘函数 var f = function (x) { if (x === 1) { return 1; } else { return x * f(x - 1); } };
Javascript中函数的巨大灵活性,导致在递归时使用函数名遇到困难,对于上面的变量式声明,f是一个变量,所以它的值很容易被替换:
var fn = f; f = function () {};
函数是个值,它被赋给fn,我们期待使用fn(5)可以计算出一个数值,但是由于函数内部依然引用的是变量f,于是它不能正常工作了。
所以,一旦我们定义了一个递归函数,便须注意不要轻易改变变量的名字。
上面谈论的都是函数式调用,函数还有其它调用方式,比如当作对象方法调用。
我们常常这样声明对象:
var obj1 = { num : 5, fac : function (x) { // function body } };
声明一个匿名函数并把它赋值给对象的属性(fac)。
如果我们想要在这里写一个递归,就要引用属性本身:
var obj1 = { num : 5, fac : function (x) { if (x === 1) { return 1; } else { return x * obj1.fac(x - 1); } } };
当然,它也会遭遇和函数调用方式一样的问题:
var obj2 = {fac: obj1.fac}; obj1 = {}; obj2.fac(5); // Sadness
方法被赋值给obj2的fac属性后,内部依然要引用obj1.fac,于是…失败了。
换一种方式会有所改进:
var obj1 = { num : 5, fac : function (x) { if (x === 1) { return 1; } else { return x * this.fac(x - 1); } } }; var obj2 = {fac: obj1.fac}; obj1 = {}; obj2.fac(5); // ok
通过this关键字获取函数执行时的context中的属性,这样执行obj2.fac时,函数内部便会引用obj2的fac属性。
可是函数还可以被任意修改context来调用,那就是万能的call和apply:
obj3 = {}; obj1.fac.call(obj3, 5); // dead again
于是递归函数又不能正常工作了。
我们应该试着解决这种问题,还记得前面提到的一种函数声明的方式吗?
var a = function b(){};
这种声明方式叫做内联函数(inline function),虽然在函数外没有声明变量b,但是在函数内部,是可以使用b()来调用自己的,于是
var fn = function f(x) { // try if you write "var f = 0;" here if (x === 1) { return 1; } else { return x * f(x - 1); } }; var fn2 = fn; fn = null; fn2(5); // OK // here show the difference between "var f = function f() {}" and "function f() {}" var f = function f(x) { if (x === 1) { return 1; } else { return x * f(x - 1); } }; var fn2 = f; f = null; fn2(5); // OK var obj1 = { num : 5, fac : function f(x) { if (x === 1) { return 1; } else { return x * f(x - 1); } } }; var obj2 = {fac: obj1.fac}; obj1 = {}; obj2.fac(5); // ok var obj3 = {}; obj1.fac.call(obj3, 5); // ok
就这样,我们有了一个可以在内部使用的名字,而不用担心递归函数被赋值给谁以及以何种方式被调用。
Javascript函数内部的arguments对象,有一个callee属性,指向的是函数本身。因此也可以使用arguments.callee在内部调用函数:
function f(x) { if (x === 1) { return 1; } else { return x * arguments.callee(x - 1); } }
但arguments.callee是一个已经准备被弃用的属性,很可能会在未来的ECMAscript版本中消失,在ECMAscript 5中"use strict"时,不能使用arguments.callee。
最后一个建议是:如果要声明一个递归函数,请慎用new Function这种方式,Function构造函数创建的函数在每次被调用时,都会重新编译出一个函数,递归调用会引发性能问题——你会发现你的内存很快就被耗光了。
js递归函数应用
最近在做项目的时候,用到了递归函数,用来调用json的子节点,把所有json中的子节点中包含某个数的object,都push到一个数组中,然后对其进行绑定。
我是通过如下递归调用的
var new_array=[]; function _getChilds(data){ if(data.ObjType=="某个数"){ new_array.push(cs_data); } if(data.Childs){ if(data.Childs.length>0){ getChilds(data.Childs) } } } function getChilds(data){ for(var i=0;i<data.length;i++){ _getChilds(data[i]); } }使用方法:getChilds("json数据")
就把json中所有包含某个数的数据push到new_array数组当中了。
总结:
相信通过对上述的讲解,大家对递归函数的认识更进阶一步、递归函数不仅仅可以再php中使用,在前端JavaScript中同样可以使用,希望对你有所帮助!
相关推荐:
JavaScript中递归函数的细化认识以及示例代码分享
JS中递归函数
js中递归函数的使用介绍
热心网友 时间:2022-05-12 10:17
其实难点就在于对递归函数的理解。所谓递归函数,就是函数在执行时调用自己。程序在调用一个函数时,首先执行这个函数的程序,执行完毕后返回到原调用前的上一级程序继续运行这一级程序。调用递归函数也是如此,在执行完递归函数,得到3之后,它要退出递归函数回到调用它的原来的主程序继续去执行原来的主程序。由于调用递归函数时程序是逐级进行的,所以返回时也是逆向逐级执行程序并返回的,即在得到3后,返回上一级执行这一级的程序就得到4(即再次执行document.writeln(num1)),再返回上一级执行这一级的程序得到5(即再次执行document.writeln(num1))。热心网友 时间:2022-05-12 11:35
其实就是作用域,在当前函数作用域下num1>3时都只减了一,热心网友 时间:2022-05-12 13:10
第一你算 运行几次 5 4 3 一共3次,为什么是334追答递归递归 有去就有回,去的时候因为条件判断所以去执行别的函数,执行完了就要回去执行原来调用她的函数, 对于递归有点抽象 不是说这一次执行完了就完了 而是要看有没有调用她的函数 或者有没有break exits之类的
热心网友 时间:2022-05-12 15:01
abc(5)第一次执行函数时num1为4,执行abc(4),4大于3,num1为3执行abc(3),3不大于3,所以不执行if语句,打印出3,紧接着返回,返回到abc(4)之后的document,此时的num1为3,所以打印出3,接着返回执行abc(5)的document,打印出4,
热心网友 时间:2022-05-12 17:09
function abc(num1){