JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.
In this article, we’ll look at ways to call functions and access arguments, ending the execution of functions, and augmenting built-in types.
Apply Invocation Pattern
We can use the function’s apply
method to set the value this
and pass in arguments.
For instance, we can write:
const array = [1, 2];
const sum = add.apply(null, array);
We set this
to null
and the arguments to the entries of array
.
The apply
method is only available in traditional functions.
Arrow function don’t bind to this
, so it doesn’t have apply
.
To set the value of this
with apply
and call a method, we can write:
const obj = {}
const obj2 = {}
function getValue(value) {
this.value = value
return this.value;
}
console.log(getValue.apply(obj, [1]));
console.log(getValue.apply(obj2, [2]));
In the code above, we have the getValue
function.
In the last 2 lines, we set the value of this
to obj
and obj2
respectively.
Then we call them 1 or 2 respectively.
This way the first call returns 1 and the second returns 2.
Arguments
We can use the arguments
object to access the arguments that are passed into a function.
This only works with traditional functions, so we can’t use it with arrow functions.
For instance, we can write:
const add = function() {
let sum = 0;
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
};
Then we can call it by writing:
add(1, 2, 3, 4, 5);
to pass them in as arguments.
Then in add
, we loop through the arguments
object to get all the arguments.
arguments
isn’t an array, but it has indexes and the length
property.
Rest Parameters
The modern alternative is to use rest parameters.
We can rewrite the add
function by writing:
const add = (...args) => {
let sum = 0;
for (const a of args) {
sum += a;
}
return sum;
};
We call add
the same way.
But we added a rest parameter args
, which is an array of all the arguments passed in.
Then we used the for-of loop to loop through the items and add up the numbers.
Return
The return
keyword is used to end the execution of a function.
We can use it anywhere.
This means we can create guard clauses with it. They are code that ends the function is something required by the function isn’t there.
A function always returns a value, if a return
value isn’t specified, then undefined
is returned.
If a function is run with a new
prefix and we didn’t specify an explicit return
statement.
Then this
, which is the object created by the constructor, is returned.
Exceptions
JavaScript has an exception handling mechansim.
Exceptions are unusual things that interfere with the normal flow of a program.
When we run into something that causes issues, we may throw an exception.
The throw statement interrupts the execution of a function.
We can surround any code that throws an exception with a try-catch block.
For instance, we can write:
try {
add(1, 2, 3);
} catch (e) {
console.log(e);
}
In the code above, add
may throw an exception, so we wrapped it around a try
block.
This way, when an exception is thrown, the catch
block will catch the exception.
Augmenting Types
Augmenting types are adding methods to built-in constructors.
We should do that by using creating a subclass of the built-in constructors.
To augment a built-in type, we can create a subclass by using the extends
keyword.
This way, we don’t change the built-in prototypes directly, which isn’t a good idea because it adds unexpected methods that people don’t expect.
For instance, we can create a subclass of String
as follows:
class FancyString extends String {
greet(){
console.log(`hi ${this}`)
}
}
const str = new FancyString('foo');
str.greet()
In the code above, we created the FancyString
class, which inherits all the members of the String
constructor.
Inside it, we add a greet
method.
Then we can use it as follows:
const str = new FancyString('foo');
str.greet();
We create a FancyString
instance and called greet
on it.
this
would be 'foo'
, so we ‘hi foo’
is logged.
Conclusion
With traditional functions, we can use the apply
method to change the value of this
inside a traditional function and pass in an array of arguments to call a function.
Functions can have code that throws exceptions, and we can use a try-catch block to catch the exceptions.
We can augment types by using the class syntax and the extends
keyword.