尾调用:指某个函数的最后一步是调用另一个函数;意义:调用记录只有一项,这将大大节省内存。这就是"尾调用优化"的意义。
尾调用之所以与其他调用不同,就在于它的特殊的调用位置。
(函数调用会在内存形成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息。
尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,
只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。)
尾递归:函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误。
“尾调用优化"对递归操作意义重大,所以一些函数式编程语言将其写入了语言规格。
ES6也是如此,第一次明确规定,所有 ECMAScript 的实现,都必须部署"尾调用优化”。这就是说,在 ES6 中,只要使用尾递归,就不会发生栈溢出,相对节省内存。