1 Optional Parameters and Defaults
2 Rest Parameters
3 The Arguments Object
4 The Spread Operator for Function Calls
5 Destructuring Function Arguments into Parameters
Function parameters are defined in the function signature; function arguments are values provided every time the function is invoked
- NOTE: function invocations work with fewer or with more arguments than declared parameters
1 Optional Parameters and Defaults
Invoking a function with fewer arguments
- a function can be invoked with fewer arguments than declared parameters
- the missing parameters are set to the
undefinedvalue - you can write a function where some arguments are optional
Writing functions with optional parameters
- in traditional JavaScript, you test whether a parameter is
undefined - as alternate solution, you can use ES6 parameter defaults syntax
- note: in functions with optional parameters, the optional ones should always be the last of the argument list
Writing functions with optional arguments, using traditional JavaScript syntax
Example: the sum function with not undefined testing
const sum = (x, /*optional*/ y) => {
// test for undefined argument
y = y === undefined ? x : y;
return x + y;
}
console.log(sum(2, 2)); // 4
console.log(sum(2)); // 4
Writing functions with optional arguments using ES6 parameter defaults syntax
- ES6 allows to define default values for each function parameter directly in the function signature
- just follow the parameter name with an equal sign and the default value
- note: parameter default expressions are evaluated when the function is invoked, not when the function is defined
- note: parameter defaults can be a constants, variables or function invocations
Example: the sum functions with default arguments
// 1. the sum function has parameter y with default argument
const sum = (x, y = x) => {
return x + y;
}
console.log(sum(2, 2)); // 4
console.log(sum(2)); // 4
// 2. the sum2 function has multiple default arguments
const sum2 = (x = 0, y = x) => {
return x + y;
}
console.log(sum2(2, 2)); // 4
console.log(sum2(2)); // 4
console.log(sum2()); // 0
2 Rest Parameters
Invoking functions with more arguments
- if you call a function with more arguments than declared parameters, the extra is ignored
console.log(sum(2, 2, 4)); // 4
Writing variadic function with ECMAScript 6 rest parameters
- ES6 rest parameters syntax allows to write function that can be invoked with more arguments than declared parameters
- functions that accept any number of arguments are named variadic functions, variable arity functions or varargs functions
Example: the sum function with rest parameters
const sum = (first = 0, ...rest) => {
let sum = first
for (const value of rest) {
sum += value
}
return sum;
}
console.log(sum(1, 2, 3, 4, 5)) // 15
console.log(sum(6, 7, 8, 9, 10)) // 40
Function's rest parameters syntax
- a rest parameter is preceded by three periods
- a rest parameter must be the last parameter in the function signature
How do rest parameters work?
- the arguments passed in the function invocation are assigned to non-rest parameters
- the remaining arguments (the rest of the aguments) are stored in a array which is the value of the rest parameter
- in the function body, the rest parameter has array type
- in the function body, the value of rest parameter can be an empty array, but cannot be
undefined
3 The Arguments Object
In traditional JavaScript, you could write variadic functions using the arguments object
The arguments object:
- it is defined in the function body
- it contains all the arguments values passed to the function for that invocation
- it is an array-like object, with
lengthproperty; which means that argument values are looped over in aforloop
Note: in modern javaScript: you should not be using the Arguments object anymore
- in strict mode
argumentsis treated as a reserved keyword - try to refactor any function using the
argumentsobject and replace it with...argsrest parameters
4 The Spread Operator for Function Calls
What is the use of the spread syntax?
- the spread syntax (
...) is used to extract the values contained in an iterable object
When using the spread syntax?
- use the spread syntax in situations where multiple simple values are expected
- for example, when creating array and object literals or when invoking functions
Example: Invoking Math.max with an array argument
// Math.max function can take any number of arguments console.log(Math.max(11, 17, 13)) // 17 let numbers = [1, 7, 5, 9] // passing an array will not work console.log(Math.max(numbers)) // NaN // you need to spread out the contents into individual arguments console.log(Math.max(...numbers)) // 9
Comparing the spread syntax and the rest syntax
- in a function invocation, the three dots are called the spread syntax as they separates the content of an iterable object into multiple single values
- in a function definition, the three dots are called the rest parameter as they gather multiple arguments into an array
5 Destructuring Function Arguments into Parameters
When a function is invoked, argument values are assigned to the parameters declared in the function signature
- parameter assignment is like variable assignment and therefore destructuring can be used in function parameter assignment
How to destructure function arguments into parameters?
- in function signature definitions:
- put parameter names in square brackets to destructure array arguments
- put parameter names in curly braces to destructure object arguments
- in function invocation expression
- pass an array value for each pair of brackets in the function signature
- pass an object value for each pair of curly braces in the function signature
- when function invocation expression is evaluated
- arguments value are extracted and assigned to the array elements or the object properties
Example: the vectorSum([x1,y1], [x2,y2]) function adds 2D vectors
- this function destructures the components of 2D vectors in two parameters
[x,y]
function vectorSum([x1,y1], [x2,y2]) {
return [x1+x2, y1+y2];
}
vectorSum([1,2], [3,4]) // [4,6]
When is it convenient to destructure object arguments into function parameters?
- use argument destructuring, if function parameter lists are long or contains many optional parameters
Example: a function with optional parameter written in traditional JavaScript
- check whether each argument is undefined and provide a default value
// 1. in traditional JavaScript, check whether argument is not undefined
function objectToString(object, config) {
if (config === undefined) config = {};
if (config.nameValueSeparator === undefined) config.nameValueSeparator = ' = ';
if (config.propSeparator === undefined) config.propSeparator = ', ';
...
}
Example: a function with optional parameter using ES6 parameter destructuring
- this function turns an object into a string
- this function is customizable, because the caller specifies some configuration parameters: the name-value separator, the property separator, etc.
- instead of using parameters, this function uses an object literal
- the function takes as second parameter an object, which declares the destructured parameter variables
- the destructured parameters are:
leftDelimiter, nameValueSeparator, propSeparator, rightDelimiter - each destructured parameter has a default value
- in case the caller does not provide any argument for the config object, there is also a default blank object
{}
// 2. in ECMAScript 6, use destructuring and assign default value to destructured parameters
function objectToString(object, {leftDelimiter = '{',
nameValueSeparator = '=',
propSeparator = ', ',
rightDelimiter = '}'} = {} ) {
let props = Object.entries(object)
.map( ([k,v]) => { return [k, typeof(v)==="string"?`"${v}"`:typeof(v)==="function"?"Function":v] })
.map( item => { return `${item.join(nameValueSeparator)}` })
.join(propSeparator)
return `${object.constructor.name}: ${leftDelimiter}${props}${rightDelimiter}`;
}
// actress object
const actress = {
id: 100,
firstName: 'Uma',
middleName: 'Karuna',
lastName: 'Thurman',
age(){ return }
};
// invoke without config argument
console.log(objectToString(actress));
// Object: {id=100, firstName="Uma", middleName="Karuna", lastName="Thurman", age=Function}
// invoke with config argument
const options = {
nameValueSeparator : '\u279C',
propSeparator : ' \u2E3A ',
rightDelimiter : ')',
leftDelimiter : '('
};
console.log(objectToString(actress, options));
// Object: (id➜100 ⸺ firstName➜"Uma" ⸺ middleName➜"Karuna" ⸺ lastName➜"Thurman" ⸺ age➜Function)
No comments:
Post a Comment