美文网首页
ES6 函数的扩展

ES6 函数的扩展

作者: 前白 | 来源:发表于2020-12-16 16:14 被阅读0次

    函数的扩展我们可以从三个方面来了解与认识:

    • 参数的默认值
    • 箭头函数
    • 关于尾调用的优化

    参数的默认值

    ES6 之前,我们不能直接为函数的参数指定默认值,只能采用变通的方法。而 ES6 中允许我们直接为函数的参数设置默认值,通过等号 = 直接在小括号中给参数赋值。

    示例:
    function log(name, age = 18) {
        console.log(name, age);
    }
    console.log('xkd');         // 输出: xkd
    console.log('summer', 20);  // 输出: summer 20
    console.log('mark', '');    // 输出: mark
    

    如果函数带有某一个参数,则表示这个参数变量已经默认声明,我们不可以使用 let 或者 const 再次声明这个变量。

    function xkd(a = 1) {
        let a = 2;
    }
    
    // 报错:SyntaxError: Identifier 'a' has already been declared
    

    还需要注意的是,在使用函数默认参数时,不允许有同名参数:

    function week(a, a, b = 100) {
        /* ... */
    }
    // 报错信息: SyntaxError: Duplicate parameter name not allowed in this context
    

    参数默认值是惰性求值:

    let a = 100;
    function xkd(sum = a + 1) {
        console.log(sum);
    }
    xkd(); // 输出:101
    

    rest不定参数

    ES6 引入 rest 参数,不定参数用来表示不确定参数个数,由 ... 加上一个具名参数标识符组成。

    示例:
    function add(...values) {
        let sum = 0;
        for (var val of values) {
            sum += val;
        }
        return sum;
    }
    console.log(add(10, 5, 7));  // 输出:22
    

    上面代码的 add 函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。

    注意 rest 参数只能放在参数组的最后,并且有且只有一个不定参数,这个参数后面不能再有其他参数,否则会报错。

    function func(a, ...b, c) {
        // ...
    }
    // 报错:SyntaxError: Rest parameter must be last formal parameter
    

    如果我们要使用函数的 length 属性来获取参数的个数,是不包括 rest 参数的。

    function func1(a, b){
        //...
    }
    function func2(a, b, ...c){
        //...
    }
    console.log(func1.length);  // 输出: 2
    console.log(func2.length);  // 输出: 2
    

    name属性

    函数的 name 属性,可以用于返回该函数的函数名。

    示例:
    function xkd() {
        console.log(xkd.name);  // 输出:xkd
    }
    xkd();
    

    也可以写成:

    var xkd = function() {}
    console.log(xkd.name); // 输出:xkd
    

    箭头函数

    ES6 中允许使用箭头 => 来定义函数,这样定义的函数叫做箭头函数。箭头函数主要的两点是:它的 this 指向是在它当时定义所在的区域,还一个是它没有一个作用域的提升。

    示例:
    var x = function (y) {
        return y;
    }
    

    上述函数使用箭头函数来写,可以写成:

    var x = y => y;
    

    如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

    示例:

    例如下面这个求两数之和的函数:

    var sum = function(num1, num2) {
        return num1 + num2;
    }
    

    等同于如下所示箭头函数的写法:

    var sum = (num1, num2) => num1 + num2;
    

    如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

    示例:
    var sum = (num1, num2) => { return num1 + num2; }
    

    由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

    示例:
    let obj = age => ({ name: "xkd", age:age });
    

    箭头函数可以与变量解构结合使用。

    示例:
    const full = ({ first, last }) => first + ' ' + last;
    
    // 等同于
    function full(person) {
      return person.first + ' ' + person.last;
    }
    

    箭头函数使用时需要注意的一下几个问题:

    • 函数体内的 this 对象指向的是定义时所在的对象,而不是使用时所在的对象。
    • 不可以当作构造函数,也就是说不可以使用 new 命令。
    • 不可以使用 arguments 对象,可以使用 rest 参数替代。
    • 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

    关于尾调用的优化

    尾调用就是指某个函数的最后一步是调用另一个函数,不适用于外部变量时只保留内层函数的调用帧。

    示例:

    例如下面这个 func() 函数中的最后一步是调用函数 show(),这就叫尾调用:

    function func(x) {
        return show(x);
    }
    

    如果在调用一个函数之后,还有其他的操作,则不属于尾调用。

    注意,尾调用不一定出现在函数尾部,只要是最后一步操作即可,例如下面这段代码中:

    function func(x) {
        if (x > 0) {
          return f1(x)
        }
        return f2(x);
    }
    

    函数 f1f2 都属于尾调用,因为这两个函数调用都是函数 func 的最后一步操作。

    ES5 中,尾调用的实现是创建一个新的栈帧 stack frame, 将其推入调用栈中表示函数调用。所以每一个未用完的栈帧都会保存在内存中,当调用栈变得过大时会造成程序问题,也就是我们常说的栈溢出。

    ES6 严格模式下,满足以下三个条件,尾调用不再创建新的 stack frame ,而是重用当前 stack frame

    • 函数不是一个闭包。
    • 在函数内部,尾调用是最后一条语句。
    • 尾调用的结果作为函数值返回。
    示例:
    'use strict';
    function func(){
        //优化后
        return f();
    }
    

    而以下几种情况不会进行优化:

    • 当没有作为函数值返回,不会优化:
    function func(){
        f(); 
    }
    
    • 返回值后还需要做其他操作,也不会优化:
    function func(){
      return 1+f(); //返回值后还需要做其他操作
    };
    
    • 函数调用不在尾部,也不会优化:
    function func(){
      const result = f(); 
      return result;
    };
    
    • 调用的函数是一个闭包函数,也不会优化:
    function func(){
      const a= 1;
      const f = () => a //这是一个闭包函数,函数 f 需要访问局部变量a
      return f();
    };
    

    更多链接:https://www.9xkd.com/

    相关文章

      网友评论

          本文标题:ES6 函数的扩展

          本文链接:https://www.haomeiwen.com/subject/qwxogktx.html