es6函数的扩展

函数参数的默认值

  • es6允许为函数的参数设置默认值,用法如下

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

    参数变量不能再次声明。另外,使用参数默认值的时候,不能有同名参数,但是不用默认值可以有同名参数

    参数默认值不是传值的,而是每次都重新计算默认值表达式的值。参数默认值是惰性求值的。

    let x = 99;
    function foo(p = x + 1) {
      console.log(p);
    }
    foo() // 100
    x = 100;
    foo() // 101
    
  • 可以在参数中使用解构赋值

    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
    

    这个例子没有给参数提供默认值,也可以为参数提供默认值

  • 一般情况下,定义的默认参数应该是尾参数,因为如果不是尾参数,这个参数无法省略,否则需要输入undefined如下:

    function f(x = 1, y) {
      return [x, y];
    }
    
    f() // [1, undefined]
    f(2) // [2, undefined])
    f(, 1) // 报错
    f(undefined, 1) // [1, 1]
    
  • 指定了默认值参数之后,函数的length属性应该返回的是没有指定默认值的参数个数

    但是如果指定的默认值不是尾参数,那么length属性不再计算后面的参数

  • 设置了参数的默认值,参数会形成一个单独的作用域

    如果在使用参数赋值之前,用var声明了一个变量,会出现暂时性死区,如下:

    var x = 1;
    
    function foo(x = x) { //相当于let  x = x
    
      // ...
    }
    
    foo() // ReferenceError: x is not defined
    

    如果参数是一个函数,那么这个函数的作用域也应该遵守规则

    var x = 1;
    function foo(x, y = function() { x = 2; }) {
      var x = 3;
      y();
      console.log(x);
    }
    
    foo() // 3
    x // 1
    

rest参数

rest参数的形式为...变量名,用于获取函数的多余参数,可以这样使用

function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

**注意:**rest参数只能作为最后一个参数,且函数的length属性不包括rest参数

严格模式

函数内部不能使用严格模式的情况:参数使用了默认值、解构赋值、扩展运算符

避免以上问题的方法:

  1. 设定全局性的严格模式

    'use strict';
    
    function doSomething(a, b = a) {
      // code
    }
    
  2. 把函数包含在一个无参数的立即执行的函数里面

    const doSomething = (function () {
      'use strict';
      return function(value = 42) {
        return value;
      };
    }());
    

name属性

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

将函数赋值给变量的两种情况:

  1. 将匿名函数赋值给一个变量,返回实际的函数名,即变量名

  2. 将具名函数赋值给一个变量:返回具名函数名

Function构造函数返回的函数实例,name属性的值为anonymous

(new Function).name // "anonymous"

bind返回的函数,name属性值会加上bound前缀。

function foo() {};
foo.bind({}).name // "bound foo"

(function(){}).bind({}).name // "bound "

箭头函数

  • 形式:
var f = v => v;

// 等同于
var f = function (v) {
  return v;
};
  • 参数:如果箭头函数不需要或者需要多个参数,可以用圆括号吧参数括起来

  • **注意:**如果要直接返回一个对象,那么必须在对象外面加上一个括号

  • 与变量结构结合:

    const full = ({ first, last }) => first + ' ' + last;
    
    // 等同于
    function full(person) {
      return person.first + ' ' + person.last;
    }
    
  • 使用注意:

    1. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    2. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

    3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

    4. 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

  • 箭头函数还有一个功能,就是可以很方便地改写 λ 演算。

    // λ演算的写法
    fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))
    
    // ES6的写法
    var fix = f => (x => f(v => x(x)(v)))
                   (x => f(v => x(x)(v)));
    

尾调用优化

  • 尾调用就是某个函数的最后一步是调用另外一个函数,即在函数的最后一步操作

  • 优化:到了尾调用的时候,只保留内层函数的调用帧,而不保留外层函数的调用帧,因为内部变量等信息都不会用到了

    只有当不再用到外层函数的内部变量时,内层函数的调用帧才会取代外层函数的调用帧,否则无法优化

  • 尾递归:尾调用自身就是尾递归

    好处:只存在一个调用栈,所以永远不会发生“栈溢出”错误

  • 严格模式:尾调用优化只在严格模式下开启

  • 在正常模式下实现尾调用优化:蹦床函数可以将递归执行转为循环执行

    function trampoline(f) {
      while (f && f instanceof Function) {
        f = f();
      }
      return f;
    }
    

函数参数的尾逗号

函数的最后一个参数允许有尾逗号

Function.prototype.toString()

函数实例的toString()方法返回函数代码本身,包括注释和空格

catch 命令的参数省略

try...catch结构中,catch代码块可能用不到这个参数,可以把这个参数是省略

参考文献

ECMAScript 6 入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值