How to keep a variable from changing in javascript - javascript

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.

Related

when changing value of copied variable it is also changing main variable value in angularjs

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

How to update object properties within a loop?

I have found a behavior I did not expect when trying to use a loop in order to change the value set for a property in an object.
Basically, I declare my object outside the loop.
Then I loop on an array of numeric values, which values are used to update the object property.
Inside the loop, I store the current object state inside an external array.
The result is that instead of having an array containing a series of objects with different numeric values, I end up having the same numeric values in each object stored.
Here is the fiddle http://jsfiddle.net/fAypL/1/
jQuery(function(){
var object_container = [];
var numeric_values = [1, 2 , 3, 4];
var my_object = {};
jQuery.each(numeric_values, function(index, value){
my_object['value'] = value;
object_container.push(my_object);
});
jQuery.each(object_container, function(index, value){
jQuery('#content').prepend(value['value']);
});
});
I would expect to get 1 2 3 4 as values stored in each object, however, what I get is 4 4 4 4, which does not make sense to me.
Any hint on this behavior is more than welcome, thanks
When your code calls .push() and passes my_object, what's being passed is a reference to the object. No copy is made.
Thus, you've pushed four references to the exact same object into the array.
JavaScript objects always participate in expressions in the form of references. There's no other way to deal with objects. Thus when you create a variable, and set its value to be an object, you're really setting its value to be a reference to the object. Same with parameter passing, and anywhere else an object can appear in an expression.
In this case, you can create new objects pretty easily; just dispense with my_object and push a fresh one on each iteration:
object_container.push( { value: value } );
You are not creating a new object each time around the loop - you are just updating the same existing object and pushing references of that to the object array. To create a new object you want to do something like:
my_object = { 'value': value };
object_container.push(my_object);
In this case you now will get something more like what you were looking for. See the updated fiddle here: http://jsfiddle.net/fAypL/2/.
Best of luck!
One more thought (Clone!) - If you are really tied to using the same object each time, just clone the object before you add to the array. There is a great solution for that here.
You are using jQuery so if what you want is to merge without effecting the original look at :
var both_obj = $.extend( {}, default_obj , adding_obj );
This will leave your original object changed, also good to use for a copy.
jquery docs - extend()
An alternate version is to use an object with a constructor and the new keyword:
var object_container = [];
var numeric_values = [1, 2 , 3, 4];
function MyObject(value)
{
this.value = value;
}
jQuery.each(numeric_values, function(index, value){
object_container.push(new MyObject(value));
});
jQuery.each(object_container, function(index, value){
jQuery('#content').prepend(value['value']);
});
Fiddle

Saving reversed array to variable in javascript

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();
// ...
}

array.splice not working

i want to remove array element, but giving error while using splice,
i m using following function
with myAra as global var,
but in console ,it is giving me an error, TypeError: myAra.splice is not a function
var myAra = Array();
function charCounts(e,textAreaId)
{
myAra = $("#"+textAreaId).val();
var countNewLines = stringOccurrences(myAra, "\n");
if(myAra.length>75)
{
for (var i = 75; i >myAra.length; i++)
{
myAra.splice(i, 1);
}
$("#"+textAreaId).val(myAra);
}
}
myAra is a String, not an Array, at the point when you call splice. It has the value of the element.
This is a nice example of why globals are EVIL, sure you declared the variable an array (badly): var myAra = Array() (I'll explain at the end what's bad about this), but later on:
myAra = $("#"+textAreaId).val();//returns a string, variable is now a string, not an array
You've reassigned a string to the array, so the variable now references a string constant, and cannot be used as an Array (not safely, in a X-browser way at least).
Array() is bad, why? Well, for starters, you're calling a constructor, but you're not using the new keyword. With arrays that's not a big problem (it'll return a new instance all the same), but when you start defining your own objects, and constructors, you'll find yourself up to your neck in globals. Also, suppose you wanted an array and initialize the first element to an int: var anArray = new Array(2);, you won't get an array that looks like this: anArray[0] === 2, you'll get anArray === [undefined,undefined]. Compare that to var anArray('2') --> ['2']. Given the fact that JS is loosely typed, and you'll often use variables when initializing an array, it's hard to tell weather or not you're passing a numeric string or a number to the constructor. The best way to initialize arrays is by using the literal notation: [2,3,4], as an added bonus, it requires less typing, too
Replace the following:
if(myAra.length>75)
{
for (var i = 75; i >myAra.length; i++)
{
myAra.splice(i, 1);
}
$("#"+textAreaId).val(myAra);
}
with the below code:
if(myAra.length>75)
{
var moreNum = myAra.length - 75;
myAra.splice(75, moreNum ); // remove all items after the 75th item
$("#"+textAreaId).val(myAra);
}
Note - splice change the actual array, that's why the loop was failing. Hope it helps.
You are assigning a string value directly to the myAra so it will convert it to string ..typeOf myAra. Use myAra[0]=$("#"+textAreaId).val();...since javascript is a loosely coupled language
In the first line you used var myAra = Array(), but the jQuery val() function returns a string.
EDIT: Also I think the prefered way of creating arrays in JS is the var myArray = [], and not using the var myArray = new Array() expression.

How to retain array in javascript?

Here's some code that has two arrays(np and op), one a copy of the other
However, when I modify the copy, the original is also modified!
take a look:
<script type="text/javascript">
var op=new Array(0, 0);
var np=op;
np[1]=2;
document.write(op+"<br>")
document.write(np)
</script>
Is there any way to retain the original and modify the copy?
Some of the built in Array functions will actually create a copy for you. One such is slice.
For example:
var op=new Array(0, 0);
var np= op.slice(0);
np[1]=2;
document.write(op+"<br>")
document.write(np)
Reference http://my.opera.com/GreyWyvern/blog/show.dml/1725165
You never made a copy of the array. You simply assigned the array to another variable. This does not copy in Javascript. In your example there is only one array with two variables by which you can access it. There is no built-in way to copy arrays in Javascript so you will need to write your own function to do it.
Take a look at this StackOverflow question for a hint on how to actually implement the copying of the elements in the array.
What you are doing is not creating a copy of the array, it's only creating a copy of the reference to the array, so you get two references to the same array object.
This is how you can create an actual copy of the array:
var np = op.concat();
The concat method creates a new array that is a copy of the array with any additional items added. If you don't specify any additional items you just get a copy of the array.
Array.prototype.copy = function() {
return this.slice(0, this.length);
}
Then
var op=new Array(0, 0);
var np=op.copy();
np[1]=2;
document.write(op+"<br>")
document.write(np)
You should clone the second array instead of copying it.
--- Update
If you assign an object to a variable, only the reference is copied (that means, they both point to the same data). For having an independent copy of this object you need to clone it. And there are several ways how to this, for example here is the way of cloning object using jQuery.
You can just use the native slice method which returns a copy of the array:
var np = op.slice(0,op.length);
The second parameter should be optional, but in IE I believe it is required.
Your code, complete with the change:
var op=new Array(0, 0);
var np=op.slice(0,op.length);
np[1]=2;
document.write(op+"<br>")
document.write(np)
To create a new array you might want to consider:
var op = [];
To copy an array:
var np=op.slice();
or
var np=op.concat();
concat is faster, while slice takes up one less character. Some people alias "slice" or "concat" as "copy" so that it's more obvious that you're making a copy.
No need for parameters in either case. Parameters in the slice will just make the code larger and slower.

Categories