I have an array of colors that I want the option to reverse. I have a toggle function that basically colors elements based on the array. If I throw a reverse variable then it reverses, but it reverses the global variable instead of the local variable.
var inc_colors = ['#000','#333','#888']; //global inc_colors
function toggleLegendColors(reverse){
var reverse = reverse || false;
var colors = inc_colors; //local colors
if(reverse) colors.reverse(); //reverses inc_colors array as well as colors
...
}
How can I get the reversed global array without changing the global array?
Since nobody has really explained why you were having a problem, I'll add that to the mix.
When you assign an array or an object in javascript to a variable, it assigns a reference to that array/object. It does not make a copy of the array/object. So, then you would have two variables that both point at the same array/object and modifying either one will affect the other (since they both point to the same underlying piece of data).
So, when you had this:
var inc_colors = ['#000','#333','#888']; //global inc_colors
var colors = inc_colors; //local colors
All you have now is two variables that both point to the exact same piece of data. Modify either one and the same result will show via the other variable because they point to the same underlying data.
If you want to make a copy, then have to explicitly make a copy (javascript doesn't do it for you automatically). For an array, the simplest way to make a shallow copy is like this:
var newColors = Array.prototype.slice.call(inc_colors);
So, in your exact code, you could apply that copy like this:
var inc_colors = ['#000','#333','#888']; //global inc_colors
function toggleLegendColors(reverse){
var reverse = reverse || false;
var colors = Array.prototype.slice.call(inc_colors); //local copy of the colors array
if(reverse) colors.reverse(); //reverses inc_colors array as well as colors
...
}
You can do this by using the es6 spread operator now too:
let colors = [ ...inc_colors ].reverse()
Just make a copy of the array using Array.slice (safe way):
var colors = Array.prototype.slice.call(inc_colors);
clean simple way that you may consider , but involves creating a new instance of the array is
var arr_reverse=arr.slice(0).reverse();
Simplistic solution:
var inc_colors = ['#000','#333','#888']; //global inc_colors
function toggleLegendColors(reverse) {
var colors = (inc_colors instanceof Array) ? inc_colors : [];
colors = (!reverse) ? inc_colors.slice() : inc_colors.slice().reverse();
// ...
}
Related
Assume the following array:
var arr = [0,0,{x:0,y:0}];
var newA = arr.slice(0);
arr[2].x =2;
arr[2].y =2;
console.log(newA)
x and y are coordinates that are supposed to be changed. How can I store them before a function is invoked and they change (perhaps pushing to a new array)? A shallow copy with slice won't work as the copied array will update the values dynamically.
You can use Object.assign to duplicate the object without creating a reference.
For example:
var arr = [0,0,{x:0,y:0}];
var bak = Object.assign({}, arr[2])
In this case, bak is not a reference to arr[2], so changing either would not affect the other.
I never used global variables in Node.js so I have trouble understanding why this wont work. I am declaring global variable that is array, than I want to push some object into it and for sake of debugging I just want to stringify it.
I tried it like this:
var test = require('./api/test'); //my class
global.arrayOfObjects = []; //declaring array
global.arrayOfObjects.push = new test(123); //docs3._id is something I return from db
console.log(JSON.stringify(global.arrayOfObjects)); //I get []
You have to pass the object you want to push into the array as an argument:
global.arrayOfObjects.push(new test(123));
Array.prototype.push() documentation
You must do one of this three, you are mixin both:
var test = require('./api/test');
//global.arrayOfObjects = []; not need to declare the var here
global.arrayOfObjects = new test(123); from db
console.log(JSON.stringify(global.arrayOfObjects));
or
var test = require('./api/test');
global.arrayOfObjects = []; //needed to declare with this option
global.arrayOfObjects.push(1);
global.arrayOfObjects.push(2);
global.arrayOfObjects.push(3);
console.log(JSON.stringify(global.arrayOfObjects));
or
global.arrayOfObjects.push(new test(123)); // I think this is the best option
I am in a strange condition. I have an array of objects, I used angular.forEach to modify each object price key value but when I am changing it in each it is also changing main array object as well.
Have a look on code, you will understand then what I am trying to say.
var option_1_val = $scope.options.option_1_val;
var option_2_val = $scope.options.option_2_val;
console.log('genies',sc.genies);
var new_arr = [];
var each ;
each = sc.genies;
angular.forEach(each,function(val,key){
var ob = {};
ob = val;
var priceA = angular.fromJson(ob.price);
console.log('price',priceA);
var option = option_1_val.replace(" ","-")+","+option_2_val.replace(" ","-");
console.log(option);
ob.price = priceA[option];
console.log(ob);
new_arr.push(ob);
});
option = 'Non-Vegetarian,' (after calculating)
sc.genies = [{"gs_id":"3","user_id":"25","service_id":"7","price":"{\"Vegetarian,Bengali\":\"200\",\"Vegetarian
,Chinese\":\"3100\",\"Vegetarian,Gujarati\":\"800\",\"Vegetarian,Italian\":\"100\",\"Vegetarian,Maharashtrian
\":\"100\",\"Vegetarian,Punjabi\":\"100\",\"Vegetarian,-South-Indian\":\"300\",\"Vegetarian,Thai\":\"100
\",\"Non-Vegetarian,Bengali\":\"1100\",\"Non-Vegetarian,Chinese\":\"3100\",\"Non-Vegetarian,Gujarati
\":\"100\",\"Non-Vegetarian,Italian\":\"100\",\"Non-Vegetarian,Maharashtrian\":\"100\",\"Non-Vegetarian
,Punjabi\":\"100\",\"Non-Vegetarian,-South-Indian\":\"80\",\"Non-Vegetarian,Thai\":\"100\",\"Jain,Bengali
\":\"2100\",\"Jain,Chinese\":\"2100\",\"Jain,Gujarati\":\"4100\",\"Jain,Italian\":\"100\",\"Jain,Maharashtrian
\":\"100\",\"Jain,Punjabi\":\"100\",\"Jain,-South-Indian\":\"800\",\"Jain,Thai\":\"100\"}","min_price"
:"80","max_price":"4100","username":"abdul quadir","email":"abdul.quadir#kiozen.com","rating":"3"}]
now when I am repeating sc.genie, I have taken it in a new variable already "each" and then I am changing "price" key of each array to undefined but strange point is when I see in console value of price in sc.genies is also changed to "undefined". Huh!
I hope you got my point, please help me why is that happening.
Thanks
You should use angular.copy then when change in each value not affect to original value. because of angular.copy assign old value in new variable without reference.
like:
var each ;
each = angular.copy(sc.genies);
instead of
each = sc.genies;
There is a simple answer. The reason why "both" values changes, is because it is actually the same object. The variable val from this line angular.forEach(each,function(val,key){ ... contains a pointer to an object. It is not another object. It is the same object, it is only accessed via different variable name.
If you really want the original and working copy to be different objects, then you need to manually create new instance with the same values.
You can create copy of an object like this (good for simple objects):
var copy = JSON.parse(JSON.stringify(originalObject));
or as pointed in the comment above, you can use angular.copy(source, destination). See the documentation https://docs.angularjs.org/api/ng/function/angular.copy
I want to keep the original information of a variable so that a reset of the code will be much easier.
var $dataSets = [1,2,3,4];
var $oldData = $dataSets;
$('.button').click(function(){
$(this).toggleClass('selected');
if($(this).hasClass('selected')) {
$dataSets.splice(1,1);
console.log($dataSets);
} else {
console.log($oldData);
}
});
The problem I have with my code is that when I modify $dataSets it also changes $oldData. How do I keep $oldData from changing?
change to
var $dataSets = [1,2,3,4];
var $oldData = $dataSets.slice();
JavaScript does not pass the value of $dataSets into $oldData, rather it passes a reference to the thing which $dataSets itself references.
This workaround works because JavaScript's Arrays (which is what $dataSets is) have a method called slice which, when called with no parameters, returns a copy of the array.
You can use the function Array.slice(), like this:
var $dataSets = [1,2,3,4];
var $oldData = $dataSets.slice();
As described in the documentation, slice() does not alter the original array, but returns a new one. So basically, using slice, you have two different arrays, and can insert/remove items in one without interfering with the other.
Is it possible to write this "singleton array declaration" even shorter? There are different scripts which adds something to array but they're loaded asynchronously, so I don't know which will initialize array first.
var array = array || [];
array.push("foo");
console.debug(array[0]);
I tried something like this but this doesn't work:
(array || []).push("foo");
Any suggestions?
If you need to preserve the existing variable (which would happen if you don't know which piece of code will execute first), your code can't be written any shorter.
Of course, you can change the default value if you want:
var array = array || ['foo'];
But if the variable already exists, it won't add foo anymore. Probably not what you want.
Old answer
With your given example:
var array = ['foo'];
Don't know what you want with the array || []. But this is how you get the same:
var array = new Array("foo");
Just use the bracket notation since its faster then using new Array().
If you need to add items dynamically, you'll need to use .push(); - or take care of the numeric index of your array by yourself.
Ok, didn't read your comment above about async loaded scripts. Why don't you just declare your array before any of the other scripts are loaded, so you can be sure that your array exists?
Depending on how you want to affect the array passed in
var newVals = (vals || []).concat(["c","d"]);
or
var newVals = [].concat((vals || []), ["c","d"]);
The shortest way is to check if array is already defined when you try to push:
var array = typeof array === 'undefined' ? ['foo'] : array.push('foo');
For readability's sake, you may want to create a lazy-loaded getter:
var addToArray = function (item) {
// ensure array is defined
if (typeof array === 'undefined') {
array = [].push(item);
}
// redefine this function as a reference to push
addToArray = array.push;
};
var array = [];
array.push("foo");
console.debug(array[0]);
If you're not adding elements dynamically, than this is enough:
var array = ["foo"];
console.debug(array[0]);
Update:
Again, if you know your elements upfront, do
var array = array || ['foo']