Reputation: 368
Which one has better performance? If statements are more readable but what if I make values in array (database-esque) and make my for loop call the function based on the current index which make it easier for further editing.
var msg = [
"You are now viewing Tab number one",
"You are now viewing Tab number two",
"You are now viewing Tab number three",
"You are now viewing Tab number four"
]
var button = document.getElementsByTagName("button")
for (var i = 0, len = button.length; i < len; ++i) {
(function(index) {
button[i].addEventListener("click",
function() {
document.getElementById("msg").innerHTML = msg[index];
});
})(i);
}
<button>Tab1</button>
<button>Tab2</button>
<button>Tab3</button>
<button>Tab4</button>
<br>
<p id="msg">Message here</p>
var button = document.getElementsByTagName("button")
for (var i = 0, len = button.length; i < len; ++i) {
(function(index) {
button[i].addEventListener("click",
function() {
if (index==0){
document.getElementById("msg").innerHTML = "You are now viewing Tab number one";
}
if (index==1) {
document.getElementById("msg").innerHTML = "You are now viewing Tab number two";
}
if (index==2) {
document.getElementById("msg").innerHTML = "You are now viewing Tab number three";
}
if (index==3) {
document.getElementById("msg").innerHTML = "You are now viewing Tab number four";
}
});
})(i);
}
<button>Tab1</button>
<button>Tab2</button>
<button>Tab3</button>
<button>Tab4</button>
<br>
<p id="msg">Message here</p>
Upvotes: 0
Views: 557
Reputation:
Using tabindex
or data-index
attribute might be a good idea in this occasion. The example snippet does not involve a loop and uses data-index
.
var msg = [
"You are now viewing Tab number one",
"You are now viewing Tab number two",
"You are now viewing Tab number three",
"You are now viewing Tab number four"
]
document.body.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
if (e.target.tagName == 'BUTTON') {
document.getElementById('msg').innerHTML = msg[e.target.dataset['index']];
}
});
<button data-index="0">Tab1</button>
<button data-index="1">Tab2</button>
<button data-index="2">Tab3</button>
<button data-index="3">Tab4</button>
<br>
<p id="msg">Message here</p>
EDIT
Try to avoid using tabindex
if you are going to have a large number of tabs. The following part is taken from MDN
Avoid using tabindex values greater than 0. Doing so makes it difficult for people who rely on assistive technology to navigate and operate page content. Instead, write the document with the elements in a logical sequence.
Furthermore tabindex
has a maximum value of 32767.
Upvotes: 1
Reputation: 164679
For 4 items, or even 40, performance is irrelevant: computers are very fast and the list is very short. What's more important is how hard it is to read and maintain.
But it's worth looking into some underlying performance principles, particularly when it comes to lists, because small lists have an annoying tendency to get large.
An array lookup like button[i]
is constant time or O(1). That means no matter how large button
gets the lookup will always take the same time.
Whereas a succession of if statements, or a switch
, must try each one until it finds one which matches. Best case is i
is always 0 and it must compare 1 time. Worst case is i
is always 3 and it must compare 4 times. If i
is evenly distributed then it will, on average, take 2 times. This is called linear time or O(n), the time of the lookup increases as the size of button
increases. If button
gets twice as large the time gets twice as long.
With an array lookup as button
gets larger the performance will remain the same. With if statements as button
gets larger the performance will get worse.
Right now, starting out, you will find linear code easier to read. You'll prefer to have everything in front of you on the page in the order it is executed. But as the code gets more complicated this rapidly becomes overwhelming and will lead to a lot of cutting and pasting code violating the DRY principle: Don't Repeat Yourself.
Experienced programmers find that it's better to push as many details off somewhere else so one can clearly see the important parts. The important part is that it generates click handlers for each button that adds a message from msg
. What's unimportant is exactly what that message is.
You could make the code even simpler, and possibly save some memory, by extracting the functions from the loop.
var addMsgListener = function(element, message) {
element.addEventListener("click",
function() {
document.getElementById("msg").innerHTML = message;
}
)
};
var buttonMessages = [
"You are now viewing Tab number one",
"You are now viewing Tab number two",
"You are now viewing Tab number three",
"You are now viewing Tab number four"
]
var button = document.getElementsByTagName("button")
for (var i = 0, len = button.length; i < len; ++i) {
addMsgListener(button[i], buttonMessages[i]);
}
Please pardon my possibly awful Javascript.
Now it's very clear what that loop does, for each button it adds a message listener. If I care what a message listener is, I can choose to look at addMessageListener
. Or I can skip it. This makes the code "skimmable"; one can read the code to get an understanding of what it does and only dive into the details as necessary. It is not a linear read, but that is something you will get used to and come to prefer.
Note that addMsgListener
no longer refers to msg
nor button
. Those are chosen by the loop using it. It is now generic and can be used for other elements and messages.
More reusability will now reveal itself; do the event and id need to be hard coded? This process of changing the code without changing what it does is called refactoring.
Every time you want to change a message you have to change code. If you want to add a message, you have to add code and renumber. If you want to remove a message, you have to delete code and renumber. If you want to reorder messages, you have to renumber. This requires a developer for what is a UI change. And the process is error prone, what if you remove a message and forget to change the indexes?
By putting the messages into an array, you only need to change msg
. If you want to add a message, you add a line to msg
. If you want to remove a message, you remove a line from msg
. If you want to reorder the messages, you reorder msg
.
msg
does not have to live in the code, it can go into a configuration file making it even easier for a non-coder to change.
This leads us to our final problem: msg
needs to be the same length and order as there are buttons. Every time the HTML is changed, msg
might need to be changed, and vice-versa. But the buttons and their messages are in separate locations. This is known as Action at a Distance: changing one part of the code is affected by something in a totally different part of the code.
To avoid this, you could give each button a class
or id
and index their messages by that. This at least means the buttons and messages don't depend on their exact order. This is useful if you're not sure which buttons will be present in the HTML, but want to have messages for all possible buttons.
var msg = {
car: "🏎",
truck: "🚚",
train: "🚆",
plane: "✈"
}
You can go the other way; generate the buttons, and their messages, in the Javascript. It still keeps all the information about each button together. This is useful if the buttons are dynamic and can change.
You can do as Thomas suggests and attach the messages to the buttons themselves. Then all the data about the buttons is together. If you add, remove, or reorder the buttons the messages still work. This allows one to work on just the HTML.
Upvotes: 2
Reputation: 12637
That's like asking which high-end graphics card should I use for my simple digital clock?
The Performance difference is neglectable. Using an iife instead of let
has already a bigger performance impact than your actual question, array index vs. multiple ifs.
And it is still irrelevant.
About the Options, I find them both pretty hard to read, especially as the number of buttons gets bigger.
How about this?
document.querySelector(".buttons").addEventListener("click", function(event) {
const button = event.target.closest("button[data-msg]");
if (button) {
document.querySelector("#msg").innerText = button.dataset.msg;
}
})
<div class="buttons">
<button type="button" data-msg="You are now viewing Tab number one">Tab1</button>
<button type="button" data-msg="You are now viewing Tab number two">Tab2</button>
<button type="button" data-msg="You are now viewing Tab number three">Tab3</button>
<button type="button" data-msg="You are now viewing Tab number four">Tab4</button>
</div>
<p id="msg">Message here</p>
imo. nice and declarative. And easy to extend.
The condition if(button)
deals with the possibility that you might add something else to div.buttons
that could be clicked on, besides these buttons.
The .closest("button[data-msg]")
delas with the cases where you might add more markup inside the buttons that might fire the event. We want the <button data-msg="...">
Upvotes: 4