A function is an invocable code branch that is capable of receiving a list of arguments, performs work, delegates to other branches within the software, and then returns control to the invoking context. Many functions have a name bound to them, allowing other contexts to reference them.
While languages will differ in syntax---and occasionally semantics---with respect to defining functions, TypeScript has four common ways to syntactically generate them. These break down into a combination of two separate concerns: boundedness versus anonymity, and keywords versus symbolics.
Name bindings for a function provide a way for other entities within the code base to refer to the function and optionally invoke it. Anonymous functions, therefore, are unbound: they lack a name by which it may be referenced. As will be seen in a later part discussing higher order functions, a binding is contextually bound to a scope, so a function which is anonymous in one context might be bound in another.
In JavaScript, the traditional keyword for defining a function is, appropriately enough, function
. The syntax opens with the keyword, is followed by an optional name binding, a parameter list, and then the function body. The body is typically defined with braces and must use the explicit return
keyword to provide a result. TypeScript augments this behavior with type notations, which will be discussed in the next part.
Arrow functions provide a degree of syntactic sugar that can simplify the definition of a function. The syntax starts with a parentheses-wrapped parameter list, proceeds with a fat arrow (=>
), and then culminates with the body. Arrow functions are, by design, unbound and anonymous, but can be assigned directly to a variable. Their bodies can be as in the traditional formation, or they can be unbraced, in which case the final statement within the body is automatically assigned as the return value.
Both syntaxes allow for immediate execution of the function, though this is usually only of direct use for unbound anonymous functions. For the keyword syntax, it is sufficient to directly invoke the function after the body with a parentheses-wrapped argument list. For the arrow syntax, it is first necessary to wrap the entire function definition in parentheses, and then provide the argument list.
Unless absolutely required for some semantic mechanic (e.g. binding this
), this series will typically default to using modern arrow notation, even for non-callbacks. This is done to accentuate the fact that TypeScript considers functions to be first-class citizens that behave---ish---like most other objects. This will be discussed further in higher order functions.