es6函数总结

做用域

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

例子二:
let x = 1;
function f(y = x) {
  let x = 2;
  console.log(y);  // 输出1
}
f()

例子三:报错
function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // ReferenceError: x is not defined

rest参数

  • rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中,这样就不须要使用arguments对象了; 见例子:
function add (...value) {
let sum = 0;
for (let i of value) {
sum += i;
}
return sum;
}
add(3, 5, 7);   // 15

箭头函数

  • () => {}; // 匿名函数
  • n => n + 1;
  • n => ({id: n}); 返回对象要用括号括起来,由于{}被解释为代码块;

注意点编程

  • 箭头函数没有this,准确来讲,箭头函数的this是其函数外的this
  • 不能够当构造函数
  • 不可以使用argument,可使用rest代替
  • 不可以使用yield命令,箭头函数不能做为Generator
  • arguments、super、new.target和this同样指向外层函数的对应变量

双冒号运算符

  • ::双冒号左边是一个对象,右边是一个函数
  • 该运算符会自动将左边的对象,做为上下文环境(即this对象),绑定到右边的函数上面

尾调用

见下面几个例子:数组

function factorial(n) {
  if (n === 1) return 1;
  return n * factorial(n - 1);
}
factorial(5)

复杂度为o(n) 太大会形成堆栈溢出app

function factorial(n, total) {
  if (n === 1) return total;
  return factorial(n - 1, n * total);
}
factorial(5, 1) //

复杂度为哦o(1)编程语言

尾递归函数的改写:函数式编程

  • 尾递归的实现,每每须要改写递归函数,确保最后一步只调用自身。作到这一点的方法,就是把全部用到的内部变量改写成函数的参数函数

  • 递归本质上是一种循环操做。纯粹的函数式编程语言没有循环操做命令,全部的循环都用递归实现,这就是为何尾递归对这些语言极其重要。 对于其余支持“尾调用优化”的语言(好比 Lua,ES6),只须要知道循环能够用递归代替,而一旦使用递归,就最好使用尾递归。优化

  • 解决方案: 一、蹦床函数的一个实现,它接受一个函数f做为参数。只要f执行后返回一个函数,就继续执行。 注意,这里是返回一个函数,而后执行该函数,而不是函数里面调用函数,这样就避免了递归执行,从而就消除了调用栈过大的问题。this

例子:rest

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

function sum(x, y) {
  if (y > 0) {
    return sum.bind(null, x + 1, y - 1);
  } else {
    return x;
  }
}

trampoline(sum(1, 100000))
// 100001

二、真的优化方案code

function tco(f) {
  var value;
  var active = false;
  var accumulated = [];

  return function accumulator() {
    accumulated.push(arguments);
    if (!active) {
      active = true;
      while (accumulated.length) {
        value = f.apply(this, accumulated.shift());
      }
      active = false;
      return value;
    }
  };
}

var sum = tco(function(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1)
  }
  else {
    return x
  }
});

sum(1, 100000)
  • 上面代码中,tco函数是尾递归优化的实现,它的奥妙就在于状态变量active。默认状况下, 这个变量是不激活的。一旦进入尾递归优化的过程,这个变量就激活了。而后,每一轮递归sum返回的都是undefined,因此就避免了递归执行;而accumulated数组存放每一轮sum执行的参数,老是有值的,这就保证了accumulator函数内部的while循环老是会执行。这样就很巧妙地将“递归”改为了“循环”,然后一轮的参数会取代前一轮的参数,保证了调用栈只有一层。
相关文章
相关标签/搜索