strange javascript variable re assignment issue - javascript

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

Related

Access Array with String key

I have two variables with JSON files. The first is a list of keys looks like this:
keylist = ["key1","key2","key3"]
The second one is generated from a database and looks like this:
data = {
"key1"{
#further data
},
"key2"{
#further data
},
"key3"{
#further data
}
}
Now I want to access the second element of the database with the key from the keylist
data.keylist[1];
Which doesn't work because the return of keylist[1] is a String? I did some research and the use of the window function was proposed. So I tried this:
window["data." + keylist[1]]();
Which leads to a "is not a function" error. What can I do to solve this problem?
As simple as that:
const mydata = data[ keylist[1] ];
Also, your code is correct from the point of syntax, but it tells completely different than you expect it to tell.
data.keylist[1];
tells JS that you expect to have an object called data which has a property called keylist and which is (most likely) type of array, and you want to get the second element of this array.
PS: And one more point here. Your question title is not completely correct because of the difference between Arrays and Object in JS.
There is no "string keys" for arrays in JS, so you cannot "access array with a string key". Well, truly speaking there are, but not for items of array. Array items only have numeric index, which you can use to access it. Objects, in contrast to arrays, may have named properties. So when you see something like that: data = myVar['data'], you can tell that you're dealing with an object, while data = someVar[0] can be both, an Array (most likely) or also an Object with key named '0'.
I don't think the issue you're having with your first example is because it returns a key. I believe the issue is because data doesn't have a property called keylist. Instead of that, try it as
data[keylist[1]]
and see if that works for you. The reason this one should work is that, in this situation, Javascript will evaluate the string return of keylist[1] and then use it as a string index for the data variable. Let me know if this works out for you :D
You can try using using something like this.
data[keylist[1]]

Console.log: the length of array is 0 and 1 at same time

About the console.log, i believe i have a case related to
Javascript array length of 0
In my console i got
my code related at 24
const lists = this.props.localData.lists;
if(lists.length === 0 ) {
console.log('lists',lists);
}
What is going on here?
if it is right in its way, how could i access lists[0](undefined)?
could anyone give me a hint?
Thanks in advance.
Some of the comments hinted at the issue here, but I don't see one that fully and correctly explains it. Here is what happened.
The initial one-line display of the array is created at the time you call console.log(). Simply viewing the log doesn't change anything (contrary to what one or two comments say). And subsequent updates to the array don't change this one-line view either.
But when you click the little triangle to expand the log entry, the expanded multiline display is created using the current array contents at the time you click the triangle. That is what causes the difference between the two. Your array was empty when you called console.log(), and you added an element to it after that but before you clicked to expand the display in the console.
If you want to get a full view of the array as it exists at the moment of the console.log() call, a good way to do it is to use JSON.stringify(). You can use the third argument to this function to pretty-print the result. So in your example, you might use:
console.log( JSON.stringify( lists, null, 4 ) );
Check this out: foo = [] create a new array and assigns a reference to it to a variable. Any other references are unaffected and still point to the original array.
foo.length = 0 modifies the array itself. If you access it via a different variable, then you still get the modified array.
Lucky with that.

Javascript object changing everywhere, if I change somewhere

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.

Angular JS: how to "load" an individual record from a json dataset?

I have json data, an array of 50 objects representing people. Each one has parameters like id and lastName.
I load this into my controller via a resolve, EmployeeResolve, and into a variable _this.employees
I also load via $state params from a previous page a rowNumber variable that holds the ID of the record the user clicked on: _this.rowNum = $stateParams.id;let's say the id is 5.
I would like to assign to a variable now the object number 5 (for want of a better way of explaining) so that in my HTML I can bind to it as in {{controller.lastName}}
What's the syntax for getting the 5th item out of employees?
UPDATE
After several helpful comments and answers, I've gotten this far (people are now packages):
_this.recordNum = Number($stateParams.id);
_this.packages = PackagesResolve;
_this.currentPackage = _this.packages.filter(function(pkg) {
return pkg.id === _this.recordNum;
});
$log.debug('package from filter', _this.currentPackage[0].status);
Note though, I expected after all this for _this.currentPackage to contain an object, so I could simply bind to its props in the html as in currentPackage.last_name But it does not. It's a resource and I need to use the above _this.currentPackage[0].status in the log statement to get anything. And that's not going to allow binding.
A colleague suggested modifying my resolve as such
PackagesResolve: function($log, MockDataFactory) {
return MockDataFactory.query({filename: 'packages'}).$promise.then(function(response) {
return response;
});
}
Adding the whole $promise.then part. No real difference.
To reiterate what I am trying to do:
PackagesResolve is getting a json array of 50 objects. I want to be able to get the CURRENT object when its row in a table of that json is clicked.
And no, #jdvp it's not a duplicate of that other post at all. I need to do this with Angular, not jquery or straight js.
If I'm understanding your issue correctly: the object returned by resolve is the resolved promise. The "data" of the resolved promise, which in this case would be the expected array of people info, is stored inside resolve.data. So for e.g. you have EmployeeResolve, you can reference the array and store it using:
Editing based on comments:
// Assuming you've done all error checking...
_this.employees = EmployeeResolve.data;
// Now _this.employees has the array of people info.
$scope.controller = {};
$scope.controller.variableName = _this.employees[$stateParams.id];
// Now, you can access your object in your template using controller.variableName.
Now although I wouldn't recommend writing code like that in your final version, I'm sure you get the gist. ;)
Additional notes: The reason I'm creating an empty object and storing it as controller on the scope is because your question stated it. I am assuming you have your own reasons for wanting to namespace your variable inside of controller.
Hope this helps!

jqGrid('getGridParam','colNames') odd behavior

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.

Categories