JS 函数 声明函数 函数三要素 箭头函数 回调函数

函数

  可以实现一定功能的一段代码的封装。

注:函数创建过后,在内存堆中以一段字符串文本储存,不执行时不会产生任何作用,就单单是存了一段字符串。

创建函数

  1、字面量(声明式,推荐)
 
      关键字  标识符  小括号  {函数体}
 
    例:
function F65(){
    console.log(`我是一个函数F65`);
 }

   

  2、表达式(匿名函数表达式)
 
      关键字  标识符 = function ()  {函数体}
    例:
let F66 = function () {
    console.log(`我是一个函数F66`);
}
let F66 = function F67() {
    console.log(`我是一个函数F66`);
}
F66();//我是一个函数F66
console.log(F66.name);//F67
console.log(F66);//[Function: F67]
//F67();//报错  F67 is not defined
//这个情况有点奇葩
 function F67() {
            console.log(`我是一个函数F67`);
        }
  F67();//我是一个函数F67
//意味着,前面并没有声明变量 F67,前面的F67只单单作为函数的一个name,但是调用时却必须使用F66作为函数名,有点扯
 

 

  3、构造函数
 
        关键字  标识符 = new Function ();
    例:
let F68= new Function(
    "console.log(123)"
);

注:内存栈  F68:函数的引用;

  内存堆  函数:"console.log(123)",就是个字符串。

 

函数三要素

  一、函数名

    函数名取名一般要求是动词或动宾格式,望文知意,其他的和变量标识符一样,并且也会和变量名冲突。

  

  二、参数

      形参:创建函数时,添加的参数
      实参:调用函数时,添加的参数
注:形参会有初始值:undefined。
 
     调用函数时,实参传给形参的过程相当于:
        let 形参 = 实参;
     有几个参数,就对应几个let。
 
     当形参与实参个数不同,在传统开发语言中,个数不同会报错,即不执行。JS不会:
  
          形参个数大于实参个数  多的形参,值为undefined
  
          实参个数大于形参个数  多的实参,不使用
 
  扩展:
      1、在最后添加一个扩展运算的变量(获取多的实参) 数组
       必须写在最后一个形参位置(尾形参,写在前面会报错),且只能有一个
  
      2、arguments获取所有实参的内容(类数组)
  
        类数组:
          1、可以用下标取值arguments[0]
          2、可以用length获取长度(个数)
          3、但不能数组的方法,例push()会报错
  
  注:函数名.length取的是形参个数(不包含扩展运算符的标识符)。
function F65(a,b,c,...d){

    console.log(a,b,c);//A B C
    console.log(d);//[ 'D', 'E', 'F', 'G', 'H' ]
    console.log(F65.length);//3
    console.log(F65.arguments);//键值对的实参
    console.log(F65.arguments[0]);//A
}
F65("A","B","C","D","E","F","G","H");

 

function f65(x,y,z,i){
     console.log(arguments[0]);//1
     x=2;
     console.log(arguments[0]);//2
     arguments[0]=5;
     console.log(x);//5
     //形参发生值的改变,相对应的arguments也会发生改变
     //arguments发生值的改变,相对应的形参不会发生改变
     console.log(i);//un
     i=2;
     console.log(i);//2
     console.log(arguments[3]);//un
     //当形参比实参多时,对多的形参进行赋值;
     //相对应的arguments不改变(即无效,也就是打印undefined)
 }
 f65(1,2,3);

注: 函数名.arguments 和直接 arguments 是不一样的,其实一般都是直接用 arguments。

 

  参数解构

function fn(a,b,{c,d}){
    //相当于
    let a=参数1;
    let b=参数2;
    let {c,d}=参数3;
}
//意味着参数3传的是一个对象
//默认值 {c,d=12}={}    {}是参数默认值,d=12是解构默认值

 

 

  三、返回值:return

    
    每个函数必须有return,如果没有添加return语句,计算机会自动在函数的最后一行补一个return,返回值为undefined。
    返回函数的结果(常量、变量、公式、表达式),同时终止函数,即不会执行return后面的代码。

 

 参数的默认值

  函数的形参在书写时可以直接赋值,(不赋值也会有:undefined),函数被调用时,如果形参有对应的实参,就用实参的值,没有就用默认值。

  给形参传值:undefined,函数也会使用该形参的默认值(不一定是undefined),

  .length获取形参个数时,有赋值默认值的形参不会计入个数,如果赋值默认值的形参写在第一个,长度会为0。

  因此,推荐把需要赋值默认值的形参写到最后。

 

 ES6 箭头函数

    

        x=> num2.has(x)    大多数时候就这个模板,函数返回表达式(num2.has(x))的结果
 

  一般有以下特点:

        1、可以省略 书写 function

        2、如果只有一个形参,可以不打小括号

        3、如果只有一条执行语句,可以不打大括号

        4、只有一条执行语句,并且需要返回这条语句的结果,可以不用写return

        5、不可以使用arguments

        6、不会把自己的this绑定到函数上

        7、不可以用作构造函数

  多数时候使用箭头函数只有一条语句,就是为了简洁方便:

let num1 = new Set([1, 2, 3, 4]);
let num2 = new Set([3, 4, 5, 6]);
// 并集
let union = new Set([...num1,...num2]);
console.log(union);//Set { 1, 2, 3, 4, 5, 6 }
//交集
let intersect = new Set(
    [...num1].filter(x=> num2.has(x)));
console.log(intersect); //Set { 3, 4 }
//差集
let difference = new Set(
    [...num1].filter(x => !num2.has(x)));
console.log(difference); //Set { 1, 2 }

 

回调函数

   把一个函数A,当参数传递给另一个函数B进行调用,函数A就是回调函数。

    把箭头函数当做回调函数用的最多。

  常用的回调函数

    

//数组的排序
let arr = [1, 3, 7, 6, 9, 4, 6, 2];
let arr1 = arr.sort(
    function (a,b){
        // return b-a;
        return a-b;
    }
)
console.log(arr1);

console.log(arr.sort((a, b) => a - b)); //升序
console.log(arr.sort((a, b) => b - a)); //降序

  回调函数用的非常多,相当重要。

arr.every(
    function(index){
        return index%2==0;
    }
)//以下为简写
// every  数组中每个值都满足条件才返回true
console.log(arr.every(index => index % 2 == 0)); //false
//some  数组中有一个条件满足则返回true
console.log(arr.some(index => index % 2 == 0)); //true
//filter(过滤) 返回所有满足条件的值
console.log(arr.filter(index => index % 2 == 0)); //[6,6,4,2]
//map  返回每个值是否满足条件
console.log(arr.map(index => index % 2 == 0)); //[ false, false, true, true, true, false, true, false ]

 

IIFE

  Immediately Invoked Function Expression

     立即执行函数,创建即调用,调用后即销毁

注:当立即执行函数中的变量在外面有调用时,变量会不销毁,但是会“隐形”,只有调用它的“人”看得到。

//一般书写方式
(function fn(){
    console.log("F65");
})()
//也可以
(function fn(){
    console.log("F65");
}())

!(function fn(){
    console.log("F65");
}())

-(function fn(){
    console.log("F65");
}())
//主要是为了让这一段代码与其他代码隔开,不会有歧义,形成一个整体

 

总结

  函数的表现形式:

    1、声明式

function fn(){}

    2、表达式

let fn = function(){}

    3、匿名函数

      不需要起名字的地方,function(){},并不能单独书写,在特定的地方出现,比如作为一个返回值、参数,或者立即执行函数

function fn(){
   return function(){};          
};
function fn(function(){}){};
(function(){})();

     立即执行函数、回调函数、箭头函数,都可以算作匿名函数的一种情况。

     4、特殊函数、递归函数

    其实就是函数直接或者间接的调用自己。递归一定要给出递归结束条件(递归出口)。

posted @ 2019-12-07 14:55  飞叶飞花  阅读(1845)  评论(0编辑  收藏  举报