This article originally appeared on my website: “The Personal Culture of a Front End Siege Strategist”.
What is a tail call
The Tail Call is an important concept of functional programming. It refers to the last step of a function that calls a function and returns:
function f(x) {
return g(x)
}
Copy the code
Tail-call optimization
A function Call forms a Call record in memory called a Call Frame, which holds information such as the location of the Call and internal variables. The layers of Call frames eventually form the Call Stack.
Tail call is the last step of the operation of the external function. If the information of the calling position and internal variables of the external function is no longer needed in the internal function, then we do not need to retain the calling frame of the outer function and directly replace the calling frame of the inner function.
This is called Tail Call Optimization, where only the Call frames of the inner function are preserved. If all functions are tail calls, then it is perfectly possible to call only one frame per execution, which would save a lot of memory. This is what tail-call optimization is all about.
The conditional nature of tail-call optimization is to determine whether the information about the outer function is no longer necessary. Therefore, we can summarize the following conditions for tail-call optimization:
- The code executes in strict mode.
- The return value of an outer function is a call to an inner function.
- No additional logic needs to be performed after the tail-calling function returns.
- Tail-calling functions are not closures that reference free variables in the scope of the outer function and do not use internal variables of the outer function.
Tail recursion
Function calls themselves are called recursion, and tail calls themselves are called tail recursion.
Recursion is very memory intensive, because you need to hold hundreds or thousands of call frames at the same time, and it is easy to make stack overflow errors (although it is sometimes possible to artificially expand the stack, this is not always a good solution). For tail recursion, however, stack overflow errors never occur because there is only one call frame.
Tail-call optimization is significant for recursive operations and has been written into the language specification in ES6. ES6 explicitly states that tail-call optimization must be deployed for all ECMAScript implementations. That is, as long as tail recursion is used in ES6, no stack overflow occurs, which is relatively memory saving.
Strict mode
Since there are two variables inside a function (see below) that track the function’s call frame in normal mode, tail-call optimization in ES6 is only enabled in strict mode and not in normal mode.
- Func.arguments returns the arguments to the function at the time of the call.
- Caller returns the function that calls the current function.
When tail-call optimization is performed, the call stack of the function is overwritten, so the above two variables are distorted. Disable these two variables in strict mode, and all tail-call modes are only valid in strict mode.