68

Let's say I have

myArray = ['item1', 'item2']

I tried

for (var item in myArray) {console.log(item)}

It prints 0 1

What I wish is to have item1 item2

Is there any other syntax that works without using

for (var i = 0; i < myArray.length; i++)
borisdiakur
  • 10,387
  • 7
  • 68
  • 100
user310291
  • 36,946
  • 82
  • 271
  • 487
  • 2
    What are you trying to achieve? Why not use a normal `for` loop or the `.forEach()` function? – Pointy Apr 01 '15 at 18:09
  • Writing it as `for (var propertyName in myArray)` would make the issue with the observed behavior more clear. In any case, for a higher-order construct, see [`Array.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) but note it has a number of implications that make it *different* from either of the above forms. (The differences between the forms are covered by *many* duplicates.) – user2864740 Apr 01 '15 at 18:10
  • 1
    @Pointy because the normal loop is uselessly complicated : why do I need to calculate the size of an array whereas the interpreter can know it. forEach() ? Well that's my question is there any other syntax so I'll try thanks. – user310291 Apr 01 '15 at 18:11
  • Looking at the [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array), there's a bunch of methods to do this. – Teemu Apr 01 '15 at 18:13
  • 7
    @user310291 `length` *doesn't* "calculate" the size of the array. The length of an array is an intrinsic value of the Array type. – user2864740 Apr 01 '15 at 18:13
  • 3
    Even if `length` was calculated, you could just cache it: `for (var i = 0, length = arr.length; i < length; i++)` – Felix Kling Apr 01 '15 at 18:23

8 Answers8

137

You can use Array.forEach

var myArray = ['1','2',3,4]

myArray.forEach(function(value){
  console.log(value);
});
makenova
  • 3,579
  • 3
  • 17
  • 20
  • 3
    Still uses array length under the hood. But it could simply be that the OP doesn't want to refer to the length explicitly. – canon Apr 01 '15 at 18:18
  • @canon, you literally suggested `forEach()` (after I answered here) in the comment for another answer. – makenova Apr 01 '15 at 18:22
  • 1
    Note that if you add `myArray[123] = '6'` you will get a totally different result using `Array.forEach` than when using `for (var i = 0; i < myArray.length; i++)` syntax. – borisdiakur Apr 01 '15 at 18:48
  • Oh, [this comment](http://stackoverflow.com/questions/29397746/in-nodejs-is-there-a-way-to-loop-through-an-array-without-using-array-size/29397769#comment46971797_29397847). I originally thought you meant [this one](http://stackoverflow.com/questions/29397746/in-nodejs-is-there-a-way-to-loop-through-an-array-without-using-array-size/29397769#comment46971853_29397769). That was mainly because, if reaching for an array method at all, `map()` wouldn't be the appropriate analog. – canon Apr 01 '15 at 18:51
73

What you probably want is for...of, a relatively new construct built for the express purpose of enumerating the values of iterable objects:

let myArray = ["a","b","c","d"];
for (let item of myArray) {
  console.log(item);
}

... as distinct from for...in, which enumerates property names (presumably1 numeric indices in the case of arrays). Your loop displayed unexpected results because you didn't use the property names to get the corresponding values via bracket notation... but you could have:

let myArray = ["a","b","c","d"];
for (let key in myArray) {
  let value =  myArray[key]; // get the value by key
  console.log("key: %o, value: %o", key, value);
}

1 Unfortunately, someone may have added enumerable properties to the array or its prototype chain which are not numeric indices... or they may have assigned an index leaving unassigned indices in the interim range. The issues are explained pretty well here. The main takeaway is that it's best to loop explicitly from 0 to array.length - 1 rather than using for...in.

So, this is not (as I'd originally thought) an academic question, i.e.:

Without regard for practicality, is it possible to avoid length when iterating over an array?

According to your comment (emphasis mine):

[...] why do I need to calculate the size of an array whereas the interpreter can know it.

You have a misguided aversion to Array.length. It's not calculated on the fly; it's updated whenever the length of the array changes. You're not going to see performance gains by avoiding it (apart from caching the array length rather than accessing the property):

loop test

Now, even if you did get some marginal performance increase, I doubt it would be enough to justify the risk of dealing with the aforementioned issues.

canon
  • 40,609
  • 10
  • 73
  • 97
6

To print 'item1' , 'item2', this code would work.

var myarray = ['hello', ' hello again'];

for (var item in myarray) {
    console.log(myarray[item])
}
4

In ES5 there is no efficient way to iterate over a sparse array without using the length property. In ES6 you can use for...of. Take this examples:

'use strict';

var arr = ['one', 'two', undefined, 3, 4],
    output;

arr[6] = 'five';

output = '';
arr.forEach(function (val) {
    output += val + ' ';
});
console.log(output);

output = '';
for (var i = 0; i < arr.length; i++) {
    output += arr[i] + ' ';
}
console.log(output);

output = '';
for (var val of arr) {
    output += val + ' ';
};
console.log(output);
<!-- results pane console output; see http://meta.stackexchange.com/a/242491 -->
<script src="//gh-canon.github.io/stack-snippet-console/console.min.js"></script>

All array methods which you can use to iterate safely over dense arrays use the length property of an object created by calling ToObject internaly. See for instance the algorithm used in the forEach method: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18 However in es6, you can use for...of safely for iterating over sparse arrays.

See also Are Javascript arrays sparse?.

borisdiakur
  • 10,387
  • 7
  • 68
  • 100
3

This is the natural javascript option

var myArray = ['1','2',3,4]

myArray.forEach(function(value){
  console.log(value);
});

However it won't work if you're using await inside the forEach loop because forEach is not asynchronous. you'll be forced to use the second answer or some other equivalent:

let myArray = ["a","b","c","d"];
for (let item of myArray) {
  console.log(item);
}

Or you could create an asyncForEach explained here:

https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404

Itamar Lev
  • 84
  • 5
1

Use Iterators...

var myarray = ['hello', ' hello again'];
processArray(myarray[Symbol.iterator](), () => {
    console.log('all done')
})
function processArray(iter, cb) {
    var curr = iter.next()
    if(curr.done)
        return cb()
    console.log(curr.value)
    processArray(iter, cb)
}

More in depth overview: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

buycanna.io
  • 1,166
  • 16
  • 18
1
    var count=0;
    let myArray = '{"1":"a","2":"b","3":"c","4":"d"}'
    var data = JSON.parse(myArray);
    for (let key in data) {
      let value =  data[key]; // get the value by key
      console.log("key: , value:", key, value);
      count = count + 1;
    }
   console.log("size:",count);
Mukesh Kashyap
  • 701
  • 7
  • 9
-1

Use the built-in Javascript function called map. .map() will do the exact thing you're looking for!

user1789573
  • 515
  • 2
  • 8
  • 23
  • 3
    I would think `forEach()` would be the more direct match than a function which creates a new array... – canon Apr 01 '15 at 18:14