patternjavascriptMinor
Store variables function-wide and access them in an anonymous function
Viewed 0 times
anonymousfunctionwidestorevariablesandthemaccess
Problem
At the moment, I have this code:
So
That's cleaner in my opinion and also faster (okay, a few nanoseconds) because of the scope chains hierarchy (Google Tech Talk: Speed Up Your JavaScript is a good introduction).
I thought of adding a property to the function (as I learnt here) but I don't have access to
The next idea I had was to use HTML 5
(The default value for
(function() {
var lastSelectedIndex = -1;
function onSelTypeSelected() {
// #selType is a tag
// var selType = document.getElementById("selType");
var selType = this;
// finished(onSuccess, onError)
loader.finished(function(data) {
lastSelectedIndex = selType.selectedIndex;
}, function(err) {
selType.selectedIndex = lastSelectedIndex;
});
}
})();So
lastSelectedIndex is not in the global context, however I want to put it into eventListener()'s context. inside eventListener(), so you can't access it in the outer anonymous function.That's cleaner in my opinion and also faster (okay, a few nanoseconds) because of the scope chains hierarchy (Google Tech Talk: Speed Up Your JavaScript is a good introduction).
I thought of adding a property to the function (as I learnt here) but I don't have access to
eventListener() in the anonymous functions.The next idea I had was to use HTML 5
data-* attributes:function onSelTypeSelected() {
// #selType is a tag
// var selType = document.getElementById("selType");
var selType = this;
// finished accepts two arguments: onSuccess and onError
loader.finished(function(data) {
selType.setAttribute("data-lastIndex", selType.selectedIndex);
}, function(err) {
selType.selectedIndex = selType.getAttribute("data-lastIndex");
});
}(The default value for
data-lastIndex will be set in the HTML Markup)Solution
lastSelectedIndex is already visible from eventListener. It is in fact visible from everywhere inside the immediately invoked anonymous function.Try putting
console.log("lastSelectedIndex is", lastSelectedIndex); in there and you'll see.This is due to the concept of closures which in technical-ish terms means that when a variable is not found inside a function's context, it looks in the parent context (the context the function was in when created) and so on all the way up to the window object. In plain-english terms this means that you should forget all your Java/C#/Php training and the variables visible inside a function are exactly those that you intuitively think should be.
That being said, there is going to be only one instance of
lastSelectIndex for this block of code, so if the eventlistener is ever attached to more than a single element all instances of the listener will be referencing the same lastSelectIndex.There are plenty of ways to skin this cat and you really did not give enough details on what your trying to achieve to give advice on best practices but let me try to give some advice anyways
- DO the simplest thing that can possibly work first
- DON'T name your functions after how they're used (eventlistner)
- DO name your functions after what they do
- DON'T use data- attributes directly. Use a library like jquery, at the very least use element.dataset to retrieve them, though keep in mind the data api is not available in all browsers (which libraries handle for you)
-
CONSIDER having everything set up in response to a user action that triggers it so in pseudocode, the following would be all inline (and with js can be written gracefully and very compact).
when the user changes the option
memoize the previous value
query the server
on success continue
on error restore the previous value
-
Finally, if you do this more than a few times, CONSIDER coming up with an abstraction (possibly a custom control) for this pattern so you don't have to do it every time
Context
StackExchange Code Review Q#12246, answer score: 7
Revisions (0)
No revisions yet.