How to get count object in javascript? [duplicate] - javascript

I have an array filled with objects. It contains 23 items in total, however when I perform a .length on it, it returns 20.
// Get the new routes
var array = PostStore.getPostList();
console.log(array.objects);
console.log(array.objects.length);
Image of what my console returns:
What's going wrong here?

The problem is probably that the array changed between the time you logged it and the time you opened it in the console.
To get the array at the logging time, clone it:
console.log(array.objects.slice());
console.log(array.objects.length);
Note that this won't protect against the array element properties changing. If you want to freeze them too, you need a deep cloning, which is most often possible with
console.log(JSON.parse(JSON.stringify(array.objects.slice()));
This won't work if the objects aren't stringifyable, though (cyclic objects, very deep objects, properties throwing exceptions at reading, etc.). In that case you'll need a specific cloning, like my own JSON.prune.log.
A alternative to logging is also, in such a case, to debug. Set a breakpoint and look at the objects while the code is stopped.

Related

TypeScript: empty array is initialized with values, and those values cannot be changed

Now, this might just be me not knowing some basics of how TypeScript works, as I am pretty inexperienced with it, but all my attempts to find a solution to this issue have so far failed.
In one of my functions I am trying to get an item-by-item disjunction of two boolean arrays. However, when I am initializing an empty array to then fill with new values, something strange happens.
let res = new Array<boolean>();
console.log(res)
Output of the freshly initialized array "res"
As you can see, while array is depicted as empty in its collapsed form, opening it for more info reveals that it actually already has 5 "false" values in it. (note: it is not always 5 falses, this is just an example)
When the function then starts pushing new values into it, while those values are depicted correctly in the array's preview, in reality there are still the same five "false" values inside it, and those are not being changed in any way. Furthermore, logging specific items from this array returns correct values
res.push(a[i] || b[i])
console.log("disjunction at position " + i.toString())
console.log(a[i])
console.log(b[i])
console.log(res[i])
console.log(res)
Console output
This function then returns a new boolean array to be pushed into an array of arrays. When I am logging this array of arrays, it depicts not arrays of values the function filled them with, but instead those weird values that have been put there with initialization. This does not seem to affect the first array (and only that one).
Array of arrays
As I said, I might just miss some crucial information about how arrays in TS/JS work. Right now I am a bit lost, so any help would be appreciated!
Turns out it was just me not knowing how dev console works. The big array of arrays is being filtered after being filled up, and because console shows all the arrays in real time, filter causes it to retrospectively depict them as full of falses. Temporarily removing filter proved this hypothesis.

How do I iterate through objects stored in a firebase array in JavaScript?

At the moment I am storing a few objects in Firebase. After successfully retrieving the items from Firebase and storing them in a firebaseArray, I want to further thin out the unwanted elements by deleting the elements in the firebaseArray that do not have the desired property. Consider my code at the moment, that does not do as wanted, however there are no errors in the console:
var querylatestPosts = firebase.database().ref("Topics");
$scope.latestPosts = $firebaseArray(querylatestPosts);
console.log($scope.latestPosts) ;
$scope.latestPosts.forEach(function(el) {
if ($scope.checkWorldview(el) == false) {
delete $scope.latestPosts.el ;
}
});
(Note I am unable to log 'el' in the console, nor does the forEach seem to execute, as I can log nothing in the function in the console)
The 'checkWorldview' function behaves as expected when elements are fed in different instances and returns false if the required property is not present in the element under consideration. Thus if the function returns false, I want to delete the specific element in $scope.latestPosts that does not contain the wanted property.
I hope this is clear, thank you in advance for any help you can offer!
The way you are using the $firebaseArray isn't recommended by the docs (see here), which state that $firebaseArray is read only and should not be manipulated.
So you have a few options:
Instead of filtering the array on the client-side, you should modify the query you're using to retrieve data from Firebase to only get elements that have the desired property (ex: use 'equalTo' in the query)
OR
Don't use a $firebaseArray because you're not using it in the way it was intended. Use a regular, good ol' fashion JavaScript array instead.
** Also, just a general comment: don't delete elements from an array as you loop through it as this is generally bad practice (we don't expect arrays to have elements added/removed while we loop through them). Instead, use Array.filter.

How to assign values to objects through a variable that is just a reference to them?

I couldn't really word the question less vaguely, but I think you will understand...
I am developing a game engine in Javascript, and the Scene object, which is a container of many things, has a method that is supposed to change one array in it, specifically the one holding all the things that can be drawn.
This array is accessed like this:
scene.internals.draw
The problem is, it is referenced many times in the method, and I think that the name/path might change. Naturally, I don't want to change every reference to it in the method each time I change the the array's path, so I did this:
var location = scene.internals.draw;
Now, the actual method code and the algorithm can stay intact, and if the name/path of the array in the scene changes, I only need to change that one line.
And it works pretty well for the most part. I can .push(obj) to it, etc, but at one point, I need to "disect" the array, ie, split it in half, add something, and then put it back together, like this:
buff1 = location.slice(0, i); //First slice of the array.
buff2 = location.slice(i, location.length); //Second slice of the array.
//Add something in between those slices.
buff1.push(ob);
location = buff1.concat(buff2); //Problems here!
This worked well while location was just scene.internals.draw, as it changed the array directly. But now, I assign the new value to the local location variable, not the desired scene.internals.draw one!
Question: how can I, using the = operator, assign values to "real" objects, instead of the variables that contain references to these objects (like location)?
The obvious solution would be this, at the end of the method:
scene.internals.draw = location.slice();
This is OK, the only side effect is that I will have to write the original name twice, and edit it twice, which isn't such a big issue. But, I maybe find myself in other situations where I just might need that functionality, so I'd still like an answer.
There is no assignment by reference in javascript, so you cannot do this. What you are doing is usually mistaken for assignment by reference but it is in fact a copy of a reference value which has implications like this.
You probably have a deeper problem somewhere since you are doing this but I don't wanna get into that.
You could do this:
location.splice( 0, location.length ); //Remove all items in the array
location.push.apply( location, buff1.concat(buff2) ); //Push the buffers into the array
To use your term, there are no "real" objects in Javascript - there are only objects, and the variables that hold references to them.
When you assign to location you're just creating an additional reference to an object. The system has no knowledge of which "real" object it was, nor of any other variables that may hold references to it.
So when you reassign to location you're just overwriting that particular reference. Any other original references to the object will stay pointing just where they were.

How do I compare Application.windows[x] to Application.activeWindow?

I'm creating a Firefox extension, in which I want to iterate through the Application.windows array and check if one of its elements is the same as Application.activeWindow.
The mentioned excerpt from my code looks like this:
for (var i in Application.windows) {
if (Application.windows[i]==Application.activeWindow) alert('debug');
// there was some more complex code than alert('debug'),
// but since it didn't work, I decided to try with an alert
}
Unfortunately, the 'debug' alert is never viewed. Thus I decided to try this code (with only one window opened):
// the following code runs in an event listener for window.onload
alert(Application.windows[0]);
alert(Application.activeWindow);
alert(Application.windows[0]==Application.activeWindow);
Firefox displayed 3 alerts: the first one was [object Object], the second one - [xpconnect wrapped fuelIWindow], and the last one (which didn't surprise me) said false. So it seems the objects I'm trying to compare have different types. How can I deal with this? Thanks in advance.
You have two problems.
The first is that XPConnect doesn't support array-valued properties, so when FUEL (or STEEL or SMILE) return an array, they're actually returning an nsIVariant of internal objects! On the other hand, single-valued objects return an XPConnect wrapper which hides the internal object.
The second is that each time you access windows or activeWindow, new internal objects are created, so even two calls to activeWindow return different objects.
The way around this is to avoid FUEL and enumerate the windows directly using the window mediator.

How come setting value in one array key is setting in another key?

I have an array of objects with various objects within to hold UI values. I wanted to have a button so that element 0's values are replicated through the whole array. However I noticed that setting one set them all. Here is an example without using any looping:
console.log('manual 3: ', lis[3].spacer.divider.type); // prints 'none'
lis[1].spacer.divider.type = 'bananas';
console.log('manual 3: ', lis[3].spacer.divider.type); // prints 'bananas'
I am completely baffled how setting lis[1] also set lis[3]
They must both be references to the same object.
If they're DOM nodes, you can copy them using cloneNode().
Watch out for IE bugs - it has a habit of not cloning properly (for example cloning a <select> doesn't maintain the selectedIndex).
See also What is the most efficent way to clone a JavaScript object? for cloning objects.
Because the variables are reference variables and they all reference the same object and as a result it looks like changing one changes all of them, really they are all the same underlying object.
If you want lots of unique arrays they should all be created as a fresh or be clones of each other.
It turns out I was referencing the same object. Thanks. It didn't click to me since all the other objects above (spacer,lis) were unique. I accidentally was setting divider to a member default of spacer instead of a function returning the default.
Thanks!

Categories

Resources