Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have the following (example) array of objects:

var theArray = [
    {theId:'1', num: 34},
    {theId:'2', num: 23},
    {theId:'5', num: 26}
];

and this function, which works fine to loop through them:

function printValues() {
    var i = 0;
    for(i; i<theArray.length; i++) {
        var obj = theArray[i];
        document.getElementById('result1').innerHTML += obj.theId + ' = ' + obj.num + '<br>';
    }
}

However, if I want to abstract this function for use on similar arrays by using function variables to access objects within them, like this:

function printValuesVar(arr,elemId,arrId,arrNum) {
    var i = 0;
    for(i; i<arr.length; i++) {
        var obj = arr[i];
        document.getElementById(elemId).innerHTML += obj.arrId + ' = ' + obj.arrNum + '<br>';
    }
}

'undefined' is the result when called as below (as I'd kind of expect since 'arrId' is not an object name):

printValuesVar(theArray,'result2','theId','num');

How can I use the values passed to the function's variables to access values of objects within the array by name?


rewritten following advice against antipatterns:

function printValuesVar(arr,elemId,arrId,arrNum) {
    var i = 0;
    var content = '';
    for(i; i<arr.length; i+=1) {
        var obj = arr[i];
        content += obj[arrId] + ' = ' + obj[arrNum] + '<br>';
    }
    document.getElementById(elemId).innerHTML = content;
}
share|improve this question
2  
Your code contains several anti-patterns: (1) You query via getElementById inside a loop - there is no need for that. Just get the reference beforehand; (2) you assign to innerHTML inside a loop - again no need for that. You want to keep DOM manipulation at a minimum. Construct the HTML string with the loop, and then assign to innerHTML after the loop. – Šime Vidas Jan 8 '12 at 15:03
+1 for the guidance - since this was a learning process, I rewrote the function (added, above) to incorporate your suggestions, before looking at your examples below. Now I'll try the advice from PointedEars. – Dave Everitt Jan 8 '12 at 15:45

2 Answers

up vote 2 down vote accepted

Because you are loking for key "arrId", not the key stored in variable arrId

document.getElementById(elemId).innerHTML += obj[arrId] + ' = ' + obj[arrNum] + '<br>';
share|improve this answer
Nice simple answer, got things working right away. – Dave Everitt Jan 8 '12 at 15:39

Try this:

function printValuesVar( arr, elemId, arrId, arrNum ) {
    var content = '';

    arr.forEach( function ( arrElem ) {
        content += arrElem[ arrId ] + ' = ' + arrElem[ arrNum ] + '<br>';
    });

    document.getElementById( elemId ).innerHTML = content;
}

Or a bit more advanced:

function printValuesVar( arr, elemId, arrId, arrNum ) {
    document.getElementById( elemId ).innerHTML = arr.map( function ( arrElem ) {
        return arrElem[ arrId ] + ' = ' + arrElem[ arrNum ];
    }).join( '<br>' );
}

ES5-shim for shitty browsers

share|improve this answer
2  
Instead of consecutive string concatenation (+=) in the loop, consider pushing to an Array that you join later. A simple for loop is likely more efficient and obviously more compatible than either of forEach or map. – PointedEars Jan 8 '12 at 15:18
1  
@PointedEars My second example uses join() instead of += string concatenation. The array iteration methods are not implemented in IE8, but you can easily shim that browser. As for efficiency, it's true that for is slightly faster than the array methods, but that doesn't mean it's preferred. – Šime Vidas Jan 8 '12 at 15:35
1  
var content = []; for (var i = 0, len = arr.length; i < len; ++i) { var arrElem = arr[i]; content.push(arrElem[arrId] + ' = ' + arrElem[arrNum]); } ….innerHTML = content.join("<br>"); is likely a lot faster and obviously more compatible than consecutive function calls from forEach with concatenation. As for the Crockford reference, that fallacy is called "argument from authority", or ipse dixit. – PointedEars Jan 8 '12 at 15:57
1  
@PointedEars No, it's not an argument from authority. An argument from authority would be if I said: "This is better because Crockford says so.". I'm not doing that. My link points to the part of the video where Crockford explains why array iteration methods are preferred over for loops. Quote: "The speed difference is not significant and the benefit in the way you can express things in code is really profound.". This is the argument I'm making. – Šime Vidas Jan 8 '12 at 16:16
1  
@DaveEveritt There is no arr.prototype.forEach. Crockford (et al.) are defining Array.prototype.forEach when it is not defined, so that the Array instance referred to by arr can inherit that method through the prototype chain. You can do that, but then you need to take precautions if you want to use for..in iteration with Array instances (which is handy with sparse arrays), because the new user-defined property is enumerable as well. (The alternative was Object.defineProperty(), but if you had that you already had Array.prototype.forEach etc.) – PointedEars Jan 8 '12 at 16:18
show 13 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.