A function is an object that can be called. JavaScript has several syntactic forms of
function, which differ in how this is set, whether they can be used with
new, and how they return (ECMA-262, ECMAScript Language: Functions and
Classes).
Forms of function
| Form | Example | new | Own this | prototype | Since |
|---|---|---|---|---|---|
| Function declaration | function f() {} | Yes | Yes | Yes | ES1 |
| Function expression | const f = function () {}; | Yes | Yes | Yes | ES3 |
| Arrow function | (a) => a + 1 | No | No | No | ES2015 |
| Method | { m() {} } | No | Yes | No | ES2015 |
| Getter, setter | { get x() {} } | No | Yes | No | ES5 |
| Generator | function* g() {} | No | Yes | Yes | ES2015 |
| Async function | async function f() {} | No | Yes | No | ES2017 |
| Async arrow | async (a) => a | No | No | No | ES2017 |
| Async generator | async function* g() {} | No | Yes | Yes | ES2018 |
| Class | class C {} | Only with new | Yes | Yes | ES2015 |
Function constructor | new Function('a', 'return a') | Yes | Yes | Yes | ES1 |
FunctionDeclaration:
function BindingIdentifier ( FormalParameters ) { FunctionBody }
FunctionExpression:
function [BindingIdentifier] ( FormalParameters ) { FunctionBody }
ArrowFunction:
ArrowParameters [no LineTerminator here] => ConciseBody
ArrowParameters:
BindingIdentifier
( ArrowFormalParameters )
ConciseBody:
[lookahead ≠ {] ExpressionBody
{ FunctionBody }
const a = (x) => x + 1; // expression body, returned
const b = (x) => { return x + 1; }; // block body
const c = () => ({ value: 1 }); // parentheses to return an object
const d = x => x * 2; // parentheses optional for one simple parameter
- A named function expression’s name is bound only inside the function. The binding is read-only.
- A function declaration inside a block follows block rules.
- The
Functionconstructor always creates a global-scope function. It does not capture the caller’s scope. - For a function written in source code,
Function.prototype.toStringreturns its exact source text, including comments (ES2019). Built-in functions give a standard placeholder.
The this binding
this is set each time an ordinary function is called, depending on how
it is called. It is not fixed when the function is defined.
| Call | this in the function |
|---|---|
f() | undefined in strict code; the global object in sloppy code |
o.f(), o[k]() | o |
o?.f() | o |
new F() | The new object |
f.call(x, a), f.apply(x, [a]) | x |
A bind result | The bound value; cannot be changed |
| An arrow function | Whatever this was where the arrow was created |
tag`text` | As for a call; o.tag`text` has this as o |
const o = {
name: 'o',
regular() { return this.name; },
arrow: () => typeof this,
};
o.regular(); // "o"
const f = o.regular;
f(); // TypeError in strict code: this is undefined
setTimeout(function () { this; }); // whatever the host passes
setTimeout(() => { this; }); // the enclosing this
this; arrows capture itIn sloppy code, a this that is null or
undefined becomes the global object, and a primitive is wrapped in an
object. In strict code it stays exactly as given. See
Strict mode.
At the top level, this is the global object in a script,
undefined in a module, and module.exports in a CommonJS
module. In a class field or static block, it is the instance or the class: see
Classes.
call, apply and bind
| Method | Effect |
|---|---|
f.call(t, a, b) | Calls with this as t and the listed arguments |
f.apply(t, list) | Calls with an array-like list of arguments |
f.bind(t, a) | Returns a new function with this and leading arguments fixed |
A bound function is an exotic object (Bound Function Exotic Objects). Its
name is "bound f", and new on it calls
the target, ignoring the bound this. It has no
prototype property.
Parameters
FormalParameters:
[empty]
FunctionRestParameter
FormalParameterList
FormalParameterList ,
FormalParameterList , FunctionRestParameter
FormalParameter:
BindingElement
BindingElement:
SingleNameBinding
BindingPattern [Initializer]
SingleNameBinding:
BindingIdentifier [Initializer]
FunctionRestParameter:
BindingRestElement
function f(a, b = a * 2, { c, d = 1 } = {}, ...rest) {
return [a, b, c, d, rest];
}
f(1); // [1, 2, undefined, 1, []]
f(1, undefined, { c: 3 }, 4, 5); // [1, 2, 3, 1, [4, 5]]
- Missing arguments are
undefined. Extra ones are ignored, apart fromargumentsand rest. - A default value (ES2015) is used when the argument is
undefined. It is evaluated at each call, left to right, and may refer to earlier parameters. - Parameters that have expressions get their own scope, separate from the body’s
vardeclarations. - A rest parameter collects the remaining arguments in an array. There may be one, and it must be last, with no default.
- Parameters are simple if none uses a default, rest or
destructuring. Non-simple parameters forbid a
"use strict"directive in the body, and forbid duplicates. - Duplicate parameter names are allowed only in sloppy functions with simple parameters.
- A trailing comma is allowed after the last parameter or argument (ES2017), but not after a rest parameter.
length and name
Every function has length and name properties, both
configurable and not writable. length is the number of parameters before
the first one with a default or rest, so
function (a, b = 1, c) {} has a length of 1. name is the
declared name, or the name inferred from the assignment target.
The arguments object
Every non-arrow function has a local binding arguments, an array-like
object of the actual arguments. It is iterable, with length, and is
not an array. An arrow function has no arguments of its own, and sees the
enclosing function’s.
| Function | Arguments object | callee | Tied to named parameters |
|---|---|---|---|
| Sloppy, simple parameters | Mapped | The function | Yes: writing one changes the other |
| Strict, or non-simple parameters | Unmapped | Throws a TypeError | No |
The mapped form is an exotic object (Arguments Exotic Objects). Prefer rest parameters, which give a real array.
new and new.target
new F(args) calls the function’s [[Construct]] internal
method. For an ordinary function, it creates an object whose prototype is
F.prototype, runs the function with that as this, and returns
the object, or the function’s return value if that is an object.
new.target is the constructor that new was applied to, or
undefined in a normal call. Arrow functions see the surrounding
value.
function Point(x) {
if (!new.target) return new Point(x);
this.x = x;
}
Point(1) instanceof Point; // true
Generators and async functions
A generator pauses at yield and returns a generator object, and an async
function returns a promise, pausing at await. They are covered in
Iterators and
generators and Async.
Tail calls
ES2015 specifies that a call in tail position in strict code must reuse the current frame (Tail Position Calls). Few engines have implemented this, so programs cannot rely on it to keep the stack shallow.