javascript for-in loop in an Array - javascript

If the code is this:
arr=Array("a","b","c");
for(i in arr);
{
alert(i);
}
there is no any alert,but if it is this:
arr=new Array("a","b","c");
for(i in arr)
{
alert(i);//alerts 0,1,2
}
What is the reason?

Array is a constructor. To create a new object you should be using the new operator to create the object, which the constructor is then bound to and run against. In this case though, it actually should work either way, your issue is most likely related to the semicolons next to your for-loop, as noted in the comments.
As an aside, for creating a new array its generally advised to use the simpler notation
var arr = ["a","b","c"];
Its also questionable to use a for-in loop with an array in javascript, as that will hit any additional properties defined on the array. (so if you said arr.x = 2 it would also iterate over x.
Better to use the iterative form
var i =0, length =arr.length;
for ( ;i<length; i++) {
alert(arr[i]);
}

The reason you're getting different results is that you were using incorrect syntax for your for/in loops.
for(i in arr);
{
alert(i);
}
should not have the first semicolon.
Also note that a nicer way to iterate over an array would be:
arr.forEach(function(value, index){
alert(value); // or alert(index);
});
As bfavaretto has mentioned.
Invoking the Array function without the new keyword will Create and return a new Array object in the same way it would had you used the new keyword.
So these two will alert the same things:
arr1 = new Array("a","b","c");
arr2 = Array("a","b","c");

Related

loop over array of numbers using for...in shows unexpected results

I have a js script.
I want to alert each number in an array.
But it always shows from 0 instead of the actual number.
var indexes = [1,2]
arrayOfDigits = indexes.map(Number);
var i = 0;
for (i in arrayOfDigits)
{
alert(i);
}
It alerts 0 then 1.
But I want 1 then 2
Quite a number of issues with your code, let's go through them:
for...in is meant to be used to iterate over own, enumerable properties of objects, not for iterating over array members. You need for...of for this instead.
Don't use var any more unless you explicitly know and need its special scoping behaviour. Use const instead, or let in case you need to assign to it more than once.
Your code has an undeclared variable which automatically makes it a global variable. It is common consensus to not pollute the global namespace. Always declare any variables before use.
Don't initialize or even declare the loop variable of a for...of loop outside of the loop. This is done right in the for (const digit of arrayOfDigits) construct itself.
Don't use alert for debugging; use console.log instead.
Here's the working, corrected code:
const indexes = [1, 2]
const arrayOfDigits = indexes.map(Number);
for (const digit of arrayOfDigits) {
console.log(digit);
}
If you are keen to have output as 1 and 2 use this instaed,
var indexes = [1,2]
arrayOfDigits = indexes.map(Number);
for (var i = 0;i<arrayOfDigits.length;i++)
{
alert(arrayOfDigits[i]);
}
The for-in loop loops over all the property of an object (including those from its prototype chain). All you want is to iterate over it. For that you can use a for-of loop (which loops over elements), or you could use Array#forEach which does just that but can help you have access to other stuff like the index:
indexes.forEach(number => {
alert(number);
});

Array.from() vs spread syntax

Is there some difference between using Array.from(document.querySelectorAll('div')) or [...document.querySelectorAll('div')]?
Here is a example:
let spreadDivArray = [...document.querySelectorAll('div')];
console.log(spreadDivArray);
let divArrayFrom = Array.from(document.querySelectorAll('div'));
console.log(divArrayFrom);
The console.log() will log the same result.
Is there any performance difference?
Spread element (it's not an operator) works only with objects that are iterable (i.e. implement the ##iterator method). Array.from() works also on array-like objects (i.e. objects that have the length property and indexed elements) which are not iterable. See this example:
const arrayLikeObject = { 0: 'a', 1: 'b', length: 2 };
// This logs ['a', 'b']
console.log(Array.from(arrayLikeObject));
// This throws TypeError: arrayLikeObject[Symbol.iterator] is not a function
console.log([...arrayLikeObject]);
Also, if you just want to convert something to array, I think it's better to use Array.from() because it's more readable. Spread elements are useful for example when you want to concatenate multiple arrays (['a', 'b', ...someArray, ...someOtherArray]).
Well, Array.from is a static method, i.e., a function whereas the spread syntax is part of the array literal syntax. You can pass functions around like data, you can invoke them once, several times or not at all. This isn't possible with the spread syntax, which is static in this regard.
Another difference, which #nils has already pointed out, is that Array.from also works with array-like objects, which don't implement the iterable protocol. spread on the other hand requires iterables.
The difference is that spread allows an array to be expanded. Whereas from() creates a new array. .from() doesn't expand upon anything, it creates a new array based on the data provided; the spread operator on the other hand can expand an array with new properties.
If the input is iterable they do the exact same thing.
However, based on the benchmarks, the spread operator seems to perform better for a Set.
https://jsben.ch/5lKjg
let set = new Set();
for (let i = 0; i < 10000; i++) {
set.add(Math.random());
}
let tArrayFrom = window.performance.now()
let arr = Array.from(set)
console.log("Array.from():", window.performance.now() - tArrayFrom + "ms")
// slightly faster in most of the runs:
let tSpread = window.performance.now()
let arr2 = [...set];
console.log("Spread syntax:", window.performance.now() - tSpread + "ms")
Using Babel is a good way to see what's happening internally.
Heads up, though. Make sure latest is selected in Babel, as the default is wrong.
Using your example above, this is the output.
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var spreadDivArray = [].concat(_toConsumableArray(document.querySelectorAll('div')));
console.log(spreadDivArray);
var divArrayFrom = Array.from(document.querySelectorAll('div'));
console.log(divArrayFrom);
I need to clarify everyone's answers:
The ...foo syntax just spreads (expands) all array values as if they were separate, comma-separated arguments. It does a shallow spread. Any primities (numbers, strings etc) are COPIED and any complex values (objects) are instead REFERENCED.
The [] around it is what CREATES a new array.
So [...foo] will create a new array and populate it by doing a SHALLOW COPY spreading of all array elements as if they were array constructor arguments which in turn takes all those copied elements and puts them in the new array.
Whereas Array.from(foo) will CREATE a new array using the input variable, but is A LOT FASTER because it ONLY creates a SHALLOW COPY (this is FASTER). So it takes the exact input and just puts every variable/reference into the new array.
Use Array.from().

OK to append a property to a javascript array? [duplicate]

Arrays have a "length" property by default.
Can I add custom properties to them?
Without having to make them objects.
var arr = [1,2,3,4,5];
arr.prop = 'value';
Arrays are already objects in JavaScript -- they just have some extra features and special literal syntax.
As other answers state, it's perfectly possible, because arrays in JavaScript are just objects. However, there is still the a question of whether it's a good idea or not.
That's a "coding style" question, so it's hard to say objectively, but Douglas Crockford doesn't have a problem with it (at least in some cases). In JavaScript: The Good Parts, he actually uses the example of adding a "total" method to an array.
Because an array is really an object, we can add methods directly to an individual array:
// Give the data array a total function
data.total = function () {
return this.reduce(add, 0);
};
total = data.total(); // total is 108
Since the string 'total' is not an integer, adding a total property to an array does not change its length.
(p62, Crockford's "JavaScript The Good Parts", found on Google Books)
However, it is worth mentioning that these extra properties are not included in JSON serialisation, and would be thrown away if you do anything like arr = arr.slice(1);.
If you meant to hide it in an Array, etc. (at least that's what I was looking for):
Object.defineProperty( targ, "myVal", { enumerable: false, writable: true } );
Then the array doesn't add it to length, so it's a property, not a value I guess you could say.
Then if you want to see the keys in an object for instance, Object.keys won't see it, but Reflect.ownKeys() will.
The Reflect version of defineProperty will return success or fail, while Object's returns the object passed.
Remember Reflect.preventExtensions() will (like it says) stop you or others from extending them.
Arrays are objects and therefore you can add your own properties to them:
var arr = [1, 2, 3];
arr.foo = 'bar';
Extending from other answers, here are the following ways of iterating over the array, excluding custom properties.
Using a standard for loop
for (let i = 0; i < arr_length; i++)
console.log(arr[i]);
or if not using ES6:
for (var i = 0; i < arr.length; i++)
console.log(arr[i]);
Using the for ... of loop (ES6+)
for (let el of arr)
console.log(el)
Using Array.prototype.forEach (ES6+)
arr.forEach(el => console.log(el));
or
arr.forEach(function(el) {
console.log(el);
});
Iterating over the array, including all properties (e.g., custom properties, length):
for (let prop in arr)
console.log(prop);
Or if not using ES6:
for (var prop in arr)
console.log(prop);
Yes. You can add them to the object by just declaring them and you can also extend Array using Array.prototype
var j = new Array();
j.yourprop = "foo";

Add a property to a JavaScript array

Arrays have a "length" property by default.
Can I add custom properties to them?
Without having to make them objects.
var arr = [1,2,3,4,5];
arr.prop = 'value';
Arrays are already objects in JavaScript -- they just have some extra features and special literal syntax.
As other answers state, it's perfectly possible, because arrays in JavaScript are just objects. However, there is still the a question of whether it's a good idea or not.
That's a "coding style" question, so it's hard to say objectively, but Douglas Crockford doesn't have a problem with it (at least in some cases). In JavaScript: The Good Parts, he actually uses the example of adding a "total" method to an array.
Because an array is really an object, we can add methods directly to an individual array:
// Give the data array a total function
data.total = function () {
return this.reduce(add, 0);
};
total = data.total(); // total is 108
Since the string 'total' is not an integer, adding a total property to an array does not change its length.
(p62, Crockford's "JavaScript The Good Parts", found on Google Books)
However, it is worth mentioning that these extra properties are not included in JSON serialisation, and would be thrown away if you do anything like arr = arr.slice(1);.
If you meant to hide it in an Array, etc. (at least that's what I was looking for):
Object.defineProperty( targ, "myVal", { enumerable: false, writable: true } );
Then the array doesn't add it to length, so it's a property, not a value I guess you could say.
Then if you want to see the keys in an object for instance, Object.keys won't see it, but Reflect.ownKeys() will.
The Reflect version of defineProperty will return success or fail, while Object's returns the object passed.
Remember Reflect.preventExtensions() will (like it says) stop you or others from extending them.
Arrays are objects and therefore you can add your own properties to them:
var arr = [1, 2, 3];
arr.foo = 'bar';
Extending from other answers, here are the following ways of iterating over the array, excluding custom properties.
Using a standard for loop
for (let i = 0; i < arr_length; i++)
console.log(arr[i]);
or if not using ES6:
for (var i = 0; i < arr.length; i++)
console.log(arr[i]);
Using the for ... of loop (ES6+)
for (let el of arr)
console.log(el)
Using Array.prototype.forEach (ES6+)
arr.forEach(el => console.log(el));
or
arr.forEach(function(el) {
console.log(el);
});
Iterating over the array, including all properties (e.g., custom properties, length):
for (let prop in arr)
console.log(prop);
Or if not using ES6:
for (var prop in arr)
console.log(prop);
Yes. You can add them to the object by just declaring them and you can also extend Array using Array.prototype
var j = new Array();
j.yourprop = "foo";

How to loop over an Array with JavaScript?

I have a string that has data separated by a pipe character (|).
Example
var somestring = "data1|data2|data3";
var separated = somestring.split("|");
I know how to use the split() to separate each data.
However, I don't know how many pipes there will be in the resulting Array.
In jQuery or JavaScript, how do I loop over the array returned?
In jQuery or JavaScript, how do I loop through each separated variable?
You basically just need to iterate over the resulting Array.
jQuery
$.each loop
This method is easy to work with, and benefits in the variables used being encapsulated.
$.each(separated, function(index, chunk) {
// `chunk` is each member of the array.
});
jsFiddle.
Of course, jQuery is JavaScript so any of the below methods will also work.
JavaScript
for loop
This is the recommended way.
for (var i = 0, length = separated.length; i < length; i++) {
var chunk = separated[i];
// `chunk` is each member of the array.
}
jsFiddle.
You'll notice too the length property is cached so it is not looked up on each iteration. Some browsers already optimise for this, however IE appears to still benefit from it cached. It only takes 5 seconds to do, so you may as well keep IE users happy too.
You may want to define i and chunk outside of the for loop, because JavaScript has no block scope (unless you're using let), and those variables will exist before (declaration hoisted) and after (no block scope).
for ( in ) loop
This loop is generally not recommended, as it should be used for iterating over object properties only, not array like member properties.
for (var chunk in separated) {
if ( ! separated.hasOwnProperty(chunk)) {
continue;
}
// `separated[chunk]` is each member of the array.
}
jsFiddle.
This loop will loop over all properties up the prototype chain, so hasOwnProperty() must be used. For this reason it is not recommended for arrays.
for ( of ) loop
This loop is standardized in ECMA 6 and is able to loop over NodeLists and iterators.
for (var chunk of separated) {
// `chunk` is each member of the array.
}
jsFiddle
forEach() method
This method is an addition to the ECMA-262 standard. It's not available in IE8, but it can be shimmed relatively easily.
separated.forEach(function(chunk, index) {
// `chunk` is each member of the array.
});
jsFiddle.
Other specialised methods
If you're looking to iterate for a specific goal, it may be useful to use a specialised iterator. Keep in mind these also don't have the best browser support.
filter method
Creates a mew array of the elements which the associated callback returned truthy for.
separated.filter(function(element) {
return +element > 255;
});
reduce method
Creates a new value based on reducing the elements of the array, from left to right.
separated.reduce(function(accumulator, element) {
return accumulator.concat(element);
}, "");
See also the reduceRight method.
map method
Creates a new array, replacing each element with the returned value of the associated callback.
separated.map(function(element) {
return element.substr(0, 1);
});
every method
Returns a boolean value of which is the result of every element in the array passing the test. This method short circuits, i.e. it returns whenever one element's callback doesn't return truthy.
separated.every(function(element) {
return element.substr(0, 1) == "a";
});
some method
Returns a boolean value of which is the result of some element in the array passing the test. This method short circuits, i.e. it returns whenever one element's callback passes the test.
separated.some(function(element) {
return element.substr(0, 1) == "a";
});
separated.length should be all you need.
str.split() returns an array of values, so in your example, since 'separated' is an array, you could:
for (var i=0, len=separated.length; i < len; i++) {
// do something with separated[i]
}
you can do it in jquery like this
$.each(separated,function(key,item){ alert('here is ' + item + ' at position ' + key) })
If your question really is "how do I loop through each separated variable?" then:
for (var i = 0; i < separated.length; i++)
{
//Do something with separated[i];
}
//or (apparently this is deprecated)
for(var a in separated)
{
//Do something with a
}
Loop through with a FOR...NEXT construct like in most other languages:
var somestring = "data1|data2|data3";
var separated = somestring.split("|");
for (i=0 ; i<separated.length; i++) {
document.write(separated[i]);
document.write("<br/>");
}

Categories