I've one object, where one value is array of numbers and I call two functions, first function sorts data and display it, second function just display it.
problem is that, in second function, data is also sorted. (I'm not sorting there, data have come already sorted)
function1(data);
function2(data);
How can I fix it?
One simple solution to this would be create a copy of the object and then using it.
You can create a copy of the object, if don't want that using:
b = Object.create(a)
In this case b is a copy of a but if you make changes in a, it won't reflect in b. For more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
Reason: In javascript objects are passed by reference
http://www.w3schools.com/js/js_function_parameters.asp
Create clone inside sorted function before sorting it
Try like this
var cloneData=data.slice();
your function1 is sorting the data which means the data will be sorted when you call function2, what you can do is in function1 take in data, but create a new variable from data and then update that so the original data is never changed
However displaying some code for function1 and function2 would really help us provide some useful code :)
You will need to duplicate your object to do this. It has to do with object refencing and such.
VERY short explanation (way too short to do it any justice) is that function1 and function2 are using the same array, so when function1 changes it, this is visible in function2 afterwards. read up in this question here, this is definitely something you should research as a programmer.
var data = ['b', 'c', 'a'];
var sortedData = data.slice(0); // shallow copy, objects in the array are not copied
call the function that sorts with sortedData, call the function that only displays with data
Read up more about object references and primitive values to understand how changing values in one array is going to affect to other one, but if you aren't changing the values anymore this is not an issue you need to worry about.
Related
I have a variable called data, which brings an array to a function.
I then decided to continue using only the first element of the array (data[0]). would it have any difference if I do either of the following?
reuse/replace the array variable name data by assigning it with its first element, which would be
data = data[0]
and continue to use data
declare a new variable and assign it the first element of the array data, which would be
var data_new = data[0]
Is there any problem in doing the first one? is there any case that I should strictly use the second one instead of the first one?
I am asking this because I had a strange problem related to this, when I got a data from a fetch request and it made a difference when I used the first method and the second method.
fetch("some json array returning url").then(response=>{
response.json().then(data => {
data = data[0]
setState(data);
return;
// Vs
var data2 = data[0]
setState(data2);
return;
//based on which is uncommented
}
}
On my first block (using same variable data), the result was randomly changing. but when I used the second block, It became stable and predictable.
To be more specific on the results, for data that as the form ["data"], when using the first block, the result fluctuates between "data" and "d", where as while using the second block, it always returns "data"
Sorry for I can't put a fully reproducible example, But It would really help me out if there is any possible reason to prefer one over the other according to javascript language, based on the above simple use cases.
Usually, you don't want to be mutating the parameters of a function. Doing data = data[0] may cause bugs later on. It is better to create a new variable and make changes to that one, as with var data2 = data[0].
I don't see any problems with both of them, but in the 1st method it can make code more confusing to read because the variables have different types in different places. I would prefer solution 2
This is my code and I am trying to change value of object in packs object. But when I type it, Javascript somehow changes all three different objects, that have nothing in common. And this is the only line that changes packs, rest should stay the same, but it's all changing with this line. How?
console.log(packs[usedPack].levels[level].bestBy) //null
console.log(defaultPack.levels[level].bestBy) //null
console.log(mainPacks[usedPack].levels[level].bestBy) //null
packs[usedPack].levels[level].bestBy = nameTyped; //this changes values in three different objects
//packs[usedPack].levels[level] = nameTyped; //if I type like this, this does change only original object, rest stays the same
console.log(packs) //nameTyped
console.log(defaultPack) //nameTyped
console.log(mainPacks) //nameTyped
Edit: It was indeed problem with referencing. I was using constructor function and this function needed to deep copy complex objects. I was checking values and I used multiple loops to copy all values from objects, but it didn't work properly. I've changed all of this to JSON.parse(JSON.stringify()), and it's working now. Thanks for help.
The issue here seems like you're assigning some object by its reference.
In javascript, if you have two objects and you assign them like
a = b;
Now whenever you will change b, a will also be changed. To avoid this we do deep clone using the spread operator
// this now does not reference to b but clones it
a = {...b}
In your code, you might be assigning some objects like this. a=b
Maybe you're assigning packs, defaultPack, and mainPacks using some same object.
Updated
#David pointed out one thing and that is if you are having some complex structure (like objects within object) and then you clone it using spread operator, the inner objects will still reference the same object.
To resolve this, for easiness you can use lodash deepclone function
const clonedeep = require('lodash/clonedeep');
const deepClonedObject = clonedeep(originalObject);
This will deep clone and even if the objects are nested they won't refer to the same object.
Using this function to return the column names of the grid works fine. The issue comes when splicing the array that it returns.
The grid includes a checkbox as the first column so I want to remove that from the array. Here is that code.
var columnTitles = $(table).getGridParam('colNames');
columnTitles.splice(0,1);
The problem comes when I use this function multiple times (it's exporting to excel). The next time I export, the getGridParam function actually returns the spliced array of column names rather than the actual ones. It's as if it's being passed by reference or something.
Further proof that it's doing that and I don't just have a problem with a global variable or something...if I do the following code:
var columnTitles = $(table).getGridParam('colNames');
var columnTitles2 = $(table).getGridParam('colNames');
columnTitles.splice(0,1);
console.log(columnTitles2);
The value of columnTitles2 comes back as the spliced array. It might be something completely stupid, but what am I missing here?
The method getGridParam returns the reference of internal parameters used by jqGrid. You should be careful if you work with arrays or objects, colNames or colNames for example. It you need to modify the arrays for your purpose, but you don't want to change the values in jqGrid you should first make copy of the arrays and then modifies the copy:
var columnTitles = $(table).jqGrid("getGridParam", "colNames").slice();
columnTitles.splice(0,1);
I used slice to make the copy of internal colNames used by jqGrid.
I am using code lines like the following in order to fetch data from an intranet website:
util.setProp(obj, "firstNameOld", $(msg).find('#fname_a').text());
Now I have another function in the same file where I want to use the above again, resp. the value of that object - currently I am hard-coding this ('Test') for test purposes:
util.setProp(obj, "firstNameNew", 'Test');
How can I pass the value from the firstNameOld object in one function to the firstNameNew object in another function ? If a solution with global variables is better here than this would work as well.
Many thanks for any help with this, Tim.
I've never used the framework that includes util But I imagine that if there is a setProp() then there has to be a getProp() or something similar.
If so, you could do something like
util.setProp(obj, "firstNameNew", util.getProp(obj, "firstNameOld"));
This also relies on the assumption that you want to copy from two properties in the same object.
If not, then pass the desired source object in the getProp() call.
My guess is that functions (or properties) are called "firstNameOld" and "firstNameNew", so the first time you get it from selector, second time you want to do the same.
Try to use the local variable like that:
var text = $(msg).find('#fname_a').text();
//
util.setProp(obj, "firstNameOld", text);
//
util.setProp(obj, "firstNameNew", text);
Below is the snippet of the code. Basically, 'this.leaves' is a array. And I want to shift first array element, make copy of it (called frontLeaf), and unshift it to the original array, change some attributes from copied element, and put that element to the parent array element.
var frontLeaf = this.leaves.shift();
this.leaves.unshift(frontLeaf);
frontLeaf.leftChild = tmp;
frontLeaf.rightChild = this;
this.parent.leaves.push(frontLeaf);
My problem is that frontLeaf seems to be passed by reference that when I assign
frontLeaf.leftChild = tmp;
frontLeaf.rightChild = this;
above two lines of code seems to affect both elements in this.leaves and this.parent.leaves... So, How can I resolve this problem?
Javascript passes all objects by reference. The only way to do what you're looking for is to create an entirely new object, do a deep copy and then push it.
See this post for a sample solution using jQuery.
Yes, in JavaScript objects are always passed by reference. If you want a copy of an object, you'll have to write a deep-copy routine yourself.
I'm not sure exactly what you're trying to do (what is tmp? what is this? what is this.leaves an array of?), but maybe there is a way to do it without needing a copy?
Here's what I did when faced the same issue:
var newObj = JSON.parse(JSON.stringify(oldObj));