1. arguments对象概念
arguments 是一个对应于传递给函数的参数的类数组对象。
类数组对象的意思是,类似于数组Array,但除了length属性和索引元素之外不具有任何Array的属性,也就意味着在对函数arguments参数处理时,很多Array的方法并不能使用。
2. arguments对象属性 1.每个函数对象都有一个arguments属性,此属性只能在函数执行体内使用,其中保存着当前函数接收到的所有实际参数,故可以使用arguments属性处理可变数量的参数。
2. arguments对象具有如下属性:length:返回实际传入的参数的个数;callee:返回当前函数的引用(匿名函数可以使用该属性实现递归调用)
3. 由于arguments类数组对象的属性,们可以先将其转换为数组,再使用数组的方法来进行处理。 常见转换方式: Array.from()方法或扩展运算符将参数转换为真实数组:
var args = Array.from(arguments);
var args = [...arguments];
3.使用arguments对象
(1)arguments多用于函数参数不定时,通过arguments.length来确定传递给函数参数的个数,然后使用arguments对象来处理每个参数。
console.log(typeof arguments); // 'undefined'
// arguments 对象只能在函数内使用
function test(a){
console.log(a,Object.prototype.toString.call(arguments));
console.log(arguments[0],arguments[1]);
console.log(typeof arguments[0]);
}
test(1);
/*
1 "[object Arguments]"
1 undefined
number
*/
(2)arguments对象可以与剩余参数、默认参数和解构赋值参数结合使用,如下所示:
function foo(...args) {
return args;
}
foo(1, 2, 3); // [1,2,3]
(3)递归函数是在一个函数通过名字调用自身的情况下构成的。如下:
function factorial(num){
if(num <= 1){
return 1;
} else{
return num*factorial(num-1);
}
}
递归函数调用时如果修改 arguments.callee是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用,虽然使用arguments.callee代替函数名,可以确保无论怎样调用函数都不会出现问题,但是会出现重复计算,函数调用是有时间和空间的消耗的,会造成严重的延时问题,因此无论是递归还是arguments.callee在开发过程中都尽量不要使用。
4. 严格模式下arguments
(1)不管arguments是否有被使用,arguments对象总会被创建,除了作为局部变量声明和作为形式参数。arguments 的 getters 和 setters 方法总会被创建,使用 arguments 对性能不会有什么影响, 除非是需要对 arguments 对象的属性进行多次访问。但这些 getters 和 setters 在严格模式下都不会被创建,参考MDN。 (2)不支持arguments.callee
function count(a){
if(a==1){
return 1;
}
return a + arguments.callee(--a);
}
var mm = count(10);
console.log(mm);
arguments.callee指向当前执行的函数,会显著的影响现代 JavaScript 引擎的性能,每次调用自己,不仅抵消了内联函数带来的性能提升,而且破坏了封装。因为严格模式要求函数的参数名唯一,所以arguments.callee会报错TypeError,它已经被废除了。
(3) arguments不能通过程序语法被绑定或赋值,且严格模式下,参数的值不会随 arguments 对象的值的改变而变化,如下示例:
"use strict";
function f(a) {
a = 42;
return [a, arguments[0]];
}
const pair = f(17);
console.log(pair);
// 严格模式下:[42,17]
// 非严格模式下: [42,42]