Iterating over an array of functions - javascript

I have the following JavaScript code:
function f(){
}
var arrOfFuncs = [f, f, f, f];
for (var i in arrOfFuncs){
console.log(typeof i);
console.log(i);
}
When I run the script it prints:
string
0
string
1
...
string
3
Since I am iterating over an array of functions, isn't "typeof i" supposed to be "function" and i.toString() supposed to be "function f(){}"?

No. The for…in construct iterates over the keys of an object or array, not its values.
You can use a simple for loop:
for (var i = 0; i < arrOfFuncs.length; i++){
console.log(typeof arrOfFuncs[i]);
console.log(arrOfFuncs[i]);
}
Or modify your for…in loop like this:
for (var i in arrOfFuncs){
console.log(typeof arrOfFuncs[i]);
console.log(arrOfFuncs[i]);
}
Or you could use the forEach method (introduced in ECMAScript 5.1):
arrOfFuncs.forEach(function(f) {
console.log(typeof f);
console.log(f);
});

When you iterate over keys of an object with for(var in in ...) i will equal the key - in the case of an array you are getting the indices as well as properties of the array (0, 1, 2, length, etc) and the type of that index or property key might very well be a string.
You want to access the value of the array at that key, so you need to do arrOfFuncs[i] - that said, it is probably better to use either .forEach or some equivalent if you can or use
for (var i = 0, l = arrOfFuncs.length; i < l; i++) {
var value = arrayOfFuncs[i];
}
Because you avoid the risk of accessing properties on the array you don't intend to access.

in your code i is the key it's not value. so your code should be like this to get function type:
function f(){
}
var arrOfFuncs = [f, f, f, f];
for (var i in arrOfFuncs){
console.log(typeof arrOfFuncs[i]);
console.log(arrOfFuncs[i]);
}

When you use for..in you are running over keys and not over values.
Read about JavaScript for..in loops.
This code will do what you want:
function f(){
}
var arrOfFuncs = [f, f, f, f];
for (var i in arrOfFuncs){
console.log(typeof arrOfFuncs[i]);
console.log(i);
}
JSFIDDLE

in for in iteration over arrays, i doesn't represent the element, it represents the index.
the below code works:
var array = [function f(){}, function k(){}];
for (var i in array) {
console.log(array[i]); //function()
console.log(typeof array[i]); //function
}

Related

How does "for in" loop work in Javascript?

The program is as follows,
function sum(x) {
console.log(typeof x[0]); //return Number
var s=0;
for(var e in x) {
console.log(typeof e); //This return string
s+=e;
}
return s;
}
console.log(sum([1,2,3,4,5])); //return 001234
If I use a number constructor then it works fine.
function sum(x) {
console.log(typeof x[0]); // return Number
var s=0;
for(var e in x) {
s+=Number(e);
}
return s;
}
console.log(sum([1,2,3])); //return 6
What is happening at for in loop?
From MDN:
The for...in statement iterates over the enumerable properties of an object, in original insertion order.
and
A different property name is assigned to variable on each iteration.
Property names are strings. So you get strings. The + operator will concatenate strings.
If you convert the value to a number, then you don't have strings any more. The + operator will perform addition on numbers.
console.log(sum([1,2,3]); //return 6
No.
It throws an error because you have one ) too few. If you fix that, it outputs 3 because you are looping over the property names not the values, so you are adding 0, 1 and 2.
For ... in loop in es6 is used to loop over objects.
As an array is technically an object it loops over the index of the array. You can see this by console.logging inside the for loop.
Use For ... of loop to loop over arrays normally.
function sum(x) {
console.log(typeof x[0]); //return Number
var s=0;
for(var e of x) { // of loop
console.log(e)
s+=e;
}
return s;
}
console.log(sum([1,2,3,4,5])); //return 001234
Others have already pointed out that for-in iterates over properties, not values. In the case of an array the properties are the indices.
function sum(x) {
var s=0;
for(var e in x) {
s+=e;
}
return s;
};
var array = [1,2,3,4,5];
array.b="z";
console.log(sum(array)); // prints 001234b
In the resulting 001234b string you have:
Leading "0": The initial value of s
Then "0" because first index is 0
Then "1", etc

For loop is not working with json data

I'm trying to make a loop in javascript with the following code. It's getting length from json data.
The console.log(albums.data.length); line is working and returning 3. Why the loop is not working then?
The console.log(x); is not returning anything, even not blank line.
There is also no error in console.
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var x in albums.data.length){
console.log(x);
for(var y in albums.data[x].photos.length){
console.log(y);
}
}
}
I have tried another type of loop(for(var i = 0; i < blabla; i++)) but its not working too.
Edit:
I wanna use
for(var x = 0; x < albums.data.length; x++){
console.log(albums.data[x].photos.id);
}
instead of
for(var x in albums.data){
How can i do it?
You should remove .length from loops
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var i = 0; i < albums.data.length; i++){
var x = albums.data[i];
console.log(x);
for(var j = 0; j < albums.data[i].photos.length; j++){
var y = albums.data[i].photos[j];
console.log(y);
console.log(albums.data[i].photos[j].id);
}
}
}
The for-in loop is not for arrays, it is for iterating over properties/fields of an object. If albums.data is an array, you should use the forEach loop statement instead. If albums.data is an object, and you are trying to access its properties/fields/attributes, you can use the for-in construct.
If albums.data is an array, try:
albums.data.forEach(function(element, index) {
// Here you have access to each element (object) of the "albums.data" array
console.log(element.toString());
// You can also access each element's properties/fields if the element is an
// object.
// If the element is an array itself, you need to iterate over its elements
// in another inner foreach.
// Here we are accessing the "photos" property of each element - which itself
// is another array.
element.photos.forEach(function(photo, index) {
// Here you have access to the elements of the "photos" array
// Each element of the "photos" array is put in the photo variable.
// Assuming each element of the "photos" array is an object, you can access
// its properties, using the dot notation:
console.log("photo id=", photo.id);
// If the property name (e.g. "id") is not a valid javascript name
// (has some special symbols), use the bracket notation
console.log("photo URL=", photo["photo-url"]);
});
});
You can also use the lodash library for this (and many other neat functionalities).
If albums.data is an object, try:
for (var prop in albums.data) {
// Again, this construct is for accessing properties of an object
// (e.g. if albums.data is an object), not an array.
console.log("property name=" + prop + ", " + "property value=" +
albums.data[prop]);
}

Javascript Map and Reduce with Sort [duplicate]

This simple javascript
var x = new Array();
x[0] = 2.73;
x[1] = 11.17;
x[2] = 3.12
x.sort();
for(var i in x)
alert(x[i]);
produces the results:
11.17, 2.73, 3.12 instead of 2.73, 3.12, 11.17.
Why is that and how can I fix it?
Thanks in advance!
It's sorting alphabetically, try passing your own sorting function:
var x = new Array();
x[0] = 2.73;
x[1] = 11.17;
x[2] = 3.12;
numberSort = function (a,b) {
return a - b;
};
x.sort(numberSort);
for(var i in x) {
alert(x[i]);
}
By default, Array.sort will sort alphabetically (lexographically)...but you can supply your own function. Try:
x.sort(function(a, b) { return a > b ? 1 : -1});
Array.sort() function treats its elements as Strings and if no function is passed to the sort() statement, it converts the elements to Unicode and sorts. Therefore, it is advised to pass a custom sort Function whenever sorting numbers.
function customSort(a, b){
return a - b;
}
console.log([-11,-2, 0 ,100].sort(customSort));
This customSort() function will sort the array in_place in ascending order.
Between them, the existing answers tell you everything, but none of them mention both of the problems in your code. Here's the full answer:
The sort isn't doing what you want because the default sort is lexical (i.e. the array elements are converted to strings and compared alphabetically). You can provide your own comparison function to sort():
x.sort(function(a, b) {
return a - b;
});
Secondly, for...in is actually telling you nothing concrete about whether your array is sorted correctly, because the enumeration of for...in is not defined (even though most but not all browsers do broadly what you'd expect). Use a for loop instead (as indeed you generally should for arrays):
for (var i = 0, len = x.length; i < len; ++i) {
alert(x[i]);
}
You are not iterating properly. It should be:
for (var i = 0; i < x.length; i++) {
alert(x[i]);
}
When you use for..in in javascript this will loop through the properties of the object and the order of iteration is undefined. You should be seeing some strange output as well such as all the functions defined in the Array class.

Uncaught Type Error in javascript: object has no method

Uncaught TypeError: Object 0 has no method 'addEventListener'
var A={};
A.addEventsToClassName=function(event,className,func)
{
var a=document.getElementsByClassName(className);
for(var b in a)
{
b.addEventListener(event,func,false);
}
};
Object b is meant to be an element object once the function is called later in the code. How can I prevent this error?
A for (var b in a) will give the property names within a, not the actual values; so you need to dererefence a when you want to use them.
a[b].addEventListener(event, func, false);
Also, it's an Array like data structure, so you should iterate it as such:
for (var i = 0; i < a.length; ++i) {
a[i].addEventListener(event, func, false);
}
The b is probably a index not your object . Perhaps you want write like this:
a[b].addEventListener(event,func,false);
b is not an object nor an element, it is a string ("0"). for...in gives you the keys not the value.
Don't use for(var b in a) to loop through a NodeList (it will loop through not only the properties of itself but also the properties inherited from its parent), do this instead:
for(var i = 0; i < a.length; a++){
a[i].addEventListener...
}
If you ask why, then take this for example,
for(var a in document.querySelectorAll("body")){
console.log(a);
}
>"0"
>"length"
>"item"
You can see that for...in does not work in this case since length and item are not actually in the list but still properties inherited.

is it possible to refer to anonymous array in a for loop?

for (var name in ['dog','cat','cow']) {
alert(name);
}
The name here is returning the index of the array, but I can't refer to it since it's anonymous.
I know I can declare it outside the loop, but here I'm asking if is there a way for refering to the name directly that is without index.
...no. There isn't, not a native loop at least. There is, however, ES5's forEach:
['dog', 'cat', 'cow'].forEach(function(value, key) {
// do stuff
});
Which is practically the same. It's supported mostly everywhere, except in old IE: something like es5-shim for example enables ES5 methods even in such old browsers, though.
If you know the keys of the array are going to be integers, there's nothing that necessitates the use the for..in construct.
for (var arr = ['dog','cat','cow'], name = 0; name < arr.length; name++ ) {
console.log(arr[ name ]);
}
In the above code, a simpler for loop allows for the creation of a new object and referencing by key inside the loop.
You have several options.
If you are using jQuery you can do this:
$.each(['dog','cat','cow'], function() {
var name = this;
alert(this);
});
If you are not using jQuery you can create your own function
function each(array, pFunction) {
for(var i = 0; i < array.length; i++) {
var element = array[i];
pFunction(element);
}
}
each(['dog','cat','cow'], function(name) {
alert(name);
});
If you don't want to create a function you can always do something crazy like this: (don't recommend it)
for (var name in { 'dog' : '','cat' : null,'cow' : null }) {
alert(name);
}
If the array is anonymous you cannot refer to its elements using a for in loop.
No you can't do it. It will show only the indexes. Besides, for in loop for array in JavaScript is a bad practice. It will loop through all the array objects method.
Array methods forEach, map, filter and so on will iterate through a literal array's indexes:
['dog', 'cat', 'cow'].forEach(alert);
Shim for older browsers:
if(![].forEach){
array.prototype.forEach= function(fun, scope){
var T= this, L= T.length, i= 0;
if(typeof fun== 'function'){
while(i< L){
if(i in T){
fun.call(scope, T[i], i, T);
}
++i;
}
}
return T;
}
}
You're using wrong syntax construction for this.
for in is for enumerating object's properties, not for iterating arrays. Declare your array outside and use regular loop.
var arr = ['dog', 'cat', 'cow'];
for(var i = 0; i < arr.length; i++) {
// your code
}

Categories

Resources