http://jsfiddle.net/gfuKS/5/
var transitionInitial = {property: "none"};
var rules = ["color", "background-color"];
var transitions = [];
for ( var k = 0; k < rules.length; k++)
{
transitions[k] = transitionInitial;
transitions[k].property = rules[k];
alert(transitions[0].property);
}
Why at the second iteration transitions[0].property equals "background-color"?
Because you are storing a reference to transitionInitial, not a copy of it. transitionInitial points to an object in memory, and you are storing a reference to this object in transitions[k]. Regardless of the iteration you are at, you are always changing the same object.
It's because both values in your transitions array are pointing at the same object. During the execution of your code you produce one object that has three different references (transitionInitial, transistions[0], & transistions[1]).
During the first iteration of the loop, transistions[0] is set to reference the transitionInitial object. Then the property property of that object is set to the value "color". During the second iteration transitions[1] is set to reference the same object as transitionInitial and transitions[0]. You then reset the property's value to "background-color".
To solve this create different objects for each of your array indexes:
// Not needed anymore:
// var transitionInitial = {property: "none"};
var rules = ["color", "background-color"];
var transitions = [];
for ( var k = 0; k < rules.length; k++) {
transitions[k] = {};
transitions[k].property = rules[k];
alert(transitions[0].property);
}
Does it have anything with this to do maybe? for ( var k = 0; k < rules.length; k++)
Try changing the timer.
Related
I am trying to create an array of objects. One object property is a function, which I want to change value of depending on which number in the array the object is.
When I try to use the 'i' value from the for loop, this is not being maintained in the function as a number. It is remaining a variable.
var array = [];
for (var i = 0; i<number; i++){
array[i].someFunction = function(i) {console.log(i)}}
However, when I call the value held in that property (i.e.):
console.log(array[2].someFunction)
It returns {console.log(i)} instead of {console.log(2)} which is what I want it to do.
Basically you had some problems in your code, like:
not defining number
using var instead of let
not defining the object
using the same value as parameter of the function
here you have the working solution.
var array = [];
// numbers was not defined.
const number = 10;
// use let instead of var
for (let i = 0; i < number; i++) {
// you are not instantiating your object, here is an example.
array[i] = {
"foo": "bar",
"index": i,
}
// you have to change i to j, because if you use i
// it will be the parameter of the function
array[i].someFunction = function(j) {
console.log('index: ', i);
console.log('parameter: ', j)
}
}
// we see the function
console.log(array[2].someFunction)
// we call the function succesfully
array[2].someFunction(100);
It's still referencing i, which has since changed to (number - 1). Save the value somewhere you know it's not subject to change- perhaps in the object itself:
var array = [{}, {}, {}];
for(var i = 0; i < array.length; i++){
array[i].index = i;
array[i].someFunction = function(){console.log(this.index);}
}
//and see that it's working...
for(var i = 0; i < array.length; i++){
array[i].someFunction();
}
I am trying to create multiple new variables inside a loop.
The number of new variables depends on the lenght of another variable (variable "list" used below).
for(var i = 0; i < list.lenght; i++)
{
var counter + i; // create new variable (i.e. counter1, counter2,...)
}
I found a lot of very simmilar questions on StackOverflow, and the answer is mostly using an array (i.e. How do I create dynamic variable names inside a loop?).
If I use the suggested solution, do I create an array of variables? So in my case I will create multiple counters and I can then add values to that variables, i.e.:
counter6++;
If that is not the case how could I tackle the problem?
I apologize for asking you to explain an old answer, but I cannot comment in the old one because of low reputation.
You have some options here :
Create them global (not best practice ) :
for(var i = 0; i < list.lenght; i++){
window['counter' + i] = 0; // create counter1, counter2,...)
}
Use object :
var scope = {};
for(var i = 0; i < list.lenght; i++){
scope['counter' + i] = 0; // create scope.counter1, scope.counter2,...)
}
Use Object with with keyword
var scope = {};
for(var i = 0; i < list.lenght; i++){
scope['counter' + i] = 0; // create scope.counter1, scope.counter2,...)
}
with(scope){
// here you can acesess keys in the scope object like them variable on the function scope
counter0++
}
Use plain old Array
var scope = new Array(list.length);
You can create an object, set property names to expected variable names, then use object destructuring assignment to get the property assignment or index of an object having a .length as a variable identifier; or use array destructuring to assign an identifier to a specfic index.
let [list, obj] = ["abc", {}];
for (let i = 0; i < list.length; i++) {
obj["counter" + i] = list[i]
}
let {counter0, counter1, counter2} = obj;
console.log(counter0, counter1, counter2);
Alternatively
let list = "abc";
let {0:counter0, 1:counter1, 2:counter2} = list;
console.log(counter0, counter1, counter2);
let list = ["a","b","c"];
let [counter0, counter1, counter2] = list;
console.log(counter0, counter1, counter2);
How can I create a multidimensional array in JavaScript?
I have:
var m = 4;
for (var i = 0; i < m; i++){
groupsData.name_of_bar = [];
groupsData.name_of_bar[i]['a'] = data[i].a;
groupsData.name_of_bar[i]['ab'] = data[i].ab;
groupsData.name_of_bar[i]['de'] = data[i].de;
groupsData.name_of_bar[i]['gh'] = data[i].gh;
groupsData.name_of_bar[i]['xy'] = data[i].xy;
}
If I do:
groupsData.name_of_bar[0]
I get errors:
TypeError: Cannot read property '0' of undefined
TypeError: Cannot set property 'a' of undefined
What am I doing wrong?
JavaScript doesn't support multidimensional arrays per se. The closest you can come is to create an array where the values in it are also arrays.
// Set this **outside** the loop so you don't overwrite it each time you go around the loop
groupsData.name_of_bar = [];
for (var i = 0; i < m; i++){
// Create a new "array" each time you go around the loop
// Use objects, not arrays, when you have named properties (instead of ordered numeric ones)
groupsData.name_of_bar[i] = {};
groupsData.name_of_bar[i]['a'] = data[i].a;
groupsData.name_of_bar[i]['ab'] = data[i].ab;
groupsData.name_of_bar[i]['de'] = data[i].de;
groupsData.name_of_bar[i]['gh'] = data[i].gh;
groupsData.name_of_bar[i]['xy'] = data[i].xy;
}
Each iteration through the loop, you are doing groupsData.name_of_bar = [];. This removes whatever else is already in there and replaces it with a blank array.
Also, when you do groupsData.name_of_bar[i]['a'], you need to create groupsData.name_of_bar[i] first.
A way to do this is:
groupsData.name_of_bar = [];
var m = 4;
for (var i = 0; i < m; i++){
groupsData.name_of_bar.push({
a: data[i].a,
ab: data[i].ab,
ab: data[i].ab,
de: data[i].de,
gh: data[i].gh,
xy: data[i].xy,
});
}
Note that in JavaScript, arrays can only be numerically indexed. If you want string indexes, you need to use an object.
Also, if there are no other values in data[i], then you can simplify this even further by doing:
groupsData.name_of_bar = [];
var m = 4;
for (var i = 0; i < m; i++){
groupsData.name_of_bar.push(data[i]);
}
Heck, why not just use groupsData.name_of_bar = data; and lose the loop altogether?
The way you are declaring your objects are a little off. It looks like you are attempting to create an array of objects.
var groupsData = {name_of_bar: []},
m = 4,
i = 0;
for(; i < m; i++) {
groupsData.name_of_bar.push({
a: data[i].a,
ab: data[i].ab,
de: data[i].de,
gh: data[i].gh,
xy = data[i].xy
});
}
I am looking at an underscore.js function to retrieve the values from an object and am curious to understand the reason the _.values function was created the way it was.
The function as is in underscore.js:
_.values = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var values = Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values;
};
I believe this would also work however:
_.values = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var values = [];
for (var i = 0; i < length; i++) {
values.push(obj[keys[i]]);
}
return values;
};
What is the tradeoff between using function #1 vs. #2. Is it simply for performance or is there other things?
Thanks.
The first approach allows the JS runtime to immediately allocate the correct amount of memory.
Calling push() on an empty array will force the array to resize as it gets full, wasting time and memory.
I try to merge two node list in one but when I concat in one array, there is two time the same node. Concat do not search if nodes to insert already exist in array...
var firstNodelist = document.querySelectorAll("#outter, #inner");
var finalArray = new Array();
for (var i = 0; i < firstNodelist.length; i++) {
var secondNodelist = firstNodelist[i].querySelectorAll("div");
var firstArray = new Array();
for (var x = 0; x < secondNodelist.length; x++) {
firstArray.push(secondNodelist[x]);
}
finalArray = finalArray.concat(firstArray)
}
console.log("FINAL", finalArray);
The jsfiddle exemple
Rather than building a second, unnecessary array within your loop, just use that inner loop to check whether the node is already in the array (Array#indexOf on all modern browsers) and only add it if it isn't.
var firstNodelist = document.querySelectorAll("#outter, #inner");
var finalArray = []; // `[]` rather than `new Array()`
for (var i = 0; i < firstNodelist.length; i++) {
var secondNodelist = firstNodelist[i].querySelectorAll("div");
for (var x = 0; x < secondNodelist.length; x++) {
// Get this node
var node = secondNodeList[x];
// Is it in the array already?
if (finalArray.indexOf(node) === -1) {
// No, put it there
finalArray.push(node);
}
}
}
console.log("FINAL", finalArray);
Be sure to test your target environment(s) to be sure they have Array#indexOf.
Having said that, there's a much better way for that specific situation: Live Example | Live Source
var finalArray = Array.prototype.slice.call(
document.querySelectorAll("#outter div, #inner div")
);
...since querySelectorAll won't include the same node more than once, even if #inner is inside #outter (or vice-versa). (The Array.prototype.slice.call(someObject) is a trick to get a true array from any array-like object.)