zoukankan      html  css  js  c++  java
  • ES6学习笔记(6)----函数的扩展

    参考书《ECMAScript 6入门》
    http://es6.ruanyifeng.com/

    函数的扩展

    函数的默认值 : ES6可以为函数指定默认值

    (1)指定默认值的两种方式

      a.函数参数的默认值
      function test(a = 0,b = 5){
        return a+b;
      }
      test();//5 调用方法时,参数a,b都是undefined,可以使用默认值,因此返回5
      test(7);//7+5 = 12
      test(,10);//报错 非尾参数设置了默认值,则调用函数时此参数无法忽略,忽略报错;显示传入undefined,则触发默认值
     
      在参数中定义了默认值的变量,代码块中不能再用let或const重新定义变量(let与const不允许在同一个作用域内重复声明同一个变量)
      function test3(a = 1){
        let a = 7;
        return a;
      }
      test3()//执行此方法时报错(定义此方法test3时不报错)Uncaught SyntaxError: Identifier 'a' has already been declared
      function test4(b = 'sdf'){
        const b = 'test4';
        return b;
      }
      test4()//执行此方法时报错(定义此方法test4时不报错)Uncaught SyntaxError: Identifier 'b' has already been declared
      function test5(c = 8){
        var c = 1;
        return c;
      }
      test5()//1 不报错 let与const不允许在同一个作用域内重复声明同一个变量,而var可以,所以使用var重复声明c不报错
     
      使用参数的默认值时,不可以在声明同名参数
      function test6(a = 1, a, b){
        return a+b;
      }//函数定义时就报错 Uncaught SyntaxError: Duplicate parameter name not allowed in this context
     
      b.对象的解构赋值默认值
      function test2({a = 1,b = 8}){
        return a+b;
      }
      test2({});//9此时参数是一个空对象,空对象里的属性全是undefined, 所以函数可以使用参数的默认值
      test2({a:12,b:13});//25
      test2({a:15});//23
      test2();//此处使用的是对象的解构赋值默认值,如果传入的参数不是对象,就无法让对象的解构赋值默认值生效,报错 Cannot destructure property `a` of 'undefined' or 'null'.
      //要解决此问题,可以将其转化为进一步的参数默认值
      function test2({a = 2,b = 3} = {}){ //此处表示函数test2的默认参数是一个空对象,此空对象的属性a的默认值是2,属性b的默认值是3
        return a+b;
      }
      test2({});//5
      test2();//5
     
    (2)指定默认值后length属性将失真,已经制定默认值的参数以及位置在其后的参数都不参与length计数
      function test7(a,b,c,d){
        return a+b+c+d;
      }
      test7.length //4
      function test8(a,b = 0,c,d){
        return a+b+c+d;
      }
      test8.length //1 只计算了一个参数a,定义了默认值的参数b以及其后的c,d均不参与length计数
    (3)参数默认值是不传值的,如果参数默认值是一个表达式赋值,那每次都需要重新计算
    (4)一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
    (5)参数默认值用途:可用于提示某参数可省略(默认值设置成undefined)或者必须(默认值设置成可以返回异常提示语句的函数)

    2.rest参数:rest参数是一个数组,length属性不记录rest参数。
      function test11(...restParams){
        return restParams;
      }
      test11(1,3,4,5,'qwe'); // [1,3,4,5,'qwe']
      test11.length; //0

    3.函数的name属性返回实际的函数名
      let f = function test12(){};
      f.name; // 'test12'
      Array.bind({}).name; // "bound Array"
    4.箭头函数
    (1)箭头函数的this始终是函数定义时的this,不是使用时的this
       function Timer(){
        this.s1 = 0;
        this.s2 = 0;
        setInterval(()=>this.s1++,1000);//箭头函数中的this,指向Timer定义时的this,即this.s1 = 0;
        setInterval(function(){
        this.s2++;//常规写法函数中的this,通常指向使用时的window/document全局变量,因此this.s2是NaN,而timer.s2始终是定义时的值。
        },1000);
       }
       var timer = new Timer();
       setTimeout(()=>console.log(timer.s1),3100);//3
       setTimeout(()=>console.log(timer.s2),3100);//0

    (2)箭头函数可以简化函数写法
       function insert(value){
        return {into : function(arr){
          return {afterValue : function(val){
            arr.splice(arr.index(val)+1,0,value);
            return arr;}
          }}}
       }
       let insert = (value) => {into : (arr) => ({afterValue : (val) => {arr.splice(arr.indexOf(val)+1,0,value);return arr;}})}

    (3)如果箭头函数右边返回的是代码块,用{}括起来;如果箭头函数右边的是对象,则必须使用({})括起来。
       (a,b) => {return a+b}
       let test13 = (a,b) => ({name : a,value : b})
       test13("test",8); //{name : "test",value : 8}
    (4)箭头函数不能做构造函数,即不能使用new命令
       let test15 = (a,b) => a*b;
       new test15(); //报错 Uncaught TypeError: test15 is not a constructor

    5.双冒号运算符:左边是一个对象,右边是一个函数
      object1 :: f1 //等同于f1.bind(object1)
      object2 :: f2(...restArr) //等同于 f2.apply(object2,restArr);
      ::f3 //等同于f3.bind(f3)
      ::f3(...restArr1) //等同于f3.apply(f3,restArr1);  
      如果双冒号运算符的结果是一个对象,则可以链式使用

    6.尾调用和尾调用优化
      尾调用:函数的最后一步调用了另外一个函数
      function test17(){
        return test18();//必须是最后一步调用此函数,而且是作为返回值返回
      }
      尾调用优化:函数A最后一步调用了另外一个函数B,且函数B执行过程中不需要使用到任何有关函数A里变量的操作,那么在尾调用执行后,有关函数A的调用帧都可以删除,只保留函数B的调用帧,这即是尾调用优化
      function A(a){
        a = a + 1;
        function B(b){
          console.log(b);
        }
        return B('this is a test')
      }
    7.递归和尾递归
      递归:函数调用自身
      尾递归:函数尾调用自身
      常见递归:遍历dom树
      function traversal(node){
        //对node的处理
        if(node && node.nodeType === 1){
           console.log(node.tagName);
        }
        var i = 0, childNodes = node.childNodes,item;
        for(; i < childNodes.length ; i++){
            item = childNodes[i];
            if(item.nodeType === 1){
             //递归先序遍历子节点
             traversal(item);//属于尾递归
            }
        }
      }
      尾递归优化
     
      普通尾递归
      function sum(x){
        if(x === 1) {return 1};
        return x+sum(x - 1);//返回当前层次计算的x的值与下一子自身调用返回的值,因此当前的调用帧不能删除
      }
      优化后的尾递归
      function sum(x,y){
        if(x === 1) {return y};
        return sum(x - 1,x+y);//执行后当前调用帧可以删除,进入下一次自调用的新参数的调用帧
      }
      5,1-->4,5+1
      4,6-->3,5+1+4
      3,11-->2,5+1+4+3
      2,14-->1,5+1+4+3+2
      1,15--->15

    8.尾逗号规则:ES6允许函数定义时尾参数带逗号
    function test16(p1,p2,p3,){}

  • 相关阅读:
    概率论基础
    感知机
    CSS3实现jquery的特效
    有品质的生活
    table点击一行显示下一行的特效
    colspan在浏览器中失效的问题
    css的框架——common.css
    使用 document.onreadystatechange()来判断页面加载完
    iframe中子页面通过js计算高度(使得页面不会显示不全)
    js返回上一页并刷新的多种方法
  • 原文地址:https://www.cnblogs.com/carolddz/p/8568992.html
Copyright © 2011-2022 走看看