[JS基础回顾] 函数那些事~~

223 阅读3分钟

目录

  1. 函数介绍
  2. 形参个数实参个数
  3. caller调用当前函数的引用
  4. callee函数本身 callee案例: 所有递归:(阶乘函数,斐波那契数列...)

零 函数介绍

1) 函数定义

专门用于封装代码,是一段可以随时被反复执行的代码块

2) 函数注意点

  1. 一个函数可以有形参也可以没有形参
  2. 一个函数可以有返回值也可以没有返回值
  3. return的作用和break相似,所以return后不能编写任何语句(执行不到). break作用:立即结束switch语句或者循环语句.return作用:立即结束当前所在函数

2) arguments 类数组 转 数组的4种方式

function fn(a,b){
    let args = [...arguments];
    let args1 = Array.from(arguments);
    let args2 = [].slice.call(arguments);
    let args3 = Array.prototype.slice.call(arguments);
    console.log(arguments, args, args1, args2, args3);
};

fn(1,2);

image.png

3) slice的实现 [] => []类数组 => []

call方法是将splice操作的对象指向argument

    Array.prototype.slice = function(start,end){

        var result = new Array();
        start = start || 0;
        end = end || this.length; 
        // this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象,这是关键
        for(var i = start; i < end; i++){
            result.push(this[i]);
        }
        return result;
    };
    
let a =[1,2,3,4]; let b = a.slice1();
console.log(b); // [1,2,3,4]

形参个数实参个数

  • 形参个数 : 函数名.length或者arguments.callee.length .
  • 实参个数 : arguments.length
function fn(a,b,c){
    console.log('形参的个数:',fn.length);
    console.log('形参的个数:',arguments.callee.length);
    console.log('arguments对象:', arguments);
    console.log('实参的个数:',arguments.length);
    
    // callee 返回一个正在被执行函数的引用  (这里常用来递归匿名函数本身 但是在严格模式下不可行)
    // callee 是arguments对象的一个成员 表示对函数对象本身的引用 它有个length属性(代表形参的长度)
    console.log('函数本身:',arguments.callee === fn); 
    console.log('函数的调用者:',fn.caller); //  caller 返回一个调用当前函数的引用 如果是由顶层调用的话 则返回null
    console.log('函数的名字:',fn.name);
}
fn(1,2,3);

//  形参的个数: 3
//  形参的个数: 3
//  arguments对象: Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//  实参的个数: 3
//  函数本身: false
//  函数的调用者: null
//  函数的名字: fn1

caller调用当前函数的引用

字面意思caller直接翻译为调用者,callee翻译为被召者

ECMAScript 5也规范化了另一个函数对象的属性caller。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null。

var callerTest = function() {
    console.log(callerTest.caller);  
} ;

function a() {
    callerTest() ;   
}
callerTest() ;//输出null
a(); // a() { callerTest(); } 

caller可以认为那个函数调用了它,它就指向谁

callee函数本身

callee函数本身, 使用场景 递归调用

arguments是一个类数组对象,它包含着所有传入函数中的参数。这个对象有一个名叫做callee的属性,该属性是一个指针指向拥有这个arguments对象的函数

1) 案例: 所有递归:(阶乘函数,斐波那契数列...)

当函数名被修改,递归调用就会出现问题.

function factorial(num){
    if(num === 1){
        return 1;
    }else{
        return num * factorial(num - 1);
    }
}
console.log(factorial(5));  //120
//递归调用时: 函数名被修改就会有问题
var fn1 = factorial;
console.log(fn1(5)); //120
factorial = function(){
    return 0
};
// 函数的执行结果 错误
console.log(fn1(5));//0
console.log(factorial(5));//0

所以, 使用 arugments.callee 可以解决函数名被修改的问题.

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

重写后的函数体中没有函数名,无论引用的函数使用任何名称时,都能保证递归的正常调用。

参考

总结

  • 形参个数 : 函数名.length或者arguments.callee.length .
  • 实参个数 : arguments.length
  • caller直接翻译为调用者callee翻译为被召者
  • callee函数本身, 使用场景 递归调用
  • caller 可以认为那个函数调用了它它就指向谁
  • 注意: calleecaller在严格模式下会有问题.
  • arguments来保存函数的实参.callee指向当前函数.caller指向调用当前函数的函数
  • 类数组 转数组4种方式