js中的arguments是一个好东西

2,702 阅读3分钟

今天有空拿出《JavaScript高级程序设计》再仔细看了下,发现js这门语言真是灵活,可以说充满了黑魔法。

今儿给大伙讲js中黑魔法之一类数组对象:

arguments

一、什么是arguments?

在js中,我们在调用有参数的函数时,当往这个调用的有参函数传参时,js会把所传的参数全部存到一个叫arguments的对象里面。

类如:

function test(a,b,c,d,e,f){
    console.log(arguments)
}
test(1,2,3,4,5,6)

在Chrome的控制台运行这段代码:

我们发现arguments的__proto__是Object,证明了arguments是个对象类型,并不是数组。它的属性名是按照传入参数的序列来的,第1个参数的属性名是"0",第2个参数的属性名是"1",以此类推,属性名类似数组中的索引值。

那么问题来了,arguments是怎么产生的呢?

Javascrip中每个函数都会有一个Arguments对象实例arguments,引用着函数的实参。它是寄生在js函数当中的,不能显式创建,arguments对象只有函数开始时才可用。

那么,既然arguments是一个对象,除了根据所在函数的实参动态生成的属性名之外,也有其他的属性名。

比如:arguments.length为函数实参个数,arguments.callee引用函数自身。

js中的arguments是真的6

有了arguments这个对象之后,我们可以不用给函数预先设定形参了,可以动态地通过arguments为函数加入参数。这也说明JS这门语言是真的皮,并不会验证传递给函数的参数个数是否等于函数定义的参数个数,不像java语言那样严谨。

function add() {  
    if( arguments.length == 2 ){       
        return arguments[0] + arguments[1];   
    }else{  
        return '传入参数不合法';    
        } 
    
}  
console.log( add(2,3) ); 
console.log( add(1,2,3) );    

这在java中就得根据参数不同进行多次重载了,而js中没有重载机制,多个同名不同参的函数,最js文档最下面的那个函数给直接覆盖。

所以,面对同名不同参的情况,我们可以利用arguments对参数进行判断,从而进行不同的运算。

arguments的属性介绍

arguments.length就不用多讲了,指的是函数传入实参的个数。

arguments.callee是指向当前正在执行函数的指针(引用),直白点来说,就是这个属性值就是当前函数的代码。

function add() {  
    var a =2;
    var b = 3;
    var c = a+b;
    console.log(arguments.callee);
    console.log(c)
} 
add()

arguments.callee的使用

在《js高级程序设计》的递归章节中,有这样的一段示例代码:

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

arguments.callee可以实现对函数的递归使用,上述的代码可以写成这样:

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

通过使用arguments.callee代替函数名,可以确保无论怎么样调用函数都不会出现问题。因此,在编写递归时,使用arguments.callee总比使用函数名更保险。 ——《js高程》原话

这里又出现了一个问题,怎么说使用函数名不保险呢?

当函数出现这样的调用时,

var anfactorial = factorial;
factorial = null;
console.log(anfactorial(4))

第一种情况会出现报错:

第二种用arguments.callee代替函数名,正常执行:

但是在ES4中新增的严格模式中,arguments.callee这个属性会导致错误。可能自己人都看不惯js这么皮了,限制了一下。 在没有使用严格模式的情况下,可以使用。对外封装开源的小插件,不建议用arguments.callee,但是arguments是基本都会用到的。

arguments是一个好东西。

本文参考了《JavaScript高级程序设计》

js中arguments的用法[www.cnblogs.com/LMJBlogs/p/…]

js的arguments到底是什么? [blog.csdn.net/qq_16339527… ]