Reasons for Creating a Function Without the Name and Assigning It to a Constant Variable
Recently, one of my readers asked me a very interesting question:
Is there any advantage to declaring an unnamed function definition to a const over simply declaring a function?
The first one is called a function expression, and the other is called a function declaration. There's no one-size-fits-all answer; it's all about what you want to achieve with your code.
So, let's discuss how they differ, allowing you to choose the right one based on your needs.
1. Preventing Variable Re-declaration
Using the const
keyword when declaring a function in JavaScript helps prevent accidental mistakes. If you declare a function with const
and later try to declare another variable with the same name, it will result in an error, alerting you to the issue.
const changeText = () => { /* original */ }; // ... const changeText = () => { /* different version */ }; // SyntaxError!
On the other hand, if you use function
to declare a function and later declare another function with the same name, it will simply replace the original function without any error.
function changeText() { /* original */ } // ... function changeText() { /* different version */ } // No error, this is your function now
2. Avoiding Global Property Creation
When you use function
to declare a function globally, it also creates a global property of the same name. This can lead to conflicts and unexpected behavior.
function changeText() { /* ... */ } console.log(window.changeText); // function changeText
Using const
(or let
) prevents the creation of these global properties.
const changeText = () => { /* ... */ }; console.log(window.changeText); // undefined
Why Avoid Global Variables?
Creating global variables comes with risks. If you have a global variable and later create another variable or function with the same name, they can interfere with each other. This isn't just a concern for your variables but could also impact variables from other scripts or frameworks you're using.
Imagine you create a variable called name
that holds information about a person:
var name = { first: "John", last: "Doe" };
Now, if you try to log this variable:
console.log(name); // What do you expect to see?
You might think it would show the person's details, but surprise! It actually shows the string "[object Object]". Why? Well, the variable name
becomes a global property, and it can only store string values. So, when you assigned an object to it, JavaScript converted the object to a string and stored it in the global window
object.
console.log(typeof name); // Outputs: string
Now, here's where it gets tricky. If you attempt to create a function with the same name name
, it doesn't coexist peacefully with the variable. Instead, it completely replaces the global name
property. Now, name
is a function, not a string.
function name() {} console.log(name); // Outputs: function name console.log(typeof name); // Outputs: function
What if you want to create a global function named top
? Nope, that won't work because there's already a global top
in place.
function top() {} // SyntaxError!
So, the lesson here is to steer clear of working in the global playground.
3. Hoisting:
Function declarations are hoisted, which means they are moved to the top of the code during the compilation phase. This allows you to call the function before it's declared in the code.
// Function Declaration greet(); // Works function greet() { console.log("Hello!"); }
Unlike function declarations, function expressions are not hoisted to the top of the scope during the compilation phase. This means that you cannot call a function expression before it is declared in your code.
// Function Expression // greet(); // Error - not yet defined const greet = () => { console.log("Hello!"); };
4. "this" Binding:
In a simple function declaration defined using the function
keyword, the this
keyword is always set to the global object (e.g., Window
in a browser) when the function is invoked without any explicit binding.
// Function Declaration function greet() { console.log(`Function Declaration: Hello, ${this.name}!`); } // this refers to the global object (e.g., Window in a browser) greet(); // Outputs: Function Declaration: Hello, undefined!
The same behavior applies to function expressions defined using the function
keyword.
// Function Expression const greetExpression = function () { console.log(`Function Expression: Hello, ${this.name}!`); }; // this refers to the global object (e.g., Window in a browser) greetExpression(); // Outputs: Function Expression: Hello, undefined!
If a named function or function expression with the function
keyword has been defined in the global scope and is then used as a method of an object, this
refers to the object it is contained within.
const obj = { name: "Alice", greetMethod: greet, greetExpressionMethod: greetExpression, }; // this refers to the object (obj) obj.greetMethod(); // Outputs: Function Declaration: Hello, Alice! // this refers to the object (obj) obj.greetExpressionMethod(); // Outputs: Function Expression: Hello, Alice!
Arrow functions, on the other hand, inherit this
from their immediate lexical scope. This means that when arrow functions are used within an object method, the this
context remains bound to the object itself, rather than the global object (Window
in a browser).
const obj = { name: "Alice", arrowMethod: () => { console.log(`Arrow Function: Hello, ${this.name}!`); }, }; // this refers to the object (obj) obj.arrowMethod(); // Outputs: Arrow Function: Hello, Alice!
Conclusion
Normally, you can use function declarations and function expressions interchangeably. However, there are times when you can select one based on your specific needs.
Choose between function declarations and function expressions with arrow function based on how you want the value of this
to behave.
Opt for function declarations when you want the function to be hoisted or function expressions when you want to control hoisting.
Use function declarations if you want to create a function on the global scope, making it available throughout your code. Use function expressions to restrict where the function is available, keep your global scope light, and maintain clean syntax.
Learn Higher-Order Functions
Write code that is easier to understand and maintain.
You've heard about higher-order functions, but every explanation you've come across is either too technical or too vague. You're searching for something clear and practical, with examples that will help you practice and truly master the concept.
Higher-order functions are key to writing better code, essential for your projects, and expected in interviews. But getting started can be tough.
But what if you could? What if you had access to easy-to-understand content that not only explains higher-order functions but also provides hands-on practice? You’d finally feel confident using them in your projects, knowing exactly what they do and how to leverage them effectively.
It’s true, finding the right resources to learn higher-order functions can be challenging… but it doesn’t have to be.
Get my guide, where you’ll:
- Understand why higher-order functions are worth learning and how they can transform your approach to writing JavaScript.
- Gain clarity as I break down higher-order functions into simple, everyday language.
- Master three important higher-order functions:
map
,filter
, andreduce
, with plenty of examples to solidify your understanding. - Apply your knowledge with real-world examples that demonstrate how these concepts work together, so you can use them easily in your projects or write better code in your interviews.