美文网首页Vue.js
ES6第四课、函数扩展

ES6第四课、函数扩展

作者: 前端一菜鸟 | 来源:发表于2019-04-01 10:35 被阅读17次

    5.1、函数参数的默认值

    5.1.1、基本用法

    ES6 之前,不能直接为函数的参数指定默认值

    function log(x, y) {
      y = y || 'World';
      console.log(x, y);
    }
    log('Hello') // Hello World
    log('Hello', 'China') // Hello China
    log('Hello', '') // Hello World
    

    这种写法的缺点在于,如果参数y赋值了,但是对应的布尔值为false,则该赋值不起作用。
    参数y等于空字符,结果被改为默认值
    为了避免这个问题,通常需要先判断一下参数y是否被赋值,如果没有,再等于默认值。

    if (typeof y === 'undefined') {
      y = 'World';
    }
    

    ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面

    function log(x, y = 'World') {
      console.log(x, y);
    }
    
    log('Hello') // Hello World
    log('Hello', 'China') // Hello China
    log('Hello', '') // Hello
    

    另外一个

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

    注意:参数变量是默认声明的,所以不能用let或const再次声明

    function foo(x = 5) {
      let x = 1; // error
      const x = 2; // error
    }
    

    5.1.2、与解构赋值默认值结合使用

    参数默认值可以与解构赋值的默认值,结合起来使用。

    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() // TypeError: Cannot read property 'x' of undefined
    

    如果函数foo调用时没提供参数,变量x和y就不会生成,从而报错。通过提供函数参数的默认值,就可以避免这种情况。

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

    上面代码指定,如果没有提供参数,函数foo的参数默认为一个空对象。
    两种写法区别

    // 写法一
    function m1({x = 0, y = 0} = {}) {
      return [x, y];
    }
    
    // 写法二
    function m2({x, y} = { x: 0, y: 0 }) {
      return [x, y];
    }
    

    上面两种写法都对函数的参数设定了默认值,区别是写法一函数参数的默认值是空对象,但是设置了对象解构赋值的默认值;写法二函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值。

    // 函数没有参数的情况
    m1() // [0, 0]
    m2() // [0, 0]
    
    // x 和 y 都有值的情况
    m1({x: 3, y: 8}) // [3, 8]
    m2({x: 3, y: 8}) // [3, 8]
    
    // x 有值,y 无值的情况
    m1({x: 3}) // [3, 0]
    m2({x: 3}) // [3, undefined]
    
    // x 和 y 都无值的情况
    m1({}) // [0, 0];
    m2({}) // [undefined, undefined]
    
    m1({z: 3}) // [0, 0]
    m2({z: 3}) // [undefined, undefined]
    

    5.1.3、参数默认值的位置

    如果传入undefined,将触发该参数等于默认值,null则没有这个效果。

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

    5.2、rest 参数

    ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
    注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

    function add(...values) {
      let sum = 0;
    
      for (var val of values) {
        sum += val;
      }
    
      return sum;
    }
    
    add(2, 5, 3) // 10
    

    arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。

    // arguments变量的写法
    function sortNumbers() {
      return Array.prototype.slice.call(arguments).sort();
    }
    
    // rest参数的写法
    const sortNumbers = (...numbers) => numbers.sort(); 
    

    5.3、严格模式

    从 ES5 开始,函数内部可以设定为严格模式。

    function doSomething(a, b) {
      'use strict';
      // code
    }
    

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

    // 报错
    function doSomething(a, b = a) {
      'use strict';
      // code
    }
    
    // 报错
    const doSomething = function ({a, b}) {
      'use strict';
      // code
    };
    
    // 报错
    const doSomething = (...a) => {
      'use strict';
      // code
    };
    

    设定全局性的严格模式,这是合法的

    'use strict';
    function doSomething(a, b = a) {
      // code
    }
    

    5.4、name 属性

    函数的name属性,返回该函数的函数名。

    function foo() {}
    foo.name // "foo"
    

    如果将一个匿名函数赋值给一个变量,ES5 的name属性,会返回空字符串,而 ES6 的name属性会返回实际的函数名。

    var f = function () {};
    // ES5
    f.name // ""
    // ES6
    f.name // "f"
    

    如果将一个具名函数赋值给一个变量,则 ES5 和 ES6 的name属性都返回这个具名函数原本的名字

    const bar = function baz() {};
    // ES5
    bar.name // "baz"
    // ES6
    bar.name // "baz"
    

    5.5、箭头函数

    5.5.1、基本用法

    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" };
    
    // 不报错
    let getTempItem = id => ({ id: id, name: "Temp" });
    

    箭头函数的一个用处是简化回调函数。

    // 正常函数写法
    [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);
    

    5.5.2、使用注意点

    -(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
    -(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
    -(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
    -(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数

    function foo() {
      setTimeout(() => {
        console.log('id:', this.id);
      }, 100);
    }
    var id = 21;
    foo.call({ id: 42 });
    // id: 42
    

    相关文章

      网友评论

        本文标题:ES6第四课、函数扩展

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