I have a simple array that I'm trying to iterate over but I'm apparently not understanding the 'for of' JavaScript loop. The following code returns exactly has it should;
const callOBJb = ['KD0NBH0BJ','W0DLKOBJ','WA0TJTOBJ'];
for (let i of callOBJb) {
console.log(i);
}
return: KD0NBHOBJ W0DLKOBJ WA0TJTOBJ
But the following code errors out with; "TypeError: i.getCenter is not a function. (In 'i.getCenter()', 'i.getCenter' is undefined)" because the variable 'i' does not resolve to one of the above.
for (let i of callOBJb) {
var Omiddle = i.getCenter();
}
When I manually type the variable in such as;
var Middle = W0DLKOBJ.getCenter();
It works just fine. What am I not understanding about how this should work?
I don't think I can use the ForEach here at least I'm not having any more luck than the for...of.
I was asked what the resolved variable for W0DLKOBJ might look like.
alert(JSON.stringify(KD0NBHOBJ));
{"_southWest":{"lat":39.204385,"lng":-94.60714},"_northEast":{"lat":39.20646,"lng":-94.60481}}
This works:
var Middle = W0DLKOBJ.getCenter();
because this:
W0DLKOBJ
is different from this:
'W0DLKOBJ'
If the array should contain the variable values and not string literals, don't use quotes:
const callOBJb = [KD0NBH0BJ, W0DLKOBJ, WA0TJTOBJ];
The callOBJb variable is an Array of strings, and when you use for..of statement to perform a loop iteration, for each item in your iterable object you will get item at deposition corresponding to the time to loop bloc code is execute.
In you case as all items in the callOBJb array is simple string, javascript String.prototype Object doesn't define a function named getCenter that is the reason why you are getting
"TypeError: i.getCenter is not a function. (In 'i.getCenter()', 'i.getCenter' is undefined)
let callOBJb = ['KD0NBH0BJ','W0DLKOBJ','WA0TJTOBJ'];
for(let item of callOBJb){
console.log(typeof item, item);
}
As you can see on each iteration the typeof item is always string.
I went back to the php and redesigned the output to make conversation to Javascript easier. By doing that I was able to iterate through the values using "for (let val of callOBJb)" successfully.
The solution came in how I received the data from PHP to start with. When I changed the definition to; const callOBJb = <?php echo "[$callOBJb]" ?> to include the square brackets and then used; for (let val of callOBJb) {...etc all of the variables resolved properly.
Related
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);
});
I am receiving a JSON data from database which is
[{"table_cols":["id","stud_name","stud_school"]}].
console.log("Response is: " + resp._bodyText); {/*Response is: [{"table_cols":["id","stud_name","stud_school"]}]*/}
let parsedData = JSON.parse(resp._bodyText);
console.log(parsedData) //Object
this.setState({...this.state,cols_of_sel_tab:parsedData})
for(let i=0; i<this.state.cols_of_sel_tab.length;i++)
{
cols = [];
console.log(this.state.cols_of_sel_tab[i])
let cols = this.state.cols_of_sel_tab[i]
console.log("WOW")
for (let j = 0; j<cols.length; j++){
console.log(cols[j])
}
}
Output: {table_cols: Array(3)}
WOW
Expected: To iterate through the inner for loop
Desired output is: id, stud_name,stud_school
Tried: using forEach instead of inner for loop
Error: ...\node_modules\react-native\Libraries\ReactNative\YellowBox.js:82 Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'forEach' of undefined
TypeError: Cannot read property 'forEach' of undefined
I need help!
State updates are asynchronous. If you want to loop through the data you've received right then, use parsedData, not this.state.cols_of_sel_tab.
Separately, never do this:
this.setState({...this.state,cols_of_sel_tab:parsedData});
If you're setting state based on your current state, you must not pass in an object; instead, you must pass in a callback function that uses the state it receives as an argument (see the linked docs for details).
But in this case, you don't need the ...this.state at all, so it would be fine if you just did this:
this.setState({cols_of_sel_tab:parsedData});
...and then (again) looped through parsedData not this.state.cols_of_sel-tab.
Separately, you have a problem with cols: You're trying to use it in a block before it's declared with let. If you'd really run that code, it would have failed with an error saying cols is not defined (because you cannot access an identifier declared with let or const within a block prior to the declaration, even if it exists in an outer scope).
1. Solution to your question
The main problem why you (somehow without syntax error and not getting the empty state problem) get the
Output:{table_cols: Array(3)} WOW
and not the array items, because of the model of your response
[
{"table_cols":
["id",
"stud_name",
"stud_school"]
}
]
So, instead of
let cols = this.state.cols_of_sel_tab[i]
should be
let cols = this.state.cols_of_sel_tab[i].table_cols
And input will be:
{table_cols: Array(3)}
WOW
id
stud_name
stud_school
2. Syntax Error
cols = [];
let cols = this.state.cols_of_sel_tab[i]
You're trying to assign empty array to the variable, that not defined.
In this particular example you could just amend the first row
3. State handling
In your code example you've got two goals: update the state with new data and use the new data for output. Cause state updates are asynchronous is much safer to manipulate and output the data you already have right away (I amended debug console output).
this.setState({cols_of_sel_tab: parsedData})
for(let i=0; i<parsedData.length; i++) {
let cols = parsedData.cols_of_sel_tab[i].table_cols
for (let j = 0; j<cols.length; j++) {
console.log(cols[j])
}
}
Also, cause states updates are merged you can amend spread operator for this.state, like in the code above.
4.More improvements
There is a map function mention in header of the question, you could use it.
parsedData.map(
col_of_sel => col_of_sel.table_cols.map(
cols => console.log(cols)
)
)
or, if you only need the table_cols of the first object:
parsedData[0].table_cols.map(cols => console.log(cols))
You've got different code style in your example in question: semicolon presence, differences in indentations. I recommend to use some kind of prettier to pretty up the code, so it will be easier to read.
Finally
let parsedData = JSON.parse(resp._bodyText)
this.setState({ cols_of_sel_tab: parsedData })
parsedData[0].table_cols.map(cols => console.log(cols))
The problem is a slight misunderstanding of what your JSON data represents.
If we make the JSON a little prettier:
[
{"table_cols":
["id",
"stud_name",
"stud_school"]
}
]
The outer square brackets represent an array. This array contains one item at index 0, which is the table_cols object. This object also contains an array, with your table col fields in.
You're running a for loop on the outer array. The first item this loop will come across is the object at index 0. To reach the table columns you'd need to either run a second for loop on the table_cols, or run the original loop on this.state.cols_of_sel_tab[0].table_cols.
I have a scoped variable that stores an archive:
viewScope.MY_SCOPE = new Array();
viewScope.MY_SCOPE.push(["id0", 0, true]);
viewScope.MY_SCOPE.push(["id1", 1, false]);
viewScope.MY_SCOPE.push(["id2", 3, true]);
now I want to update one of item.
viewScope.MY_SCOPE[1][2] = "true";
and this fails with the error:
Error while executing JavaScript action expression put(int index,FBSValue value) not supported in JavaWrapperObject.
How do I update a specific item in the array?
When adding the SSJS array object to the scope, it is converted to a java.util.Vector. Hence, if you want to set the value, you should use
viewScope.MY_SCOPE[1].set(2,"true");
instead of viewScope.MY_SCOPE[1][2] = "true";.
I think the problem is that using ...[2] = "true" tries to execute the put method of the given object. While put is available in Maps like HashMaps or the scope maps, Vectors use set instead of put to change values. For that reason, you get the "action expression put(...) not supported" error. In contrast to this, it's no problem to get the variable with viewScope.MY_SCOPE[1][2] because the get method is availiable in both HashMaps and Vectors.
When storing arrays in scope variables, I like to put the value into a properly typed javascript variable, make edits, and then replace the scope variable with the updated value.
In your case I would do the following:
var tempVar = viewScope.MY_SCOPE.toArray(); //convert to array to make sure properly typed
tempVar[1][2] = true;
viewScope.put(MY_SCOPE,tempVar);
Update:
After testing your code along with mine, I too get the same error. To be honest, I never would have messed with multi dimensional arrays in the first place. This is a perfect opportunity to use an array of objects:
var tempVar = []; // initialize the array
tempVar.push({val1:"id0",val2:0,val3:true});
tempVar.push({val1:"id1",val2:1,val3:false});
tempVar.push({val1:"id2",val2:3,val3:true});
viewScope.put("MY_SCOPE",tempVar);
Then to change the desired value:
var tempVar = [];
tempVar = viewScope.get("MY_SCOPE");
tempVar[1].val3 = true;
viewScope.put("MY_SCOPE",tempVar)
I tested this method and it works fine.
When I'm working with data, I normally have the need of create Arrays or Objects on a loop, let's say "on the fly".
Lets say for example I want to rearrange an array grouping the element by one of the array keys: One of the methods I use is to loop trough an for in. But the problem is when I define more than one index on the fly.
for(key in array){
newArray[array[key]['gouping_key']] = array[key];
}
This example works fine. But if you have more than one element with the same grouping_key, this code is going to override your previous element.
So, I try this:
var i = 0;
for(key in array){
newArray[array[key]['gouping_key']][i] = array[key];
i++
}
But when I add that second index the interpreter complains saying that the newArray[array[key]['gouping_key']] is undefined. Problem it doesn´t seems to have on the previous example.
Why is that?
I've made this fiddle with an example in case the previous snippets an explanation would be insuficient and unclear. In the fiddle you have three snippets (two commented out).
The first one is the error I get when trying something like what Iǘe mentioned previously.
The second is the solution I use.
And the third an example of the creation of an array on the fly with only one index.
Summing up, I want to know why, when you add the second index, you get that error.
Thanks!
var i = 0;
for(key in array){
// If nested object doesn't exist, make an empty one.
newArray[array[key]['gouping_key']][i] =
newArray[array[key]['gouping_key']][i] || [];
newArray[array[key]['gouping_key']][i] = array[key];
i++
}
You need to create an array to push to, it's not created for you. You can use the || operator to only create an empty array if it's undefined.
Also, that's a lot of nesting to follow... If I may...
var x, y;
y = 0;
for(key in array){
x = array[key].gouping_key;
newArray[x][y] = newArray[x][y] || []
newArray[x][y] = array[key];
y++
}
See how much more readable that is? It's also faster! You dont have to deeply traverse complex objects over and over again.
First using for in for arrays is no good idea, it does not what you are expecting I think. see: https://stackoverflow.com/a/4261096/1924298. Using a simple for loop (or while) should solve your problem.
I'm trying to load text of all divs that have a particular class into an array, but this
var temp = $('.theClass').text();
temp = temp.toArray();
console.log(temp);
keeps giving me the error
Uncaught TypeError: Object has no method 'toArray'
And
var tempArr = [];
var temp = $('.theClass').text();
for (var t in temp){
tempArr.push(t);
}
console.log(tempArr);
results in an array filled with many, many objects within objects just filled with integers.
An explanation of how to do this properly can be found here, but I wonder if someone could provide me with an explanation for why I get these errors. Thanks!
You can use map to iterate over each element of the matched set and return some data (in this case, the text). You can then use get to convert the resulting jQuery object into an actual array:
var arr = $('.theClass').map(function () {
return $(this).text();
}).get();
Your first attempt fails because the text method returns a string, and strings don't have a toArray method (hence your "Object has no method" error).
Your second attempt fails because you're iterating over the string with the for...in loop. This loop iterates over the characters of the string. Each iteration t is assigned the index of the character, so you end up with an array, with one element for each character in the string. You should never really be using a for...in loop for iterating over anything other than object properties, and even then, you should always include a hasOwnProperty check.