Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
In JavaScript, there are multiple ways to declare a function. One way is to declare it with the function keyword. The other way is to declare it as an arrow function.
In fact, there are two ways to declare a function with the function
keyword. One way is using function declarations, which are also called function statements, and the other is to use function expressions.
In JavaScript, functions are first-class, which means that they’re objects we can define on the fly.
Function Declarations
Function declarations, also called function statements, are the way we define a function — with the function
keyword followed by the name of the function.
For example, we can write the following to define a function with a function declaration:
function foo(){
return 'foo';
}
A function declaration is stored in memory prior to executing the program. This means we can reference it anywhere in our code, even before it’s declared. Storing a variable in memory prior to executing the program is called “hoisting” in JavaScript.
For example, if we write the following:
console.log(foo());
function foo() {
return 'foo'
}
console.log(foo());
We get foo
logged from both function calls.
Function Expressions
Function expressions are functions stored as a value of a variable.
For example, to define a function as a function expression, we write:
const foo = function() {
return 'foo'
}
Unless they’re function declarations or statements, function expressions aren’t stored in memory before the program runs. The function is defined in run-time, so we can only reference them after they’re declared.
For example, if write the follwing:
console.log(foo());
const foo = function() {
return 'foo'
}
console.log(foo());
We’ll get the following error: Uncaught ReferenceError: Cannot access ‘foo’ before initialization’
.
In the code above, we have the variable declaration when the program initially runs, but we don’t have the function assigned to it yet, so we can’t access it. Also, anything defined with the let
, or const
keywords can’t be used with those variables or constants before it’s defined, which also prevents it from being run.
When Should We Use Function Declarations or Expressions?
It depends on personal style. Function declarations are more convenient — they’re available in any part of the script — while function expressions let us assign a function to a variable and reference the variable in various ways, like the calling methods it has.
First-Class Functions
As we see in the function expression example, we can assign a function to a variable in JavaScript. The term for this is a first-class function. First-class functions are functions defined on the fly as the program runs.
This is because in JavaScript, functions are objects just like everything else. Functions have their own methods and other properties and can be used just like objects.
For example, all functions have the toString
method to convert them to a string with the code that defines the function.
Other methods in a function would be methods that call a function with a different this
value, like bind
, call
, and apply
.
We can use the toString
method by writing the following code:
function foo() {
return 'foo'
}
console.log(foo.toString());
Then we get the following from the console.log
:
function foo() {
return 'foo'
}
The bind
, call
, and apply
methods are similar. They all take an object for the this
keyword in the function as the first argument. bind
and call
take a comma-separated list of arguments for the other arguments and apply
takes an array of arguments as the second argument.
For example, we can change the value of this
in a function with the call
method by writing the following code:
let obj = {
firstName: 'Joe',
lastName: 'Smith'
}
let person = {
firstName: 'Jane',
lastName: 'Smith',
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
console.log(person.getFullName());
console.log(person.getFullName.call(obj));
The first example would be the same except that we change call
to apply
, since we didn’t pass in the second or subsequent arguments:
let obj = {
firstName: 'Joe',
lastName: 'Smith'
}
let person = {
firstName: 'Jane',
lastName: 'Smith',
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
console.log(person.getFullName());
console.log(person.getFullName.apply(obj));
Then we get Jane Smith
for the first console.log
, since we haven’t changed the value with apply
yet, but we changed the value of this
to obj
with the apply
method in the second console.log
so that we get Joe Smith
.
We can call bind
with an object passed in, as in the following code:
let person = {
firstName: 'Jane',
lastName: 'Smith',
getName() {
return `${this.firstName} ${this.lastName}`
}
}
const joe = {
firstName: 'Joe',
lastName: 'Smith'
}
console.log(person.getName.bind(joe)());
Then we get 'Joe Smith'
since we passed in the joe
object into the first argument of the bind
method, which sets the this
object inside the getName
method to the joe
object.
In JavaScript, there are two ways to declare a function with the function
keyword. One way is using function declarations, which are also called function statements, and the other is to use function expressions.
Function declarations are defining a function with the function
keyword followed by the name of the function. They are available anywhere in the program.
Function expressions are functions assigned to variables. They’re only available after they’re declared and assigned to the variable.
In JavaScript, functions are first-class, which means that they’re objects that we can define on the fly.
With these features in mind, we can use in ways that are different from languages like Java, where functions can only be inside classes.