In this code
if (direction === 'up') {
for (key in elements) {
if (elements.hasOwnProperty(key)) {
elements[key].style.opacity = statics.elapsed / max_time;
}
}
} else if (direction === 'down') {
for (key in elements) {
if (elements.hasOwnProperty(key)) {
elements[key].style.opacity = (max_time - statics.elapsed) / max_time;
}
}
}
I’d like to abstract out this common idiom:
for (key in elements) {
if (elements.hasOwnProperty(key)) {
// function using elements[key] and outside parameters
}
}
so I could simply write
manyElements(element, function () {
});
How would I write the function prototype as starting point. My guess would be.
function manyElements (elements, the_function) {
for (key in elements) {
if (elements.hasOwnProperty(key)) {
the_function();
}
}
}
but I need access to outside parameters, what is the best way to pass these in? Is this a good idea in general, to abstract out this code?
It seems like I would have to pass each parameter in individually defeating the purpose of making a general purpose function.
I don’t prefer not to use an outside library, except for correlation. Per answer here is lodash implementation:
Snippet 1
function forEach(collection, callback, thisArg) {
if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
if (callback(collection[index], index, collection) === false) {
break;
}
}
} else {
each(collection, callback, thisArg);
}
return collection;
}
Snippet 2
var each = createIterator(eachIteratorOptions);
Snippet 3
function createIterator() {
var data = {
'arrayLoop': '',
'bottom': '',
'hasDontEnumBug': hasDontEnumBug,
'isKeysFast': isKeysFast,
'objectLoop': '',
'nonEnumArgs': nonEnumArgs,
'noCharByIndex': noCharByIndex,
'shadowed': shadowed,
'top': '',
'useHas': true
};
// merge options into a template data object
for (var object, index = 0; object = arguments[index]; index++) {
for (var key in object) {
data[key] = object[key];
}
}
var args = data.args;
data.firstArg = /^[^,]+/.exec(args)[0];
// create the function factory
var factory = Function(
'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
'nativeKeys, propertyIsEnumerable',
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
);
// return the compiled function
return factory(
createCallback, hasOwnProperty, isArguments, isString, objectTypes,
nativeKeys, propertyIsEnumerable
);
}
If you do this several times in your code, there is nothing wrong with abstracting it out. You almost have the answer already too: Just pass the parameters you need back into the function that you passed into
manyElements. I’d go for passing both the key and the value, since you might need the key in some places (e.g. to change the assignment to something else).Usage would be like this:
I wouldn’t call the function manyElements though, because that name doesn’t really explain what the function does. Something like
forEachPropertymight be more self-documenting.