JavaScript中arguments.callee属性的作用与替换方案

arguments.callee的作用

在函数内部,有两个特殊的对象:arguments 和 this。其中, arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。 请看下面这个非常经典的阶乘函数

function factorial(num){
   if (num <=1) {
      return 1;
   } else {
   return num * factorial(num-1)
   }
}

定义阶乘函数一般都要用到递归算法;如上面的代码所示,在函数有名字,而且名字以后也不会变 的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为 了消除这种紧密耦合的现象,可以像下面这样使用 arguments.callee

function factorial(num){
   if (num <=1) {
      return 1;
   } else {
   return num * arguments.callee(num-1);
   }
}

在这个重写后的 factorial()函数的函数体内,没有再引用函数名 factorial。这样,无论引用 函数时使用的是什么名字,都可以保证正常完成递归调用。例如

function factorial(num){
          if(num <= 1){
              return 1;
          }else{
              return num * arguments.callee(num-1);
          }
      }
      var trueFactorial = factorial;
      alert(trueFactorial(5));    //120   

      factorial = function() {
          return 0;
      }
      alert(trueFactorial(5));// 120 如果没有使用arguments.callee,将返回0

在此,变量 trueFactorial 获得了 factorial 的值,实际上是在另一个位置上保存了一个函数 的指针。然后,我们又将一个简单地返回 0的函数赋值给 factorial 变量。如果像原来的 factorial() 那样不使用 arguments.callee,调用 trueFactorial()就会返回 0。可是,在解除了函数体内的代 码与函数名的耦合状态之后,trueFactorial()仍然能够正常地计算阶乘;至于 factorial(),它现 在只是一个返回 0的函数。

arguments.callee的替换方案

现在已经不推荐使用arguments.callee();

原因:访问 arguments 是个很昂贵的操作,因为它是个很大的对象,每次递归调用时都需要重新创建。影响现代浏览器的性能,还会影响闭包。

不能用怎么办?

像第三段中的例子,重写 factorial()方法导致trueFactorial()结果不在预期。是为了演示而做的。平时写代码应该避免。

递归时用到arguments.callee()是常见的事情,比如

一道面试题。接受参数n=5,不用for循环输出数组【1,2,3,4,5】

这用递归的思路,配合arguments.callee,代码如下

function show(n) {
    var arr = [];
    return (function () {
        arr.unshift(n);
        n--;
        if (n != 0) {
            arguments.callee();
        }
        return arr;
    })()
}
show(5)//[1,2,3,4,5]

现在arguments.callee 被弃用了。怎么办,其实很简单,给内部函数一个名字即可

function show(n) {
    var arr = [];
    return (function fn() {
        arr.unshift(n);
        n--;
        if (n != 0) {
            fn();
        }
        return arr;

    })()
}
show(5)//[1,2,3,4,5]

斐波那契递归算法替换

function factorial(num) {
      if (num <= 1) {
        return 1
      }
      var fac = 1
      return (function fn() {
        fac *= num
        num--
        if (num != 0) {
          fn()
        }
        return fac
      })()
    }
    factorial(5) // 120

到此这篇关于JavaScript中arguments.callee属性的作用与替换方案的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2022-06-24

js arguments.callee的应用代码

复制代码 代码如下: function f(x){ alert(x); return arguments.callee; } f(0)(1)(2)(3)(4)(5)(6)(7)(8)(9); 复制代码 代码如下: function f(){ var a=arguments,i,l=a.length; for(i=0; i<l;i++){ alert(a[i]); } return arguments.callee; } f(0)(1,2)(3,4,5)(6,7,8,9);

Javascript函数中的arguments.callee用法实例分析

本文实例讲述了Javascript函数中的arguments.callee用法.分享给大话公大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml&

Javascript中arguments和arguments.callee的区别浅析

通过一个例子来理解下arguments与arguments.callee的具体区别: 代码如下: 复制代码 代码如下: <script type="text/javascript">                 function check(args){                         var ac = args.length;              var ex = args.callee.length;              document

JavaScript arguments.callee作用及替换方案详解

一.arguments.callee的作用:返回正被执行的 Function 对象 arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文,这有利于匿名函数的递归或者保证函数的封装性. 请看下面这个非常经典的阶乘函数 function factorial(num){ if (num <=1) { return 1; } else { return num * factori

js arguments,jcallee caller用法总结

关键字:arguments,callee,callerarguments:表示传入函数的参数callee:表示函数和函数主体的语句caller:表示调用该函数的函数arguments 该对象代表正在执行的函数和调用它的函数的参数. caller 返回一个对函数的引用,该函数调用了当前函数.functionName.callerfunctionName 对象是所执行函数的名称. 说明对于函数来说,caller属性只有在函数执行时才有定义.如果函数是由顶层调用的,那么 caller包含的就是 nul

js的隐含参数(arguments,callee,caller)使用方法

在提到上述的概念之前,首先想说说javascript中函数的隐含参数: arguments arguments 该对象代表正在执行的函数和调用它的函数的参数.[function.]arguments[n]参数function:选项.当前正在执行的 Function 对象的名字. n :选项.要传递给 Function 对象的从0开始的参数值索引.说明Arguments是进行函数调用时,除了指定的参数外,还另外创建的一个隐藏对象.Arguments是一个类似数组但不是数组的对象,说它类似数组是因为

关于arguments,callee,caller等的测试

关于arguments,callee,caller等的测试 function testArg() { var sTemp ="test()开始执行\n\n函数定义的正文:\n\n"; sTemp+=arguments.callee + "\n\n"; sTemp+="传入参数的长度:\n"; sTemp+=arguments.length+"\n\n"; sTemp+="传入参数的内容:\n"; for (

javascript中call,apply,callee,caller用法实例分析

本文实例讲述了javascript中call,apply,callee,caller用法.分享给大家供大家参考,具体如下: 实践一:call,apply 用来让一个对象去调用本不属于自己的方法,两者都可以传递参数,call的参数是列表形式,apply的参数是数组形式 var person = { "name":"Tom", "say":function(){ console.log("person say"); }, &quo

JS数组方法concat()用法实例分析

本文实例讲述了JS数组方法concat()用法.分享给大家供大家参考,具体如下: 数组方法concat() concat()可以基于当前数组中的所有项创建一个新数组.即这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组. 没有给concat方法传递参数的情况下,它只是复制当前数组并返回副本. 如果传递的是一或多个数组,则该方法会将这些数组中的每一项都添加到结果数组中 如果传递的值是不是数组,这些值会被简单的添加到数组的末尾 注意:该方法不会改变先后的数

JS数组方法join()用法实例分析

本文实例讲述了JS数组方法join()用法.分享给大家供大家参考,具体如下: join()方法 定义和用法: join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 语法:arrayObject.join(separator) 参数:可选,指定要使用的分隔符. 注:不给join()方法传入任何值,或者给它传入undefined,则使用逗号作为分隔符. IE7及更早版本会错误的使用字符串"undefined"作为分隔符. 数组中的某一项是null或u

JS数组方法slice()用法实例分析

本文实例讲述了JS数组方法slice()用法.分享给大家供大家参考,具体如下: slice()方法 slice(),它能基于当前数组中的一个或多个创建一个新数组.可以接受一或两个参数,即要返回的起始和结束位置. 一个参数:slice()方法返回从该参数指定位置开始到当前数组末尾的所有项. 两个参数:该方法返回起始和结束位置之间的项(但不包括结束位置的项). slice不会影响原始数组. 结束位置小于起始位置,返回空数组. 可以接受负数,用数组长度加上该负数来确定相应位置. var arr = [

js简单工厂模式用法实例

本文实例讲述了js简单工厂模式用法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html> <html> <head> <title>简单工厂模式</title> </head> <body> <script> //简单工厂模式 var BicycleShop = function(){}; BicycleShop.prototype ={ sellBicycle : function(mod

js常用系统函数用法实例分析

本文实例讲述了js常用系统函数用法.分享给大家供大家参考. 具体代码如下: 复制代码 代码如下: <html> <head> </head> <body> <script type="text/javascript"> //1. escape()函数,把字符串转成各计算机平台通用的unicode编码:解码(转回去)则用enescape(). var str = '王美人'; document.write(escape(str)

JS产生随机数的用法小结

代码如下所述: <script> function GetRandomNum(Min,Max) { var Range = Max - Min; var Rand = Math.random(); return(Min + Math.round(Rand * Range)); } var num = GetRandomNum(1,10); alert(num); </script> var chars = ['0','1','2','3','4','5','6','7','8','