Functions API Flashcards
Function()
constructor
The Function()
constructor creates Function objects. Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues as eval()
. However, unlike eval
(which may have access to the local scope), the Function
constructor creates functions which execute in the global scope only.
Syntax
new Function(functionBody) new Function(arg1, functionBody) new Function(arg1, arg2, functionBody) new Function(arg1, arg2, /* …, */ argN, functionBody) Function(functionBody) Function(arg1, functionBody) Function(arg1, arg2, functionBody) Function(arg1, arg2, /* …, */ argN, functionBody)
Note: Function()
can be called with or without new
. Both create a new Function
instance.
Parameters
-
arg1, …, argN
Optional - Names to be used by the function as formal argument names. Each must be a string that corresponds to a valid JavaScript parameter (any of plain identifier, rest parameter, or destructured parameter, optionally with a default), or a list of such strings separated with commas.
As the parameters are parsed in the same way as function expressions, whitespace and comments are accepted. For example: "x"
, "theValue = 42"
, "[a, b] /* numbers */"
— or "x, theValue = 42, [a, b] /* numbers */"
. ("x, theValue = 42", "[a, b]"
is also correct, though very confusing to read.)
-
functionBody
- A string containing the JavaScript statements comprising the function definition.
Examples:
// Example can be run directly in your JavaScript console // Create a function that takes two arguments, and returns the sum of those arguments const adder = new Function("a", "b", "return a + b"); // Call the function adder(2, 6); // 8
“Function()
constructor - JavaScript | MDN” (MDN Web Docs). Retrieved April 9, 2024.
Function.prototype.arguments
Deprecated: This feature is no longer recommended.
The arguments accessor property of Function
instances returns the arguments passed to this function. For strict, arrow, async, and generator functions, accessing the arguments property throws a TypeError
.
The value of arguments is an array-like object corresponding to the arguments passed to a function.
In the case of recursion, i.e. if function f
appears several times on the call stack, the value of f.arguments
represents the arguments corresponding to the most recent invocation of the function.
Examples:
function f(n) { g(n - 1); } function g(n) { console.log(`before: ${g.arguments[0]}`); if (n > 0) { f(n); } console.log(`after: ${g.arguments[0]}`); } f(2); console.log(`returned: ${g.arguments}`); // Logs: // before: 1 // before: 0 // after: 0 // after: 1 // returned: null
“Function.prototype.arguments
- JavaScript | MDN” (MDN Web Docs). Retrieved April 10, 2024.
Function: length
data property
The length
data property of a Function
instance indicates the number of parameters expected by the function. i.e. the number of formal parameters. This number excludes the rest parameter and only includes parameters before the first one with a default value. By contrast, arguments.length
is local to a function and provides the number of arguments actually passed to the function.
The Function constructor is itself a Function object. Its length
data property has a value of 1
.
Value
A number
.
Examples:
console.log(Function.length); // 1 console.log((() => {}).length); // 0 console.log(((a) => {}).length); // 1 console.log(((a, b) => {}).length); // 2 etc. console.log(((...args) => {}).length); // 0, rest parameter is not counted console.log(((a, b = 1, c) => {}).length); // 1, only parameters before the first one with // a default value are counted
“Function: length - JavaScript | MDN” (MDN Web Docs). Retrieved April 10, 2024.
Function: name
data property
The name
data property of a Function
instance indicates the function’s name as specified when it was created, or it may be either anonymous
or ''
(an empty string) for functions created anonymously.
The name
property is read-only and cannot be changed by the assignment operator.
Value
A string.
Examples:
// -- someModule.js -- export default function () {} // -- main.js -- import someModule from "./someModule.js"; someModule.name; // "default" new Function().name; // "anonymous" const someFunction = function someFunctionName() {}; someFunction.name; // "someFunctionName" (function () {}).name; // "" (() => {}).name; // "" const f = function () {}; const object = { someMethod: function () {}, }; console.log(f.name); // "f" console.log(object.someMethod.name); // "someMethod"
“Function: name - JavaScript | MDN” (MDN Web Docs). Retrieved April 10, 2024.
Function: prototype
data property
The prototype
data property of a Function
instance is used when the function is used as a constructor with the new
operator. It will become the new object’s prototype.
Value
An object.
Description
When a function is called with new
, the constructor’s prototype property will become the resulting object’s prototype.
function Ctor() {} const inst = new Ctor(); console.log(Object.getPrototypeOf(inst) === Ctor.prototype); // true
A function having a prototype
property is not sufficient for it to be eligible as a constructor
. Generator functions have a prototype property, but cannot be called with new
:
async function* asyncGeneratorFunction() {} function* generatorFunction() {}
Instead, generator functions’ prototype property is used when they are called without new
. The prototype
property will become the returned Generator
object’s prototype
.
In addition, some functions may have a prototype
but throw unconditionally when called with new
. For example, the Symbol()
and BigInt()
functions throw when called with new
, because Symbol.prototype
and BigInt.prototype
are only intended to provide methods for the primitive values, but the wrapper objects should not be directly constructed.
The following functions do not have prototype, and are therefore ineligible as constructors, even if a prototype property is later manually assigned:
const method = { foo() {} }.foo; const arrowFunction = () => {}; async function asyncFunction() {}
The following are valid constructors that have prototype:
class Class {} function fn() {}
A bound function does not have a prototype
property, but may be constructable. When it’s constructed, the target function is constructed instead, and if the target function is constructable, it would return a normal instance.
const boundFunction = function () {}.bind(null);
A function’s prototype
property, by default, is a plain object with one property: constructor
, which is a reference to the function itself. The constructor property is writable
, non-enumerable
, and configurable
.
If the prototype
of a function is reassigned with something other than an Object
, when the function is called with new
, the returned object’s prototype would be Object.prototype
instead. (In other words, new
ignores the prototype
property and constructs a plain object.)
function Ctor() {} Ctor.prototype = 3; console.log(Object.getPrototypeOf(new Ctor()) === Object.prototype); // true
“Function: prototype
- JavaScript | MDN” (MDN Web Docs). Retrieved April 17, 2024.
Function.prototype[@@hasInstance]()
The [@@hasInstance]()
method of Function instances specifies the default procedure for determining if a constructor function recognizes an object as one of the constructor’s instances. It is called by the instanceof
operator.
The instanceof operator calls the @@hasInstance method of the right-hand side.
Syntax
func[Symbol.hasInstance](value)
Parameters
value
- The object to test. Primitive values always return false.
Return valuetrue
if func.prototype
is in the prototype chain of value; otherwise, false
. Always returns false
if value is not an object or this is not a function. If this is a bound function, returns the result of a instanceof
test on value and the underlying target function.
Exceptions
TypeError
- Thrown if this is not a bound function and this.prototype
is not an object.
Examples:
class Foo {} const foo = new Foo(); console.log(foo instanceof Foo === Foo[Symbol.hasInstance](foo)); // true
You may want to use this method if you want to invoke the default instanceof behavior, but you don’t know if a constructor has a overridden [@@hasInstance]()
method.
class Foo { static [Symbol.hasInstance](value) { // A custom implementation return false; } } const foo = new Foo(); console.log(foo instanceof Foo); // false console.log(Function.prototype[Symbol.hasInstance].call(Foo, foo)); // true
“Function.prototype[@@hasInstance]() - JavaScript | MDN” (MDN Web Docs). Retrieved April 18, 2024.
Function.prototype.apply()
The apply()
method of Function
instances calls this function with a given this value, and arguments provided as an array (or an array-like object).
Syntax
apply(thisArg) apply(thisArg, argsArray)
Parameters
-
thisArg
- The value ofthis
provided for the call tofunc
. If the function is not in strict mode,null
andundefined
will be replaced with the global object, and primitive values will be converted to objects. -
argsArray
Optional - An array-like object, specifying the arguments with whichfunc
should be called, ornull
orundefined
if no arguments should be provided to the function.
Return value
The result of calling the function with the specified this
value and arguments.
“Function.prototype.apply()
- JavaScript | MDN” (MDN Web Docs). Retrieved April 18, 2024.
What limitations do the Function.prototype.apply()
and the spread syntax have with respect to function arguments?
Using apply()
(or the spread syntax) with an arbitrarily long arguments list, you run the risk of exceeding the JavaScript engine’s argument length limit.
The consequences of calling a function with too many arguments (that is, more than tens of thousands of arguments) is unspecified and varies across engines. (The JavaScriptCore engine has a hard-coded argument limit of 65536.) Most engines throw an exception; but there’s no normative specification preventing other behaviors, such as arbitrarily limiting the number of arguments actually passed to the applied function. To illustrate this latter case: if such an engine had a limit of four arguments (actual limits are of course significantly higher), it would be as if the arguments 5, 6, 2, 3
had been passed to apply
in the examples above, rather than the full array.
If your value array might grow into the tens of thousands, use a hybrid strategy: apply your function to chunks of the array at a time:
function minOfArray(arr) { let min = Infinity; const QUANTUM = 32768; for (let i = 0; i < arr.length; i += QUANTUM) { const submin = Math.min.apply( null, arr.slice(i, Math.min(i + QUANTUM, arr.length)), ); min = Math.min(submin, min); } return min; } const min = minOfArray([5, 6, 2, 3, 7]);
“Using apply() and built-in functions” (MDN Web Docs). Retrieved April 18, 2024.
Function.prototype.bind()
The bind()
method of Function
instances creates a new function that, when called, calls this function with its this
keyword set to the provided value, and a given sequence of arguments preceding any provided when the new function is called.
Syntax
bind(thisArg) bind(thisArg, arg1) bind(thisArg, arg1, arg2) bind(thisArg, arg1, arg2, /* …, */ argN)
Parameters
-
thisArg
- The value to be passed as the this parameter to the target functionfunc
when the bound function is called. If the function is not in strict mode,null
andundefined
will be replaced with the global object, and primitive values will be converted to objects. The value is ignored if the bound function is constructed using thenew
operator. -
arg1, …, argN
Optional - Arguments to prepend to arguments provided to the bound function when invokingfunc
.
Return value
A copy of the given function with the specified this
value, and initial arguments (if provided).
Examples:
// Top-level 'this' is bound to 'globalThis' in scripts. this.x = 9; const module = { x: 81, getX() { return this.x; }, }; // The 'this' parameter of 'getX' is bound to 'module'. console.log(module.getX()); // 81 const retrieveX = module.getX; // The 'this' parameter of 'retrieveX' is bound to 'globalThis' in non-strict mode. console.log(retrieveX()); // 9 // Create a new function 'boundGetX' with the 'this' parameter bound to 'module'. const boundGetX = retrieveX.bind(module); console.log(boundGetX()); // 81
“Function.prototype.bind()
- JavaScript | MDN” (MDN Web Docs). Retrieved April 19, 2024.
Given the following code:
"use strict"; // prevent `this` from being boxed into the wrapper object function log(...args) { console.log(this, ...args); } const boundLog = log.bind("this value", 1, 2); const boundLog2 = boundLog.bind("new this value", 3, 4); boundLog2(5, 6);
What will boundLog2(5, 6)
print?
It will print:
"this value", 1, 2, 3, 4, 5, 6
Explanation:
The bind()
function creates a new bound function. Calling the bound function generally results in the execution of the function it wraps, which is also called the target function. The bound function will store the parameters passed — which include the value of this
and the first few arguments — as its internal state. You can generally see
const boundFn = fn.bind(thisArg, arg1, arg2)
as being equivalent to
const boundFn = (...restArgs) => fn.call(thisArg, arg1, arg2, ...restArgs)
for the effect when it’s called (but not when boundFn
is constructed).
A bound function can be further bound by calling boundFn.bind(thisArg, /* more args */)
, which creates another bound function boundFn2
. The newly bound thisArg
value is ignored, because the target function of boundFn2
, which is boundFn
, already has a bound this
. When boundFn2
is called, it would call boundFn
, which in turn calls fn
. The arguments that fn
ultimately receives are, in order:
- the arguments bound by
boundFn
, - arguments bound by
boundFn2
, and - the arguments received by
boundFn2
.
“Function.prototype.bind()
” (MDN Web Docs). Retrieved April 19, 2024.
What happens when you call a bounded function with the new
operator?
A bound function may also be constructed using the new
operator if its target function is constructable. Doing so acts as though the target function had instead been constructed. The prepended arguments are provided to the target function as usual, while the provided this
value is ignored (because construction prepares its own this
, as seen by the parameters of Reflect.construct
). If the bound function is directly constructed, new.target
will be the target function instead. (That is, the bound function is transparent to new.target.
)
class Base { constructor(...args) { console.log(new.target === Base); console.log(args); } } const BoundBase = Base.bind(null, 1, 2); new BoundBase(3, 4); // true, [1, 2, 3, 4]
However, because a bound function does not have the prototype
property, it cannot be used as a base class for extends
.
class Derived extends class {}.bind(null) {} // TypeError: Class extends value does not have valid prototype property undefined
“Function.prototype.bind()
” (MDN Web Docs). Retrieved April 19, 2024.
What happens when using a bound function as the right-hand side of instanceof
operator?
When using a bound function as the right-hand side of instanceof
, instanceof
would reach for the target function (which is stored internally in the bound function) and read its prototype instead.
class Base {} const BoundBase = Base.bind(null, 1, 2); console.log(new Base() instanceof BoundBase); // true
“Function.prototype.bind() - JavaScript | MDN” (MDN Web Docs). Retrieved April 20, 2024.
What properties does a bound function have?
The bound function has the following properties:
-
length
- The length of the target function minus the number of arguments being bound (not counting thethisArg
parameter), with0
being the minimum value. -
name
Thename
of the target function plus a"bound "
prefix.
The bound function also inherits the prototype chain of the target function. However, it doesn’t have other own properties of the target function (such as static properties if the target function is a class).
“Function.prototype.bind() - JavaScript | MDN” (MDN Web Docs). Retrieved April 20, 2024.
Function.prototype.call()
The call()
method of Function
instances calls this function with a given this value and arguments provided individually.
Syntax
call(thisArg) call(thisArg, arg1) call(thisArg, arg1, arg2) call(thisArg, arg1, arg2, /* …, */ argN)
Parameters
-
thisArg
- The value to use asthis
when callingfunc
. If the function is not instrict mode
,null
andundefined
will be replaced with the global object, and primitive values will be converted to objects. -
arg1, …, argN
Optional - Arguments for the function.
Return value
The result of calling the function with the specified this
value and arguments.
Note: This function is almost identical to apply()
, except that the function arguments are passed to call()
individually as a list, while for apply()
they are combined in one object, typically an array — for example, func.call(this, "eat", "bananas")
vs. func.apply(this, ["eat", "bananas"])
.
Examples:
function greet() { console.log(this.animal, "typically sleep between", this.sleepDuration); } const obj = { animal: "cats", sleepDuration: "12 and 16 hours", }; greet.call(obj); // cats typically sleep between 12 and 16 hours
“Function.prototype.call()
- JavaScript | MDN” (MDN Web Docs). Retrieved April 20, 2024.
What happens if you use call()
to invoke a function without specifying the first argument?
If the first thisArg
parameter is omitted, it defaults to undefined
. In non-strict mode, the this
value is then substituted with globalThis
(which is akin to the global object).
globalThis.globProp = "Wisen"; function display() { console.log(`globProp value is ${this.globProp}`); } display.call(); // Logs "globProp value is Wisen"
In strict mode, the value of this
is not substituted, so it stays as undefined
.
"use strict"; globalThis.globProp = "Wisen"; function display() { console.log(`globProp value is ${this.globProp}`); } display.call(); // throws TypeError: Cannot read the property of 'globProp' of undefined
“Using call() to invoke a function without specifying the first argument” (MDN Web Docs). Retrieved April 22, 2024.