The Linq-For-Javascript library contains functions that convert between "jQuery objects" and "Enumerable objects": toEnumerable() and TojQuery(). Consider the difference between these two lines:
$('tr'); // returns array of tr
$('tr').toEnumerable().TojQuery(); // returns array of tr[1]
Converting from jQuery to Enumerable and back to jQuery does not give you what you started with. The end result is an array of arrays of elements, with each sub-array having a length of 1. I do need to make use of Enumerable, so this is just a convenient example of my problem.
This means that to get the id of an element, you'd need to do the following:
$('tr')[0].id; // returns "myID"
$('tr').toEnumerable().TojQuery()[0][0].id; // returns "myID"
I'm surprised of this, because even though I've allegedly gone back TojQuery(), the object returned by TojQuery() does not work with typical jQuery calls:
$('tr').find('td').length; // returns 170 (in my case)
$('tr').toEnumerable().TojQuery().find('td').length; // returns 0 (BAD)
I would like it if both lines returned 170, but apparently Linq-For-Javascript doesn't work that way.
So, my questions:
Why is this?
Am I doing it wrong?
If not, any good workarounds? (convert array of 1-element arrays to array of elements?)
Thanks!
JQuery handles operations according to types. In the first line of the code, if finds all HTML TR objects and by the help of this information it can attach necessary functions to the found objects.
$('tr').find('td')
However, it could not understand after you change it to enumarable object since it is no longer seems to be a HTML Object instead it becomes any other type of object. Thus, jquery cannot attach a function to it.
$('tr').toEnumerable()
Related
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.
This is more a general question about the inner workings of the language. I was wondering how javascript gets the value of an index. For example when you write array[index] does it loop through the array till it finds it? or by some other means? the reason I ask is because I have written some code where I am looping through arrays to match values and find points on a grid, I am wondering if performance would be increased by creating and array like array[gridX][gridY] or if it will make a difference. what I am doing now is going through a flat array of objects with gridpoints as properties like this:
var array = [{x:1,y:3}];
then looping through and using those coordinates within the object properties to identify and use the values contained in the object.
my thought is that by implementing a multidimensional grid it would access them more directly as can specify a gridpoint by saying array[1][3] instead of looping through and doing:
for ( var a = 0; a < array.length; a += 1 ){
if( array[a].x === 1 && array[a].y === 3 ){
return array[a];
}
}
or something of the like.
any insight would be appreciated, thanks!
For example when you write array[index] does it loop through the array till it finds it? or by some other means?
This is implementation defined. Javascript can have both numeric and string keys and the very first Javascript implementations did do this slow looping to access things.
However, nowadays most browsers are more efficient and store arrays in two parts, a packed array for numeric indexes and a hash table for the rest. This means that accessing a numeric index (for dense arrays without holes) is O(1) and accessing string keys and sparse arrays is done via hash tables.
I am wondering if performance would be increased by creating and array like array[gridX][gridY] or if it will make a difference. what I am doing now is going through a flat array of objects with gridpoints as properties like this array[{x:1,y:3}]
Go with the 2 dimension array. Its a much simpler solution and is most likely going to be efficient enough for you.
Another reason to do this is that when you use an object as an array index what actually happens is that the object is converted to a string and then that string is used as a hash table key. So array[{x:1,y:3}] is actually array["[object Object]"]. If you really wanted, you could override the toString method so not all grid points serialize to the same value, but I don't think its worth the trouble.
Whether it's an array or an object, the underlying structure in any modern javascript engine is a hashtable. Need to prove it? Allocate an array of 1000000000 elements and notice the speed and lack of memory growth. Javascript arrays are a special case of Object that provides a length method and restricts the keys to integers, but it's sparse.
So, you are really chaining hashtables together. When you nest tables, as in a[x][y], you creating multiple hashtables, and it will require multiple visits to resolve an object.
But which is faster? Here is a jsperf testing the speed of allocation and access, respectively:
http://jsperf.com/hash-tables-2d-versus-1d
http://jsperf.com/hash-tables-2d-versus-1d/2
On my machines, the nested approach is faster.
Intuition is no match for the profiler.
Update: It was pointed out that in some limited instances, arrays really are arrays underneath. But since arrays are specialized objects, you'll find that in these same instances, objects are implemented as arrays as well (i.e., {0:'hello', 1:'world'} is internally implemented as an array. But this shouldn't frighten you from using arrays with trillions of elements, because that special case will be discarded once it no longer makes sense.
To answer your initial question, in JavaScript, arrays are nothing more than a specialized type of object. If you set up an new Array like this:
var someArray = new Array(1, 2, 3);
You end up with an Array object with a structure that looks more-or-less, like this (Note: this is strictly in regards to the data that it is storing . . . there is a LOT more to an Array object):
someArray = {
0: 1,
1: 2,
2: 3
}
What the Array object does add to the equation, though, is built in operations that allow you to interact with it in the [1, 2, 3] concept that you are used to. push() for example, will use the array's length property to figure out where the next value should be added, creates the value in that position, and increments the length property.
However (getting back to the original question), there is nothing in the array structure that is any different when it comes to accessing the values that it stores than any other property. There is no inherent looping or anything like that . . . accessing someArray[0] is essentially the same as accessing someArray.length.
In fact, the only reason that you have to access standard array values using the someArray[N] format is that, the stored array values are number-indexed, and you cannot directly access object properties that begin with a number using the "dot" technique (i.e., someArray.0 is invalid, someArray[0] is not).
Now, admittedly, that is a pretty simplistic view of the Array object in JavaScript, but, for the purposes of your question, it should be enough. If you want to know more about the inner workings, there is TONS of information to be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
single dimension hash table with direct access:
var array = {
x1y3: 999,
x10y100: 0
};
function getValue(x, y) {
return array['x' + x + 'y' + y];
}
With jQuery I can do
$('#some_id').find('div').first()
or
$('#some_id').find('div').last()
and get an answer like
[<div>something</div>]
If I do
$('#some_id').find('div')[3]
I get answer like
<div>something</div>
How do I specify an index in array and get an array just with that object?
I would love to do something like
$('#some_id').find('div').somefunc(3)
and get
[<div>something</div>]
I know there is slice(), but I feel like there is some simpler function that I have over looked in my hours of searching.
I know there is :nth-child() but again, it feels like there is some other function that I can call the way I call first() or last().
I am trying to chain some functions together to have one line that does what I need.
If there is not other ways, then I guess that is fine. I just wanted to make sure.
Thanks!
You can use .eq():
$('#some_id').find('div').eq(3) // This will return the fourth div inside #some_id
Since .eq() is 0-based index, if you want to get the third div you need to use:
$('#some_id').find('div').eq(2)
You can also use .get(index)
$($('#some_id').find('div').get(3)); // jQuery obj
or
[$('#some_id').find('div').get(3)]; // Array
The .get() method grants access to the DOM nodes underlying each
jQuery object. If the value of index is out of bounds — less than the
negative number of elements or equal to or greater than the number of
elements — it returns undefined.
I'm wondering, why do some elements appear like an array and others like HTMLSpanElement. I've attached a picture as I'm not sure how to describe this otherwise.
The following log is made via
log(returner);
log(returner[0]);
Is returner a jQuery object as a result of $() ? $() will always return an array, even if there is one or zero elements inside of it. Without specifying an index in your first console.log, the entire contents of the array are outputted. In the second console.log, you include an array index, so only the element matching that index is outputted.
Because the element that appears like an array IS an array - it's an array of DOM element objects (HTMLSpanElement, etc).
When you log the first element of the array with returner[0], that element is a DOM object, so it logs it as an object.
Because (it looks like) returner is not an element, but an array of elements.
By this I mean when calling .push() on an Array object and JavaScript increases the capacity (in number of elements) of the underlying "array". Also, if there is a good resource for finding this sort of information for JS, that would be helpful to include.
edit
It seems that the JS Array is like an object literal with special properties. However, I'm interested in a lower level of detail--how browsers implement this in their respective JS engines.
There cannot be any single correct answer to this qurstion. An array's mechanism for expanding is an internal implementation detail and can vary from one JS implementation to another. In fact, the Tamarin engine has two different implementations used internally for arrays depending on if it determines if the array is going to be sequential or sparse.
This answer is wrong. Please see #Samuel Neff's answer and the following resources:
http://news.qooxdoo.org/javascript-array-performance-oddities-characteristics
http://jsperf.com/array-popuplation-direction
Arrays in JavaScript don't have a capacity since they aren't real arrays. They're actually just object hashes with a length property and properties of "0", "1", "2", etc. When you do .push() on an array, it effectively does:
ary[ ary.length++ ] = the_new_element; // set via hash
Javascript does include a mechanism to declare the length of your array like:
var foo = new Array(3);
alert(foo.length); // alerts 3
But since arrays are dynamic in javascript there is no reason to do this, you don't have to manually allocate your arrays. The above example does not create a fixed length array, just initializes it with 3 undefined elements.
// Edit: I either misread your question or you changed it, sorry I don't think this is what you were asking.