简单了解一下JavaScript的argument

  函数调用的时候,浏览器每次都会传递进两个隐式参数:一个是函数的上下文对象this,另一个则是封装实参的类数组对象arguments

  arguments被定义为对象,但对象的属性是无序的,而arguments是用来存储实参的,是有顺序的,它具备和数组相同的访问性质及方式,并拥有数组长度属性length,所以arguments是特殊的对象,又叫类数组对象。可以arguments[i]来访问对象中的元素,但它不能用数组的一些方法,例如push,pop,slice等。

1、Arguments的length属性

function argTest(a,b,c){
    var d = arguments.length; //实际传参个数
    var e = argTest.length;   //期望传参个数

    console.log(d);
    console.log(e);
}

argTest(1,2);       //t=2,e=3
argTest(1,2,3);    //t=3,e=3
argTest(1,2,3,4); //t=4,e=3

结论:ECMAScript不会验证传递给函数的参数个数是否等于函数定义的参数个数。

2、Arguments的参数访问

arguments访问单个参数的方式与访问数组元素的方式相同,可以用arguments[i]来访问函数所传的参数。通过length属性可以知道实参的个数。

function fn() {
    console.log(arguments[0]); // name
    console.log(arguments[1]); // age
    console.log(arguments.length); // 2
}
fn('name', 'age');

 

3、Arguments的callee调用

Arguments的callee属性用来调用函数本身,当函数正在执行时才可调用,可以用来实现方法的递归调用。

function argTest(a,b,c){
    var e = arguments.callee.toString();
    console.log(e);
}

argTest(); //打印出函数本身

function fn() {
  console.log(arguments.callee === f3); // true
}
fn('name', 'age')

 

4、Function对象caller属性

  Function对象的caller属性可以指向当前函数的调用者,当调用者函数正在执行时才可调用

function callerTest(){

    if(callerTest.caller){
        var caller = callerTest.caller.toString();
        console.log(caller);
    }else{
        console.log("no caller")
    }
}

function handler(){
    callerTest();
}

function handlerToHandler(){
    handler();
}

callerTest();        //no caller
handler();           //返回调用者handler函数
handlerToHandler();  //返回调用者handler函数

/ *
no caller
function handler(){
    callerTest();
}
function handler(){
    callerTest();
}
*/

 

5、arguments的修改

arguments对象是允许在函数运行时进行修改的

function fn() {
    arguments[0] = 'sex';
    console.log(arguments[0]); // sex
}
fn('name', 'age');

 

6、arguments转化成真实数组

arguments是类数组对象,除了length属性和索引元素之外没有任何Array属性。例如,它没有 pop方法。但是它可以被转换为一个真正的Array:

function fn(){
    // 可以使用slice来将arguments转换为真实数组
    var args1 = Array.prototype.slice.call(arguments);
    var args2 = [].slice.call(arguments);
    // 也可以使用Array.from()方法或者扩展运算符来将arguments转换为真实数组
    var args3 = Array.from(arguments);
    var args4 = [...arguments];
}
fn('name', 'age');

 

7、Arguments的应用

a:验证实参和形参个数是否相等

function fn (a, b, c) {
    if (fn.length != arguments.length) {
        console.log('形参和实参的个数不一致');
    } else{
        console.log('形参和实参的个数一致');
    }
}
fn(1, 2);

b:callee来让匿名函数实现递归(注意是匿名函数)

function sum(n) {
    if (n == 1) {
        return 1;
    } else {
        return n + arguments.callee(n - 1); // 5 4 3 2 1
    }
}
console.log(sum(6)); // 21


function factorial(n){
  if(n == 1){
    return 1;
  }else{
    n * arguments.callee(n-1);
  }
}
factorial(5); // 120

 

c: 遍历参数求和或者求最大值

function max () {
    var max = arguments[0];
    for (item of arguments) {
        if (item > max) {
            max = item;
        }
    }
    return max;
}
console.log(max(6, 3, 5, 9, 2)); // 9

d:方法模拟重栽

  方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。 Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。

// 未重载
function add(num1, num2) {
    console.log(1);
}

function add(num1, num2, num3) {
    console.log(2);
}
add(1, 2); //2
add(1, 2, 3);//2

// 重载
function add(num1, num2, num3) {
    if (arguments.length === 2) {
        console.log("Result is " + (num1 + num2));
    }
    else if (arguments.length === 3) {
        console.log("Result is " + (num1 + num2 + num3));
    }
}

add(1, 2); // 3
add(1, 2, 3) // 6

 

posted @ 2022-03-18 19:11  夏目友人喵  阅读(278)  评论(0编辑  收藏  举报