How to Avoid Global Variables in JavaScript

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



Leave a reply



Submit