Javascript: What datatype is this? - javascript

I am using API to build something, but it's not well documentated, so I am moving by guess.
I have a 2 variables:
g.nodes and g.edges, when I do:
console.log(g.nodes);
console.log(g.edges);
I got output for g.nodes as:
Object {hello: Object, test: Object, test1: Object, test2: Object, test3: Object…}
and for g.edges as :
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
I understood that g.edges is an array, but what datatype is g.nodes?

for the first one g.nodes are simply a javascript object, but you can consider it as something like a HashMap or a key-value pair.
and the next one is an array or an array like object which could be a javascript object which all the keys are numbers, it could also be a arguments type object.
about how to go thru:
for g.nodes you can do this:
for(var key in g.nodes){
var value = g.nodes[key];
console.log(typeof value);
}
for arrays you'd better not use the first iteration method, because other than the actual data of the array it can also iterates all other properties defined in Array.prototype, for instance if you add this:
Array.prototype.myarray_prop = 1;
if you use for(var key in obj) method, in addition to the actual array values the myarray_prop will show up as a key, as far as when we usually use arrays we want to iterate the actual values of the array, not these kinds of extra props, it is not a good idea to use for(var key in obj);
so for g.edges you'd better do this:
for(var i=0;i<g.edges.length;i++){
var edge = g.edges[i];
console.log(typeof edge);
}

This is an interesting Question. Lets discuss this one by one:
console.log(g.nodes);
The output suggests that this is an Object. The properties of this Object are:
hello
test
test1
and so on...
Secondly there is an array of an object. This is essentially a JavaScript collection of objects.
A good way not to encounter such things is by debugging your Scripts properly.
A good way to debug JavaScript:
Whenever you feel like that you are not understanding the flow of JavaScript, run that script in FireFox, FireBug and insert break points at all important locations. Then FireBug will show you the type and state of each variable.
An Example of Debugging:
function SayHello(){
debugger;
var msg = "Hello World";
console.log(msg);
}
The code will stop at debugger and you can see the steps from there. You can even see the type of variable "msg".
Hope this helps you a long way.

Related

Arranging array of nested objects by one of the nested variables - Angular JS

I am using Angular JS to provide output for an endpoint, the logic to achieve this output is created in the controller as follows:
myApp.controller('AnalyticsController',['$scope','$rootScope','$location','token_service','api_service',function($scope,$rootScope,$location,token_service,api_service){
var analytics = api_service.get_analytics()
analytics.then(function(response){
$scope.analytics = response;
$rootScope.spinner = false;
})
}])
Please note: get_analytics is from another script and the data comes from that service.
The output I get is a nested object, in the console it looks like as follows:
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
0:Object
Devices:Array[1]
Id:"eefd439f-1e2e-481e-815d-0a2ce9a38bbe"
KeyHolderDeviceConfiguration:null
Name:"Shaun m "
Photos:null
Type:2
__proto__:Object
1:Object
2:Object
There are more objects in the list but I figure there's no point opening them as is just repetition.
I wish to separate each nested object in the actual output, so there is one set of results for each 'Name'. Any idea how I would go about doing this?
I saw a similar problem - AS3 - Sorting an array of nested arrays - but I am unsure how to apply this to my problem. Any ideas? Many thanks in advance.
When you use .then the response contain more than property
you should assign data like this
$scope.analytics = response.data;

Splice on copied array removes object from parent / master array

I have what you may call a parent array, a master array. On page load, a json_encoded PHP array containing information about every user on the site is assigned to a JS variable - var all_users = <?php echo $users;?>;. A console.log of this array looks like this...
[Object, Object, Object, Object, Object, Object, Object, Object, Object]
0: Object
user_id: "4"
registered: "2015-02-15 12:54:34"
...etc
1: Object
user_id: "5"
...etc
In an external .js file I have a few event handlers for various filtering options. At the moment these filters work by sending an AJAX request to the server, querying the database, and then returning the data. This is great, but it's unnecessary to query the database every single time (there will only be around 50 records) hence changing my approach to the JS array.
My solution therefore was to start by copying the contents of all_users to a new variable, display_users, every time the function below is called (so that to reset display_users to contain all users). The purpose of this new variable is to then be able to remove any records that do not match the user's filters. So for example a search for user_id = 4 would result in the second, third, fourth, ... objects being removed from display_users, leaving just those that match.
var display_users = [];
function update_users (type) {
display_users = all_users;
i = 0;
$.each(all_users, function() {
var user = this;
$.each(user, function(k, v) {
// show_admin_only is true or false
if (show_admin_only) {
// if the key is_admin has a value of 0 they are not an admin, remove them from the display users array
if (k == 'is_admin' && v == 0) display_users.splice(i,1);
}
});
i++;
});
// pass the array through to a jQuery template
}
The problem, however, is that the splice is causing an error. The first time the function is ran all is great, however on the second time Chrome reports two warnings, 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead. and 'webkitIndexedDB' is deprecated. Please use 'indexedDB' instead.. After these errors, any future runs of that function results in the removal of records from both arrays, the master and the copy.
Given this, I'd guess that display_users is acting as a pointer to the master array, all_users, but then that wouldn't make much sense to me, and is why I'm now at a complete loss. A console.log of both arrays after i = 0 outputs this...
Run 1
[Object, Object, Object, Object, Object, Object, Object, Object, Object]
[Object, Object, Object, Object, Object, Object, Object, Object, Object]
Run 2
[Object, Object, Object, Object, Object, Object, Object, Object]
[Object, Object, Object, Object, Object, Object, Object, Object]
// for every run, -1 Object from BOTH arrays
I added a console.log(user); within $.each(user, function(k, v) { and it is during these second, third, ... runs that it begins to output hundreds of Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…} as well as those expected, such as Object {user_id: "4", registered_date: "2015-02-15 12:54:34" ... }.
Has anyone any idea why this is happening? Sorry for the long post for what is probably a very simple fix...!
For duplication use:
display_users = all_users.slice();
Your problem is right here
display_users = all_users;
It is not copying the array but creating one more reference to the same array. If you wish to copy the array you ca use Array.slice() instead
var display_users = all_users.slice(0);

JavaScript objects from Eloquent JavaScript Chapter 4

JSFiddle: http://jsfiddle.net/TkV2y/3/
var chineseBox = {}; //create an object
chineseBox.content = "chineseBox"; //put a key/value pair inside chinesebox
alert(chineseBox); // why does the alert display { Object object }?
alert("content" in chineseBox); //returns true, as expected
alert("content" in chineseBox.content); //why does this alert not show up??
My questions are:
Why, when I do alert(chineseBox), do I not get the contents of the chineseBox object? I'd expected to see this:
{content: "chineseBox"}
Instead, I got [object Object] in the alert.
Why does the third alert I have there—alert("content" in chineseBox.content);—not show up?
That is the default .toString() implementation for objects in most JavaScript engines. To see the contents of the object, try: alert(JSON.stringify(chineseBox));
If you check the browser console, you'll find a type error. You cannot use the in operator on non-objects. This doesn't work (errors out): 'foo' in 'bar', but this does work (returns false): 'foo' in new String('bar')
Is the result of invoking toString upon an object Since they are objects and there is no specific format they should use, JavaScript wouldn't know how to serialize the object. If you want to see its content you need to use JSON.stringify.
The in operator searches for content inside an object. You can not search for content inside a primitive value since it has no methods or properties; hence, it will fail. You can test this by searching in a empty object; you'll see you get false as a response.

Dynamically Reading Array Values form a JSON Object

I am working on a function that accepts a JSON object as a parameter. Each property of the object passed in will be an array. I need to determine the length of each of these arrays.
What I won't know in advance are: the names of the properties, or how many properties there are.
How can I determine the length of each array? Again, I can't refer to any of the properties/keys explicitly because I won't know their names ahead of time. How do I reference each unknown property as an array?
Thank you in advance,
-RS
You can iterate over the object using a for...in loop to access each property.
for (var key in myObject) {
// Check to make sure the property is not part of the `Object` prototype (eg. toString)
if (myObject.hasOwnProperty(key)) {
console.log(key, myObject[key].length);
}
}
In the above example, we iterate over the properties of the object myObject and we log out their length values (assuming they are all arrays).
If by "JSON object" you mean that it is a string of JSON, you can first parse myObject into a true object by using myObject = JSON.parse(myObject) (which works in modern browsers) or myObject = eval("(" + myOjbect + ")") which is considered unsafe (but works in all browsers). After parsing, you may use the above technique to fine array lengths.
Note: Since you updated the post to specify that the object is JSON, you may not need the hasOwnProperty check, but it is safer to always use this test.
Use JSON.parse to convert JSON data to JS Objects, and then you can use Array's length etc properties.
var myObject = JSON.parse(myJSONtext, reviver);
JSON Reference: http://www.json.org/js.html

How to check if an argument is an object (and not an array) in JavaScript

After testing out instasnceof I found that it will return true if the argument is an array or an object literal.
function test(options){
if(options instanceof Object){alert('yes')}//this will alert for both arrays and object literals
}
test({x:11})// alerts
test([11])// alerts as well but I do not want it to
Is there a way to test if the argument "options" is an object literal?
P.S. I am creating a module that will allow the user to access its configuration options, and I want to test if the argument is only an object literal or not?
is there a way to test if the argument "options" is an object literal?
No, because it makes no sense. You can test whether it's an object, but how it was created (via a literal in the call to your function, via a literal elsewhere, through new Object, by deserializing a JSON string, ...) is not information that's maintained.
after testing out instasnceof i found that it will return true if the argument is an array or an object literal
Correct. Arrays in JavaScript are objects (and not really arrays).
If you want to test that an object is a plain old object, you can do this:
if (Object.prototype.toString.call(options) === "[object Object]") {
// It's a plain object
}
But there's really no reason to do that. It's not your problem. As long as what they pass you has the properties you expect, don't try to limit the object further.
p.s. i'm making a module that will allow the user to pass it configuration options and i want to test to make sure that the argument is only an object literal.
Why? If the user wants to use an object that hasn't been declared as a literal right there and then, why would you care? If they want to use an object that they've created via a different constructor function (e.g., rather than just a plain object), again, why would you care?
function isPlainObject(o) {
return Object(o) === o && Object.getPrototypeOf(o) === Object.prototype;
}
However, you can't test wether o was declared as a literal or instantiated somehow else - you can just test whether it's a plain object without any constructor than Object.
If you're trying to forbid arrays, you can just do this:
var isObject = options instanceof Object;
var isArray = options instanceof Array;
if(isObject && !isArray)
{
alert('yes');
}
An alternative solution would be to use Lodash:
_.isPlainObject(value)
Here is the documentation:
https://lodash.com/docs/4.17.15#isPlainObject

Categories