What is meant by obj[''] in Javascript? - javascript

Toward the bottom of this javascript file, there is a line
return map[""];
where map is an associative array of objects with parent/child relationships. After calling map[""] the returned structure is a transformation into a hierarchical array. What is really going on under the hood here and where is this syntax documented? (It's hard searching for such empty strings on the net.)

It just reads the empty string property of map, just like how this:
map["a"]
is the same as
map.a
However, you can't just do
map.
so that's why they do
map[""]
This is generated by the function find which ends when the strings become empty, which is why the final element will be found in map[""].

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]]

Keeping insertion order in Angular

I have a HTML fragment that iterates over key, value collection. When I create an object and put some value in, then iterate trough that object via HTML fragment, all works perfectly.
However since I need keys in specific order, I'm using a Map instead of plain object. This time when I debug I can see that my insertion order was preserved, but for some reason the HTML fragment which iterates over collection doesn't seem to know how to do so. I see nothing on my screen when I use the map object, opposed to the regular object when I see unordered content
tr ng-repeat="(key, value) in rowTitlesValues"
Is how my HTML fragment looks like, when I switch rowTitlesValues back to object works again, what am I doing wrong, and how does one keep insertion order or how do I sort object so it's keys are in custom order?
From Angular reference on ng-repeat (link):
Iterating over object properties
It is possible to get ngRepeat to iterate over the properties of an object using the following syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>
You need to be aware that the JavaScript specification does not define the order of keys returned for an object. (To mitigate this in Angular 1.3 the ngRepeat directive used to sort the keys alphabetically.)
Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser when running for key in myObj. It seems that browsers generally follow the strategy of providing keys in the order in which they were defined, [...]
If this is not desired, the recommended workaround is to convert your object into an array that is sorted into the order that you prefer before providing it to ngRepeat. You could do this with a filter such as toArrayFilter or implement a $watch on the object yourself.
Additionally, I do not think Angular 1.x knows how to iterate over a Map. I believe this line in the code proves it:
collectionKeys = [];
for (var itemKey in collection) { // iterates your object using `in`, not `of` or `Map.forEach()`
...
}
// ng-repeat then iterates the collectionKeys to create the DOM
So you will probably need to act as Angular docs suggest:
[...] convert your object into an array that is sorted into the order that you prefer before providing it to ngRepeat. You could do this with a filter such as toArrayFilter or implement a $watch on the object yourself.

Function param array, how to affect reference = [] or reference.concat(array2)? [duplicate]

This question already has an answer here:
Mutate JavaScript Array Inside Function
(1 answer)
Closed 8 years ago.
So it could just be I'm crazy tired but I can't seem to figure this out.
I've been picking up javascript which I'm finding horrible coming from actionscript 3 where everything was typed. I had a function that referenced two array variables directly, I later needed to use it again for a different data set so I've altered it to take parameters and now it's breaking.
I have one array full of elements, the 2nd is empty. When I call the function, a random element is removed from the first array and pushed into the 2nd array, that element is also returned by the function. If the 1st array is empty I have concat the 2nd array to fill it back up. The goal was to randomly iterate through the elements and not have the selected elements show up again until I had finished a full cycle.
Prior to concat I was using slice(which should work just as well?), the problem I believe is that I know have a parameter that is redefined when I do 'array = array2.slice()', concat doesn't seem to work around that. I don't know if returning the single sliced element from the first array is bad if I'm expecting a string, I think slice is returning an array with the single element, easy fix there though by adding [0] to the return statement.
Heres the code:
//Gets a random element from array, that element is moved from the 'src' array to the 'bin' array,
//this allows random selection without choosing the same element until all of 'src' array elements have been picked
function getRandomElement(array_src,array_bin){
//Randomly selects a tweet from the que, then stores it in another array so each tweet shows once before recycling
if(array_src.length==0 && array_bin.length>0) {array_src.concat(array_bin);} //Recycles array elements when the src array is empty
var randomElement = array_src.splice(Math.floor(Math.random()*array_src.length),1); //Grab a random array element
array_bin.push(randomElement);//array elements stored here to be recycled
return randomElement;
}
I think I could maybe use an object with two properties pointing to the arrays and pass those in, though it'd be nicer if there is a better way. I could also use push on array_src looping through the array_bin to work around that issue if there isn't any other way.
I wouldn't say this is a duplicate Felix. The answer you provided is pretty much the same, but the question itself is phrased differently, I wasn't aware of the term mutate, finding the question/answer wouldn't be easy, none of the suggested links SO provided were relevant. Worth keeping up for making the answer more discoverable to those unaware of the mutate term.
I have a hard time understanding the problem, but I think you are wondering why array_src.concat(array_bin) doesn't seem to do anything?
That's because .concat returns a new array. If you want to mutate the existing array_src array, you can use .push:
array_src.push.apply(array_src, array_bin);
FWIW, this has nothing to do with strong typing. JavaScript (and I guess ActionScript as well), is pass-by-value. That implies that assigning a new value to array_src doesn't change the value of the variable that was passed to getRandomElement.
But since arrays are mutable in JavaScript (and ActionScript I assume), you can mutate the array itself.

Counting object pairs in JSON array

ive got a problem getting parameters from a json chain, the json I got looks something like this
[{"aa":"bb","ccc":"ddd","eeee":"ffff","ggggg":"hhhhh","iiiiii":"jjjjjj","kkkkkkk":"lllllll"}]
Im trying to count how many pairs there are inside the '{}' but i dont know how. I tried json.length and json[0].length, the first one gave me back the value '1' and the second one undefined.
Your json object is an array containing one object. So the length is 1. The object in the array has multiple properties (key/value pairs).
So in most modern browsers (except IE), this would work for you:
Object.keys(json[0]).length
Check out the answers here of various techniques for iterating/counting properties of an object in JavaScript:
How to efficiently count the number of keys/properties of an object in JavaScript?

what does "var links = [].slice.apply(document.getElementsByTagName('a'));" really do?

I don't understand how this works:
var links = [].slice.apply(document.getElementsByTagName('a'));
It creates an empty array but I don't completely get the rest. What do slice and apply really do together in this script?
document.getElementsByTagName() and similar DOM methods return an array-like structure, a node list, instead of a true array. This is a common trick to convert it into a true array. It is also commonly used with the arguments special variable, another array-like structure. The slice method of the Array object would normally expect an array, and returns an array, but this way you can pass in something that is not technically an array. A slightly more readable, and arguably better version is this:
Array.prototype.slice.apply(document.getElementsByTagName('a'));
This basically converts the nodeList object retrieved from the getElementsByTagName into regular javascript array, to be able to use array methods on it.

Categories