How to avoid global variables in JavaScript?
The easiest way is to wrap your code in a closure and manually expose only those variables you need globally to the global scope:
(function() {
// Your code here
// Expose to global
window['varName'] = varName;
})();
To address Crescent Fresh's comment: in order to remove global variables from the scenario entirely, the developer would need to change a number of things assumed in the question. It would look a lot more like this:
Javascript:
(function() {
var addEvent = function(element, type, method) {
if('addEventListener' in element) {
element.addEventListener(type, method, false);
} else if('attachEvent' in element) {
element.attachEvent('on' + type, method);
// If addEventListener and attachEvent are both unavailable,
// use inline events. This should never happen.
} else if('on' + type in element) {
// If a previous inline event exists, preserve it. This isn't
// tested, it may eat your baby
var oldMethod = element['on' + type],
newMethod = function(e) {
oldMethod(e);
newMethod(e);
};
} else {
element['on' + type] = method;
}
},
uploadCount = 0,
startUpload = function() {
var fil = document.getElementById("FileUpload" + uploadCount);
if(!fil || fil.value.length == 0) {
alert("Finished!");
document.forms[0].reset();
return;
}
disableAllFileInputs();
fil.disabled = false;
alert("Uploading file " + uploadCount);
document.forms[0].submit();
};
addEvent(window, 'load', function() {
var frm = document.forms[0];
frm.target = "postMe";
addEvent(frm, 'submit', function() {
startUpload();
return false;
});
});
var iframe = document.getElementById('postHere');
addEvent(iframe, 'load', function() {
uploadCount++;
if(uploadCount > 1) {
startUpload();
}
});
})();
HTML:
<iframe src="test.htm" name="postHere" id="postHere"></iframe>
You don't need an inline event handler on the <iframe>
, it will still fire on each load with this code.
Regarding the load event
Here is a test case demonstrating that you don't need an inline onload
event. This depends on referencing a file (/emptypage.php) on the same server, otherwise you should be able to just paste this into a page and run it.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>untitled</title>
</head>
<body>
<script type="text/javascript" charset="utf-8">
(function() {
var addEvent = function(element, type, method) {
if('addEventListener' in element) {
element.addEventListener(type, method, false);
} else if('attachEvent' in element) {
element.attachEvent('on' + type, method);
// If addEventListener and attachEvent are both unavailable,
// use inline events. This should never happen.
} else if('on' + type in element) {
// If a previous inline event exists, preserve it. This isn't
// tested, it may eat your baby
var oldMethod = element['on' + type],
newMethod = function(e) {
oldMethod(e);
newMethod(e);
};
} else {
element['on' + type] = method;
}
};
// Work around IE 6/7 bug where form submission targets
// a new window instead of the iframe. SO suggestion here:
// http://stackoverflow.com/q/875650
var iframe;
try {
iframe = document.createElement('<iframe name="postHere">');
} catch (e) {
iframe = document.createElement('iframe');
iframe.name = 'postHere';
}
iframe.name = 'postHere';
iframe.id = 'postHere';
iframe.src = '/emptypage.php';
addEvent(iframe, 'load', function() {
alert('iframe load');
});
document.body.appendChild(iframe);
var form = document.createElement('form');
form.target = 'postHere';
form.action = '/emptypage.php';
var submit = document.createElement('input');
submit.type = 'submit';
submit.value = 'Submit';
form.appendChild(submit);
document.body.appendChild(form);
})();
</script>
</body>
</html>
The alert fires every time I click the submit button in Safari, Firefox, IE 6, 7 and 8.
Should global variables in javascript be always avoided?
so the reason for to avoid using global variables as much as possible as stated in the previous answers. It is about easily overriding problem and troubleshooting when some global values are being overriden. From my own experience, I usually create an utility to handle sharing values. The idea is as following
//global.js
(function(){
const context = {};
function setGlobalValue(key, value) {
context[key] = value;
}
function getGlobalValue(key) {
return context[key];
}
window.setGlobalValue = setGlobalValue;
window.getGlobalValue = getGlobalValue;
}());
// app.js
function codeAddress(address) {
geocoder.geocode({ 'address': address},
function(response, status) {
if (status == 'OK')
{
var senddata = $.get('/myurl',{params}, function (data){ setGlobalValue('codeAddress', data) });
} else {
}
});
}
// get value here
console.log(getGlobalValue('codeAddress'));
by this way we can track all the global values by searching for setGlobalValue since this is the only way to set "global" value context.
Javascript avoiding global variables - can´t get how it works
It's easy to understand closures once you compare them with what the equivalent singleton using globals would be:
(full disclosure, this example is bad practice)
var i = 0;
function counter() { console.log(++i);}
counter();counter();
How to avoid global variables in JavaScript
A good technique for this is a self-executing closure:
// bob is a global variable, which you want to avoid
var bob = 1;
// By wrapping this function declaration in parentheses, then
// appending (), it gets invoked immediately. But everything
// inside it is scoped to the anonymous function!
(function () {
// sue can only be seen inside this function
var sue = 1;
// But if you want to, you can still create global variables.
// This creates a global variable called joe:
window.joe = 1;
})();
Applying this technique to your code, you could write this to have no global variables:
(function() {
var size_li = $("#myList li").size();
var x = 3;
$('#myList li:lt(' + x + ')').show();
$('.loadmore').on('click', function() {
x = (x + 2 <= size_li) ? x + 2 : size_li;
$('#myList li:lt(' + x + ')').show();
});
})();
I've Heard Global Variables Are Bad, What Alternative Solution Should I Use?
The primary reason why global variables are discouraged in javascript is because, in javascript all code share a single global namespace, also javascript has implied global variables ie. variables which are not explicitly declared in local scope are automatically added to global namespace. Relying too much on global variables can result in collisions between various scripts on the same page (read Douglas Crockford's articles).
One way to reduce global variables is to use the YUI module pattern. The basic idea is to wrap all your code in a function that returns an object which contains functions that needs to be accessed outside your module and assign the return value to a single global variable.
var FOO = (function() {
var my_var = 10; //shared variable available only inside your module
function bar() { // this function not available outside your module
alert(my_var); // this function can access my_var
}
return {
a_func: function() {
alert(my_var); // this function can access my_var
},
b_func: function() {
alert(my_var); // this function can also access my_var
}
};
})();
now to use functions in your module elsewhere, use FOO.a_func()
. This way to resolve global namespace conflicts you only need to change the name of FOO
.
How might I avoid a global mutable variable in this code?
Instead of for_each()
, I guess you need find()
.
This returns Some( found_element )
if found or None
if not found.
You can then use the Option
returned by find()
with if let
, match
, is_some()
...
if let Some(_) = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.find(|x| page_two_filter(x, url))
{
println!("There is page two.")
}
How to secure global scope variables and prevent users from accessing it via console
It's quite simple: if you have variables within your code and you want to store them safely, you have to basically drop them into self invoking anonymous function which will work like a closure.
(function() {
// just drag your whole code from your script.js and drop it here
})();
Read more at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Related Topics
How to Determine the Number of Days in a Month with JavaScript
Add Property to an Array of Objects
When a 'Blur' Event Occurs, How to Find Out Which Element Focus Went *To*
JavaScript Es6 Computational/Time Complexity of Collections
Why Does JavaScript Replace Only First Instance When Using Replace
How to Execute a Function When Page Has Fully Loaded
Function in JavaScript That Can Be Called Only Once
How to Access a JavaScript Variable Using a String That Contains the Name of the Variable
How to View Events Fired on an Element in Chrome Devtools
How to Initialize an Array's Length in JavaScript
How to Raw Url Encode/Decode in JavaScript and Ruby to Get the Same Values in Both
Escaping </Script> Tag Inside JavaScript
How to Replace All Dots in a String Using JavaScript
Angularjs Ng-Click Stoppropagation
How to Get the Title of HTML Page with JavaScript
Converting Milliseconds to a Date (Jquery/Javascript)