Reputation: 11
I think two examples will illustrate my question best.
(function(){
var myBtn = document.getElementById('myBtn');
function one() {
console.log(myBtn.innerHtml);
}
function two() {
myBtn.innerHtml = "apple";
}
function three() {
console.log(myBtn.value);
}
})();
vs
(function(){
function one() {
var myBtn = document.getElementById('myBtn');
console.log(myBtn.innerHtml);
}
function two() {
var myBtn = document.getElementById('myBtn');
myBtn.innerHtml = "apple";
}
function three() {
var myBtn = document.getElementById('myBtn');
console.log(myBtn.value);
}
})();
So the first examples uses a global variable (or when it's locked withing a self-invoking function it's not a global variable?) the second does not. The first example is more DRY while the second keeps everything within functions.
Which one is better to use? What are the pros and cons of both? Does project scale matter?
Again this is a theoretical example, the functions obviously don't work without html. Thanks.
Upvotes: 1
Views: 602
Reputation: 41065
The reason its recommended that you don't use a global variables is so that you don't pollute the global namespace. The same argument would hold for a large closure. You don't want to be polluting the closure with too many variables
So while something like
(function(){
var myBtn = document.getElementById('myBtn');
function one() {
console.log(myBtn.innerHtml);
}
function two() {
myBtn.innerHtml = "apple";
}
function three() {
console.log(myBtn.value);
}
})();
does not pollute the global scope, it does pollute the closure i.e. imagine how difficult maintenance would be if you had something like
(function(){
var myBtn = document.getElementById('myBtn');
// lots of code..
function one() {
console.log(myBtn.innerHtml);
}
// lots of code..
function two() {
myBtn.innerHtml = "apple";
}
// lots of code..
function three() {
console.log(myBtn.value);
}
})();
because you have to know that when you are in three()
that myBtn exists in the parent scope and creating a local variable within three
would mask that
Another case against using variable from an outer scope
(function(){
var myBtn = document.getElementById('myBtn');
// lots of code..
function one() {
console.log(myBtn.innerHtml);
}
// lots of code..
var myBtn1 = document.getElementById('myBtn1');
function two() {
myBtn1.innerHtml = "apple";
}
// lots of code..
function three() {
console.log(myBtn.value);
}
})();
with a long enough outer closure, you'd be forced to keep track of myBtn, myBtn1.... So while this is better than global scope (where you had to keep track of variable across files), now you (just?) have to keep track of all the variables within the closure.
Which begets the question, what would be a better way for large closures. Here is one option
(function () {
// lots of code..
function one(myBtn) {
console.log(myBtn.innerHtml);
}
// lots of code..
function two(myBtn) {
myBtn.innerHtml = "apple";
}
// lots of code..
function three(myBtn) {
console.log(myBtn.value);
}
var myBtn = document.getElementById('myBtn');
one(myBtn);
two(myBtn);
three(myBtn);
})();
which keeps everything nicely localized. Of course if you have a large closure it is probably an indication that you are doing too much in that closure (module).
Of course for small closures, your first option is pretty ok.
Upvotes: 0
Reputation: 64923
There's a third and missing approach in your question: using objects.
If myBtn
element won't be dropped from the document within the life of the page (i.e. until user refreshes the page F5), as your first approach, you should store a reference to the element in order to avoid querying the document many times:
(function() {
// SomeObject isn't global, but a local variable of IIFE's scope ;)
var SomeObject = function() {
this.myBtn = document.getElementById("myBtn");
};
SomeObject.prototype = {
one: function() {
console.log(this.myBtn.innerHTML);
},
two: function() {
this.myBtn.innerHtml = "apple";
},
three: function() {
console.log(this.myBtn.value);
}
};
// This is required in order to be sure that SomeObject is going to
// be able to retrieve "myBtn" element during its construction time,
// because the document is already loaded
document.addEventListener("DOMContentLoaded", function() {
var some = new SomeObject();
some.one();
});
})();
<button id="myBtn">My button</button>
Upvotes: 0
Reputation: 1004
First one is better to use. it gives cleaner and faster code.
(function(){
var myBtn = document.getElementById('myBtn');
function one() {
console.log(myBtn.innerHtml);
}
function two() {
myBtn.innerHtml = "apple";
}
function three() {
console.log(myBtn.value);
}
})();
Edit: There is no need to run the same code multiple times when the result would just be stored and shared across all you functions
Upvotes: 0
Reputation: 1082
The document.getElementById
function will return the reference to the first object with the ID specified. This means it will return the reference to the same object during subsequent calls (in most cases, if used appropriately), which will never refer to other elements, or get invalidated.
You can safely stick to the style of the first example. This is not c++, and your object won't disappear.
Upvotes: 0
Reputation: 140
One of te disadvantages of the second is that within every function the variable needs to be calculated and stored again. This will have an impact on the performance. The variable will be the same in all functions so you could subtract it at place it above the function as in function 1. The variable in example 1 will not become a global variable (because of the use of an iffy). This is also positive. Need to keep the global environment as clean as possible. Personally I think option 1 is also more obvious what is going on.
Upvotes: 1