0

Here's my html:

<div id='test'>
<input name="M1" size="3" value="1">
<input name="M2" size="3" value="2">
<input name="M3" size="3" value="3">
</div>

here's my javascript:

var test = document.getElementById('test');
var arr = test.querySelectorAll('input');
var arr2 =[];
for (i in arr) {arr2.push(arr[i].value) ;}

this my final array arr2:

["1","2","3",undefined,undefined,undefined,undefined,undefined,undefined]

the point is that arr.length is 3 but arr2.length is 9, six elements are undefined. Could you please explain why and better way to achieve it?

2
  • 1
    for (i in arr) { console.log(i); arr2.push( arr[i].value ); }I suspect that this may make it clearer. Incidentally: let arr2 = Array.from( test.querySelectorAll('input') ).map( (inputEl) => inputEl.value ) would be a less complex way of achieving your (apparent) desired end result. Also: see the for...in documentation on MDN. Commented Jun 26, 2020 at 8:31
  • try for (const i of arr) { arr2.push(i.value) } instead, in is not a collection iterator, but of is.. Commented Jun 26, 2020 at 8:41

2 Answers 2

1

A for..in loop in JavaScript loops over the enumerable properties of an object. Here, you are trying to use for..in on arr, which is not an array, it's a NodeList (as that's the return value of querySelectorAll).

A NodeList has the enumerable properties of:

0
1
2
length
item
entries
forEach
keys
values

As you can see, it doesn't just contain the indexes of arr, but rather all the enumerable properties. This means your for..in loop will go through each of these. That's why you get undefined in your array as arr['length'].value for example will give you undefined. For looping a NodeList, you can use a regular for loop, a for..of loop or NodeList.prototype.forEach():

const test = document.getElementById('test');
const nodes = test.querySelectorAll('input');
const arr2 = [];
for (const input of nodes) {
  arr2.push(input.value);
}
console.log(arr2);
<div id='test'>
  <input name="M1" size="3" value="1">
  <input name="M2" size="3" value="2">
  <input name="M3" size="3" value="3">
</div>

As a side note, if you're trying to build an array of values from your inputs, you can use Array.from() with a mapping function on your NodeList like so:

const test = document.getElementById('test');
const nodes = test.querySelectorAll('input');
const arr2 = Array.from(nodes, ({value}) => value);
console.log(arr2);
<div id='test'>
  <input name="M1" size="3" value="1">
  <input name="M2" size="3" value="2">
  <input name="M3" size="3" value="3">
</div>

Sign up to request clarification or add additional context in comments.

Comments

0

forEach should work:

var test = document.getElementById('test');
var arrInput = test.querySelectorAll('input');
var arr2 = [];

arrInput.forEach(element => {
    arr2.push(element.value);
})
console.log(arr2)
<body>
    <div id='test'>
        <input name="M1" size="3" value="1">
        <input name="M2" size="3" value="2">
        <input name="M3" size="3" value="3">
    </div>
</body>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.