欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES6新特性——函数的扩展

程序员文章站 2022-07-16 22:42:21
...
```handlebars
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
           1.函数参数的默认值
                 ES6允许为函数的参数设置默认值,即直接写在参数定义的后面
                 参数变量是默认声明的,不能用let和const再次声明
                 使用参数默认值时,函数不能有同名参数
                 参数默认值是惰性求值的
         */
         //eg:
         function log(x,y='world'){
             console.log(x,y);
         }
         log('hello');//hello world
         log('hello','china');//hello china
         log('hello','');//hello

         //eg:
         function Point(x=0,y=0){
             this.x=x;
             this.y=y;
             console.log(x,y)
         }
         const p=new Point();

         //参数变量是默认声明的,不能用let和const再次声明
         
         function foo(x=5){
           let x=1; //x' has already been declared
           const x=2; //x' has already been declared
             console.log(x);
         }
         foo();
         
         //参数默认值是惰性求值的,每次调用函数foo都会重新计算
         let x=99;
         function foo(p=x+1){
             console.log(p);
         };
         foo();

         //与解构赋值默认结合使用
         //参数默认值可以与解构赋值的默认值,结合起来使用
         function foo({x,y=5}){
            console.log(x,y);
        };
        foo({});//undefined 5
        foo({x:1});//1 5
        foo({x:1,y:2});//1 2
        foo();//property `x` of 'undefined' or 'null'

        //赋值给{}代表提供函数参数的默认值
        function foo({x,y=5}={}){
            console.log(x,y);
        };
        foo();

        //有{},原函数中没有赋值,就输出默认值,
        //没有{},原函数中没有赋值,则报错
        function fetch(url,{body='',method='GET',header={}}){
            console.log(method);
        }
        fetch('ht',{});//GET
        fetch('ht');//报错  undefined' or 'null'
        //双重默认值可以取消报错
        function fetch(url,{body='',method='GET',header={}}={}){
            console.log(method);
        }
            fetch('ht');
        

        //参数默认值的位置
        function f(x=1,y){
            console.log(x);
            console.log(y);
        }
        f(2);//2 undefined;
        f(); 


        function foo(x=5,y=6){
            console.log(x,y);
        };
        foo(undefined,null);//5 null

        //函数的length属性:返回没有指定默认值的参数的个数
        console.log(function (a) {}.length);//1
        console.log(function(a=5){}.length);//0
        console.log(function(a,b,c=1){}.length);//2
        console.log(function(...args){}.length);
        //如果设置了默认值的参数不是尾参数,那么length属性也不再计入后边的参数
        console.log(function(q=0,b,c,d){}.length);

        /* 
            作用域:
              一旦设置了参数的默认值,函数进行声明初始化时,
              参数会形成一个单独的作用域(context)。
              等到初始化结束,这个作用域就会消失
              这种语法行为,在不设置参数默认值时,是不会出现的
         */        
         var x=1;
        function f(x,y=x){
            console.log(y);
        }
        f(2);//2

        /* 
           函数f调用时,参数y=x形成一个单独的作用域
           这个作用域里面,变量x本身没有定义,
           所以指向外层的全局变量x.
           函数调用时,函数体内部的局部变量x影响不到默认值变量x
           如果此时,全局变量x不存在,就会报错
         */
        let x=1;
        function f(y=x){
            let x=2;
            console.log(y);
        }
        f();//1

        /* 
           rest参数
              ES6引入rest参数(形式为 ...参数名),用于获取函数的多于参数,
              这样就不需要使用arguments对象了
              rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
            注意:
              1.rest参数之后不能再有其他参数(即只能是最后一个参数),否则会报错
              2.函数的length属性,不包括rest参数
         */
         //eg:
         function add(...values){
            let sum=0
            for(var val of values){
                sum+=val;
            }
            return sum;
        }
            //add();
            let res=add(1,2,3);
            console.log(res);
            /* 
               arguments对象
                   arguments对象不是数组,而是一个类似数组的对象
                   如果要使用数组的方法,必须使用Arr.prototype.slice.call
                   先将其转为数组
             */
             //arguments变量的写法
        function sortNumbers(){
            return Array.prototype.slice.call(arguments).sort();
        }
        let an=sortNumbers();
        console.log(an);
        

        //函数的length属性,不包括rest参数
        console.log((function(a) {}).length);
        console.log((function(...a){}).length);
        console.log((function(a,b,e,...c){}).length);

        /* 
           严格模式:
              从ES5开始,函数内部可以设定严格模式
              ES2016做了一点修改,规定只要函数参数使用了默认值、解构赋值、
              或者扩展运算符,那么函数内部就不能显示设置为严格模式,否则会报错
         */

         /* 
            name属性 
              函数的name属性,返回该函数的函数名
        */
        function foo(){};
        console.log(foo.name);

        var f=function(){};
        console.log(f.name);
        //bind()方法:将函数绑定至某个对象
        //bind返回的函数,name属性值会加上bound前缀
        function foo(){};
        console.log(foo.bind({}).name);
        /* 
           箭头函数(=>)
        */
             //基本用法
             var f=v=>v;
             //等同于
            var f=function(v){
               return v;
            }

            //如果箭头函数不需要参数或多个参数,就使用一个圆括号代表参数部分
            var f=()=>5;
            //等同于
            var f=function(){return 5};

            var sum=(num1,num2)=>num1+num2;
            //等同于
            var sum=function(num1,num2){return num1+num2;};
            /* 
                由于大括号被解释为代码块,如果箭头函数直接返回一个对象,
                必须在对象外加上括号,否则会报错
             */
             let getTempItem=id=>({id:id,name:"Temp"});

             //箭头函数可以与变量解构结合使用
             const full=({first,last})=>first+''+last;
             //等同于
            function full(person){
                return person.first+''+person.last;
            }

            //箭头函数使表达更简洁
            const isEven=n=>n%2===0;
            const square=n=>n*n;

            //箭头函数的一个用处使简化回调函数
            //正常函数写法
            [1,2,3].map(function(x){
                return x*x;
            })
            //箭头函数写法
            [1,2,3].map(x=>x*x);
            
            //正常函数的写法
            var result=values.sort(function(a,b){
                return a-b;
            });
            //箭头函数的写法
            var result=values.sort((a,b)=>a-b);

            //rest参数与箭头函数结合
            const numbers=(...nums)=>nums;
            numbers(1,2,3,4,5);
            
            /* 
                使用箭头函数的注意点:
                  1.箭头函数体内的this指的是定义时所在的对象,
                  而不是使用时所在的对象,
                  在箭头函数里,this是固定的
                  2.不可以当作构造函数,也就是说,不可以使用new命令,
                  否则会抛出一个错误
                  3.不可以使用arguments对象,该对象在函数体内不存在。
                  如果要用,可以用rest参数替代
                  4.不可以使用yield命令,因此箭头函数不能作Generator函数
                  5.当函数体很复杂,有许多行,或者函数内部有大量的读写操作,
                  不单纯是为了计算值,也不应该使用箭头函数,而是要使用普通函数,
                  这样可以提高代码可读性
             */

             //嵌套的箭头函数
             function insert(value){
                return {into:function(array){
                    return{after:function(afterValue){
                        array.splice(array.indexOf(afterValue)+1,0,value);
                        return array;
                    }}
                 }}
               }
            var a=insert(2).into([1,3]).after(1);
            console.log(a);
            //等价于
            let insert=(value)=>({into:(array)=>({after:(afterValue)=>
                {array.splice(array.indexOf(afterValue)+1,0,value);
                    return array;
            }})})
            var a=insert(2).into([1,3]).after(1);
            console.log(a);
    </script>
</body>
</html>