jlrdw's avatar
Level 75

Seeing how you folks would iterate returned JSON

WIth data like this:

[
    {
        "id": 122,
        "lastname": "Ross"
    },
    {
        "id": 123,
        "lastname": "Smith"
    },
    {
        "id": 124,
        "lastname": "White"
    }
] 

For years I looped like this:

    for (var i = 0; i < data['employee'].length; i++) {
        var item = data['employee'][i];
        div.innerHTML += "---" + item.lastname + "<br>";
    }

But recently ran across the javascript hasOwnProperty(key) method. Or perhaps property.

So this also works:

    for (var key in data['employee']) {
        if (data['employee'].hasOwnProperty(key)) {
            div.innerHTML += "---" + data['employee'][key].lastname + "<br>";
        }
    }

Both work. Which if either is the best, and do you have even a better way. Ignore the div.innerHTML part, just testing this out, real app I fill some fields with data.

0 likes
15 replies
jeffallen's avatar

Another way would be like this.

        somedata.forEach(item => {
            div.innerHTML += "---" + item.lastname + "<br>";
        });

The hasOwnProperty is new to me to. I don't know which is the best method.

2 likes
Ben Taylor's avatar

div.innerHTML = data.employee.reduce((carry, item) => carry += `---${item.lastname}<br>`, '')
2 likes
Tray2's avatar
Tray2
Best Answer
Level 73

I usually go for the forEach approach, unless I need to know which iteration I'm on.

2 likes
jlrdw's avatar
Level 75

I will probably stick with my original technique for now. Because like you said , you might want to get one particular value sometimes. @Tray2

Thank you everyone for your answers.

@ben taylor I believe reduce has a problem with null values but I will check it out again.

@jeffallen That method you showed is pretty neat. I am playing catchup on some of the new Javascript shortcuts.

1 like
Ben Taylor's avatar

@jlrdw just filter out the null values

.filter(item => item?.lastname)
2 likes
Ben Taylor's avatar

@Tray2 you can access index in for each.

.forEach((item, index) => ...)
3 likes
jlrdw's avatar
Level 75

@Ben Taylor when I tried

div.innerHTML = data.employee.reduce((carry, item) => carry += `---${item.lastname}<br>`, '')

Uncaught (in promise) TypeError: data.employee is undefined

I have never used reduce. Also ide shows item as unused.

Here is the exact test data:

var employee = [
        {
            "id": 122,
            "lastname": "Ross"
        },
        {
            "id": 123,
            "lastname": "Smith"
        },
        {
            "id": 124,
            "lastname": "White"
        }
    ];

    div.innerHTML = data.employee.reduce((carry, item) => carry += `---${data.lastname}<br>`, '')

Is carry a function of reduce?

1 like
Ben Taylor's avatar

@jlrdw oh, sorry. Had to guess what your structure was. Just do employee.reduce

2 likes
jlrdw's avatar
Level 75

@Ben Taylor got it:

   function runMulti() {
        var employee = [
            {
                "id": 122,
                "lastname": "Ross"
            },
            {
                "id": 123,
                "lastname": "Smith"
            },
            {
                "id": 124,
                "lastname": "White"
            }
        ];
        var div = document.getElementById('msg');
        div.innerHTML = employee.reduce((carry, data) => carry += `---${data.lastname}<br>`, '')

    }
2 likes
Ben Taylor's avatar

@jlrdw carry is just a variable that you are building and will be eventually returned by the reduce function. In this case, it is a string. But it could be anything, like an object etc.

You can call it anything you like. I just called it carry because that is how it is usually referenced. In practice, I might use something more semantic.

2 likes
jlrdw's avatar
Level 75

@Ben Taylor if I take out a lastname, I get error: Uncaught SyntaxError: expected expression, got '}'

But it works if I replace with null:

errors out:

        var employee = [
            {
                "id": 122,
                "lastname": "Ross"
            },
            {
                "id": 123,
                "lastname": 
            },
            {
                "id": 124,
                "lastname": "White"
            }
        ];

Works

        var employee = [
            {
                "id": 122,
                "lastname": "Ross"
            },
            {
                "id": 123,
                "lastname": null 
            },
            {
                "id": 124,
                "lastname": "White"
            }
        ];
        var div = document.getElementById('msg');
        div.innerHTML = employee.reduce((carry, data) => carry += `---${data.lastname}<br>`, '')

But I will experiment with reduce more. Thanks to letting me know about it.

2 likes
Ben Taylor's avatar

@jlrdw it is erroring out because the object is misformed. You are removing the lastname value, but leaving the key. You have to remove the key too, or use null, undefined or '' for the value

2 likes
jlrdw's avatar
Level 75

@Ben Taylor got it. Is there a way to use a ternary here.

Tomorrow I will test a response json from laravel and have a last name empty in the database (or some field) to see how it works.

Edit:

Test with database data, results, just some old test data I use:

---Belle
---

The second dog was Dale Evans, I allowed null on name and deleted just the name:

div.innerHTML = data['dog'].reduce((carry, item) => carry += `---${item.dogname}<br>`, '')

Still don't get what the end (, '') does.

1 like
Ben Taylor's avatar

@jlrdw sure is.

div.innerHTML = employee.reduce((carry, data) => carry += data.lastname ? `---${data.lastname}<br>` : '', '')

2 likes
Ben Taylor's avatar

@jlrdw For the end bit (, '') think of the part after the comma as instantiating the carry variable with whatever value you like. In your case, we are building the inner html string and so I set carry to be an empty string.

But you could set it to a number or object or array. Anything you like

[1, 4, 6].reduce((sum, n) => sum+= n, 0)

I have used a single line short arrow function, but you can do more inside the callback function if you want. Just make sure to return the carry at the end

div.innerHTML = employee.reduce((carry, data) => {
	... do whatever you need to do...
	return carry;
}, '')

2 likes

Please or to participate in this conversation.