how many nested object should i define in javascript? - javascript

I am new in javascript.
Here I am wondering about how many nested or inner object could i
define in javascript
how to find first 2 nested object's key in js.
i also search it on google but i didn't get any solution.
here is example what i want!
var obj = {
a:{
b:{
c:{
//so on
}
}
}
}
thanks in advance.

Here I am wondering about how many nested or inner object could i define in javascript
There is no specified limit.
In the case of an object initializer such as the one you've shown, eventually you'll run into some sort of limitation of a particular JavaScript engine running the code, e.g., around its parsing / processing of the initializer, but nothing defined in the specification.
If you build objects dynamically on your own, for instance like this:
// Don't run this code!
var obj = {};
while (true) {
obj.child = {};
obj = obj.child;
}
...there's no reason to believe you'll run into anything other than a memory limit related to the number of objects you're creating (not their nesting).
how to find how many objects keys are defined in js
In one particular object, you can get an array of its own (not inherited) properties via Object.getOwnPropertyNames and Object.getOwnPropertySymbols, then take the length of the array. To find out how many properties the object has and how many the objects its properties refer to have, you'd use a recursive search — but beware of cyclic structures.
For instance:
const obj = {
a: {
b: {
c: {
}
}
}
};
function countProps(target, recursive = false) {
const ownProperties = [
...Object.getOwnPropertyNames(target),
...Object.getOwnPropertySymbols(target)
];
let count = ownProperties.length;
if (recursive) {
for (const key of ownProperties) {
const value = target[key];
if (value && typeof value === "object") {
count += countProps(value, true);
}
}
}
return count;
}
console.log(countProps(obj, true));

answer for first question.
There is not any restriction for nested object. you can define nested object as per you want until your memory limit exceed.
answer for second question.
here is a code to find keys from nested objects but it is work for only 2nd nested object.
for (var key in ob) {
if (!ob.hasOwnProperty(key))
continue;
var obj = ob[key];
help += "</br>"
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;
help += " ---) \""+key+" "+prop+"\"</br>"
}
}
tell me if you got what you want.

Here I am wondering about how many nested or inner object could i define in javascript?
In the specification of JS it is not defined.
You can define nested or inner object how many you want.
But: do not forget: every object in your code need place in PC memory. And if you have to many objects you browser will not work correctly.
How to find how many objects keys are defined in JS?
With following metods:
Object.getOwnPropertyNames
Returns an array containing the names of all of the given object's own enumerable and non-enumerable properties.
Object.getOwnPropertySymbols
Returns an array of all symbol properties found directly upon a given object.
you will find the length of how many objects keys are defined in your object.

Related

How can google DataLayer be converted into javascript object with key values for variables?

When you use Google Analytics DataLayer on your website you have it as a global variable dataLayer.
You can add your own events variables into it.
How can you convert all variables inside it to an object like
{var:value}
You access it like any other object:
var dataLayer = [{
myVar1: 'val1',
myVar2: 'val2
}]
var myVar1 = dataLayer[0].myVar1;
var myVar2 = dataLayer[0].myVar2;
I do not quite understand your heated response to nyuens answer. Firstly, since this is javascript so an array is also an object, secondly the dataLayer is an array of objects or, as we call it in JavaScript, an object (it's called JavaScript Object Notation after all). So you have an array with numeric indexes where every element is an object (which might in turn contain other arrays and objects).
I strongly disagress with nyuen's suggestion to adress elements in the dataLayer with the numeric index, though. If you push data to your dataLayer before the tag manager code dataLayer[0] will contain your custom data, if you don't it will contain the gtm.load event and related data. So this is not reliable.
However it seems want you really want is to flatten the object, i.e. remove the nested structure with numerical keys and have a one-dimensional structure. Luckily somebody has written a function that does this:
var flattenObject = function(ob) {
var toReturn = {};
for (var i in ob) {
if (!ob.hasOwnProperty(i)) continue;
if ((typeof ob[i]) == 'object') {
var flatObject = flattenObject(ob[i]);
for (var x in flatObject) {
if (!flatObject.hasOwnProperty(x)) continue;
toReturn[i + '.' + x] = flatObject[x];
}
} else {
toReturn[i] = ob[i];
}
}
return toReturn;
};
This makes a "one-dimensional" object from a nested object. Usually this would mean that keys with the same name will be overwritten by the respective last element. I.e.
dataLayer = [
{'key':value1},
{'key':value2},
]
would result in a simple
{'key':value2}
since the second "key" overwrites the first. However the function above mitigates this by storing the index as part of the key name, so you would get
{'0.key':value1, '1.key':value2}
which somewhat unfortunately means you cannot use dot syntax and have to adress the elements with angled brackets:
yourvariablename['0.key']

Delete object properties similiar like deleting array elements with splice?

We have object type variable in Jquery:
var obj = *{"1234" : "xx", "4321" : "yy", "5555" : "hh", "2321" : "aa" };*
Lets say that I want to delete every property from property name "5555" to the end of the object(that means that I want to delete obj['5555'] and delete obj['2321'] ).
I am interested in smartest way, trough loop, to do that.
In array I would use splice(2, arr.length) but I am confused.
There's no guarantee as to the order of an object's properties. When pasting your example object in my console, Here's what I saw:
> obj = {"1234" : "xx", "4321" : "yy", "5555" : "hh", "2321" : "aa" }
Object {1234: "xx", 2321: "aa", 4321: "yy", 5555: "hh"}
As you can see, chrome ordered the properties in ascending order, like it would an array. Who knows, but maybe IE doesn't do this... Maybe some obscure browser would order the properties in descending order... There's no way of knowing what the actual object will look like, so perhaps have a rethink.
If all your properties are, essentially numeric, there's nothing wrong with using an array, in JS, the Array prototype is nothing but an augmented Object:
obj = [];
obj[1234] = 'xx';
obj[2321] = 'aa';
obj[5555] = 'hh';
The numeric indexes are coerced to strings internally anyway (because Array's are objects), so JS isn't going to create endless empty indexes for you, it resolves obj[200] just like it would resolve objectLiteral.undefinedProperty: scan instance, then prototypechain. If the requested property wasn't found, return undefined.
They're added as you go along, yet here are 2 ways:
//Assume simpel object (non-nested)
var newObj = JSON.parse(JSON.stringify(obj).replace(/\{|,\s*"5{4}"\s*:.+$/,'}'));
This, I think, is the easiest way, but not very reliable. The most "tried and tested" apprach is:
var unset = false;
for (var prop in obj)
{
if (obj.hasOwnProperty(prop))
{
unset = unset || !!(prop === '5555');
if (unset === true)
{
delete(obj[prop]);
}
}
}
The last approach creates an array, containing all keys, which you can iterate over, and delete the properties that way. It's here for completeness' sake only: I wouldn't use it, though, simply because it requires a browsers that supports the ES5 spec (not all browsers do, sadly), and there's no real advantage over the code above:
var keys = Object.keys(obj).sort(),//call sort to assure ascending order
toDelete = keys.splice(keys.indexOf('5555'), keys.length).sort();
for(var i=0;i<toDelete.length;i++)
{
delete obj[toDelete[i]];
}
Push the obj to be searched and the value to be found into a function that returns a new object with only those properties up to the value you specified.
function returnNewobj(obj, value) {
var newObj = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (prop === value) return newObj;
newObj[prop] = obj[prop];
}
}
return newObj;
}
Edit: probably not necessary, but I added the hasOwnProperty line to be on the safe side.
Edit2: It's worth pointing out that new properties are added to objects in alphanumerical order, not to the end of objects like elements are added to arrays. So don't get caught out by that.
I would recommend you to get the index of the element from which you want to start deleting elements and then looping throw the object deleting the elements with a higher index.
You might want to create a function to make it more similar to splice i you prefer.
Find the element you are looking for and set that particular element and any element after that to null.
Its very tricky to delete property name however property value can be made null or undefined but removing property is difficult but you can do one thing can copy the required properties in new object its a workaround though here is a sample fiddle i use this often in this kind of situation
objCopyTo[strToPropertyName] = objCopyFrom[strPropertyName];
here is the fiddle

Ordered Map Implementation in JavaScript

My Task
In my JavaScript code i'm often using objects to "map" keys to values so i can later access them directly through a certain value. For example:
var helloMap = {};
helloMap.de = "Hallo";
helloMap["en"] = "Hello";
helloMap.es = "Hola";
So i build up the map object step by step in my source code using the two available notations object style and array style.
Later i can then access the values i added through helloMap["de"] for example. So thats all fine if i don't have to care about the order in which the attributes has been set on the object.
If i want to iterate the objects properties now as far as i know there is no way to ensure that i'll iterate them in the order they have been added (insertion order).
Note: I can't use some wrapper object and simply hold a array in there and then use its methods to add the values so something like this:
var HelloMap = function(){
this.myMap = [];
this.addProperty = function(key, value){
this.myMap.push({key: key, value: value});
}
}
or something similar won't work for me. So the solution needs to be absolutely transparent to the programmer using the object.
That said the object i needed would be an empty object which maintains the order of the properties that were added to it. Something like this would do:
var helloMap = {};
helloMap = getOrderAwareObject(helloMap);
so that every further assignment of the form helloMap.xy = "foo" and helloMap["yz"] = "bar" would be tracked in the object "in order",
Possible Solutions
Since i did not find any solution in underscore or jQuery giving me such a special object i came across the possibility of defining getters and setters for properties in JavaScript objects with Object.defineProperty since i can rely on ECMAScript 5 standard i can use it.
The Problem with this one is, that you have to know all the possible properties that can be set on the object, before they are actually set. Since if you define it you got to name it.
What i am searching for is something like a Default Getter and Default Setter which applies on the object if no getter and setter has been defined for the property. So i could then hide the sorted map behind the object inteface.
Is there already a solution for this in any framework you know?
Is there a mechanism like "default getter/setter" ?
You'll need a wrapper of some kind using an array internally, I'm afraid. ECMAScript 5 (which is the standard on which current browser JavaScript implementations are based) simply doesn't allow for ordered object properties.
However, ECMAScript 6 will have a Map implementation that has ordered properties. See also http://www.nczonline.net/blog/2012/10/09/ecmascript-6-collections-part-2-maps/.
There may also be other options in ECMAScript 6. See the following question:
How can I define a default getter and setter using ECMAScript 5?
Adding a link to a custom javascript library which provides Sorted maps and other implementation, for future reference in this thread . Check out https://github.com/monmohan/dsjslib
-msingh
I don't know of a general solution but non-general solutions are very simple to construct.
Typically, you maintain an Array of objects, with several methods defined as properties of the Array. At least, that's my approach.
Here's an example, taken (in a modified form) from a larger application :
var srcs = [];
srcs.find = function(dist) {
var i;
for(i=0; i<this.length; i++) {
if(dist <= this[i].dist) { return this[i]; }
}
return null;
};
srcs.add = function(dist, src) {
this.push({ dist:dist, src:src });
}
srcs.remove = function(dist) {
var i;
for(i=0; i<this.length; i++) {
if(this[i].dist === dist) {
srcs.splice(i,1);
return true;
}
}
return false;
};
srcs.add(-1, 'item_0.gif' );
srcs.add(1.7, 'item_1.gif');
srcs.add(5, 'item_2.gif');
srcs.add(15, 'item_3.gif');
srcs.add(90, 'item_4.gif');
Unfortunately, you lose the simplicity of a plain js object lookup, but that's the price you pay for having an ordered entity.
If you absolutely must have order and dot.notation, then maintain a plain js Object for lookup and an Array for order. With care, the two can be maintained with total integrity.
See my answer to this question. I implemented an basic ordered hashtable (ES 5+ only, didn't bother to polyfill)
var put = function(k,v){
if(map[k]){
console.log("Key "+ k+" is already present");
}else
{
var newMap = {};
map[k] = v;
Object.keys(map).sort().forEach(function(key){
newMap[key] = map[key];
});
map = newMap;
//delete newMap; in case object memory need to release
return map;
}
}
Put method will always take a key-value pair, internally creates another map with sorted keys from the actual map, update the value and return the updated map with sorted keys.No external library need to includ.

How to merge these arrays/json objects?

I am a bit confused at this point on what is an object, what is an array, and what is a JSON. Can someone explain the differences in syntax between the two? and how to add items to each, how to merge each type, and such? I am trying to get this function to take the new information from a JSON object (I think) and merge it with some new information. This information will then be passed to a PHP script to be processed.
Here is the console output:
{"public":{"0":["el29t7","3bmGDy"]}}
{"public":"[object Object][object Object]"}
Here is the JS I am using:
/* Helper function to clean up any current data we have stored */
function insertSerializedData(ids, type) {
// Get anything in the current field
current_data = $('#changes').val();
if (!current_data) {
var data = {};
data[index++] = ids;
var final_data = {};
final_data[type] = data;
$('#changes').val(JSON.stringify(final_data));
} else {
current_data = JSON.parse(current_data);
var data = {};
data[index++] = ids;
// Does the index exist?
if (type in current_data) {
var temp_data = current_data[type];
current_data[type] = temp_data + data;
} else {
current_data[type] = data;
}
//var extra_data = {};
//extra_data[type] = data;
//$.merge(current_data, extra_data);
$('#changes').val(JSON.stringify(current_data));
}
console.log($('#changes').val());
}
The idea is if the key (public, or whatever other ones) doesn't exist yet, then to make it point to an array of arrays. If it does exist though, then that of array of arrays need to be merged with a new array. For instance:
If I have
{"public":{"0":["el29t7","3bmGDy"]}}
and I want to merge it with
["aj19vA", "jO71Ba"]
then final result would be:
{"public":{"0":["el29t7","3bmGDy"], "1":["aj19vA", "jO71Ba"]}}
How can i go about doing this? Thanks
Excellent two-part question. Overall, the second question is non-trivial because of the complexity of the first.
Question 1:
what is an object, what is an array, and what is a JSON. Can someone
explain the differences in syntax between the two?
Question 2:
and how to add items to each,
Question 3:
how to merge each type, and such?
Answer 1:
This is a common stumbling point because, JavaScript is more flexible than one might initially expect. Here is the curve.
In JavaScript everything is an object.
So here is the code for each:
//What is an object?
var obj = { };
var obj2 = { member:"value", myFunction:function(){} }
Above is an empty object. Then another object with a variable and a function.
They are called object-literals.
//What is an array
var array1 = [ ] ;
var array2 = [0,1,2,3,4];
Above is an empty array. Then another array with five Integers.
Here is the curve that causes confusion.
//Get elements from each of the prior examples.
var x = obj2["member"];
var y = array2[1];
What??? Both Object and Array are accessing values with a bracket?
This is because both are objects. This turns out to be a nice flexibility for writing advanced code. Arrays are objects.
//What is JSON?
JSON stands for JavaScript Object Notiation. As you might have guessed. Everything is an object... It is also an { }; But it is different because - it is used to transfer data to - and - from JavaScript, not actually used (commonly) in JavaScript. It is a file transfer format.
var JSONObject = {"member":"value"};
The only difference to the prior example is quotes. Essentially we are wrapping the object literal as a string so that it can be transferred to a server, or back, and it can be reinterpreted, very easily. Better than XML - because it does not have to be custom-parsed. Just call, stringify() or ParseJSON(). Google it. The point is... JSON can be converted into an object-literal JS object, and JS object-literals can be converted into JSON, for transfer to a server or a CouchDB database, for example.
Sorry for the tangent.
Answer 2:
How to add an item to each? Here is where the curve stops being a nuisance, and starts being awesome! Because everything is an object, it is all just about the same.
//Add to an object
var obj {member1:"stringvalue"}
obj.member2 = "addme"; //That is it!
//Add to an array
var array1 [1,2,3,4,5];
array1[0] = "addme";
array[6] = null;
//We shouldn't mix strings, integers, and nulls in arrays, but this isn't a best-practice tutorial.
Remember the JS object syntax and you may start to see a whole new flexible world of objects open up. But it may take a bit.
Answer 3: Ah, yeah... how to merge.
There are seriously (very many) ways to merge two arrays. It depends on exactly what you need. Sorted, Duplicated, Concatenated... there are a few.
Here is the answer!
UPDATE: How to make a beautiful multiple dimensional array.
//Multiple Dimension Array
var array1 = [1,2,3];
var array2 = [3,4];
var arraysinArray = [array1,array2]; //That is it!
Here is the curve again, this could be in an object:
var obj{
array1:[1,2,3],
array2:[3,4]
}
JavaScript is powerful stuff, stick with it; it gets good. : )
Hope that helps,
All the best!
Nash
In this case, think of a JavaScript's object literal {} as being like PHP's associative array.
Given that, an "array of arrays" actually looks like this (using your above desired output):
{public: [["el29t7","3bmGDy"], ["aj19vA", "jO71Ba"]]}
So here we have an object literal with a single property named "public" whose value is a 2-dimensional array.
If we assign the above to a variable we can then push another array onto "public" like this:
var current_data = {public: [["el29t7","3bmGDy"], ["aj19vA", "jO71Ba"]]};
// Using direct property access
current_data.public.push(["t9t9t9", "r4r4r4"]);
// Or using bracket notation
current_data["public"].push(["w2w2w2", "e0e0e0"]);
current_data's value is now:
{public: [
["el29t7","3bmGDy"],
["aj19vA", "jO71Ba"],
["t9t9t9", "r4r4r4"],
["w2w2w2", "e0e0e0"]
]}
So now "public" is an array whose length is 4.
current_data.public[0]; // ["el29t7","3bmGDy"]
current_data.public[1]; // ["aj19vA", "jO71Ba"]
current_data.public[2]; // ["t9t9t9", "r4r4r4"]
current_data.public[3]; // ["w2w2w2", "e0e0e0"]
MDN has very good documentation on Array for insight on other functions you might need.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array
First is an object, that contains array, second is an array.
DEMO showing display output http://jsfiddle.net/GjQCV/
var object={"public":{"0":["el29t7","3bmGDy"]}};
var arr=["aj19vA", "jO71Ba"] ;
/* use object notation to add new property and value which is the array*/
object.public[1]=arr;
It'd be much more natural if {"0": ...} were a true array rather than an object, but anyway:
function maxKey(b) {
var max;
for( var key in b )
var max = key;
return max;
}
function merge(a,b) {
for( var key in a ) {
b[key] = b[key] ? (b[key][maxKey(b)+1]=a[key], b[key]) : a[key];
}
return b;
}
Note that this assumes you would insert at the next integer index
Arrays are a particular kind of Javascript object
JSON is a way of representing Javascript objects (and as such can represent arrays and more)
Objects are much more general, and can be simple objects that can be represented as JSON, or can contain functions and prototypes.
So, this is not an array of arrays (you would access items using JSON notation like myobj["0"]):
{"0":["el29t7","3bmGDy"], "1":["aj19vA", "jO71Ba"]}
This is an array of arrays, which means you can use the push method to add an item, and access items using array notation like myobj[0]:
[ ["el29t7","3bmGDy"], ["aj19vA", "jO71Ba"] ]
It seems like the structure you want is something like this:
var myobj = { "public": [ ["key", "value"], ["key", "value"] ] }
Then if you want to add/merge new items, you'd write this:
if (myobj["public"] != null) {
myobj["public"].push(["newkey", "newval"]);
} else {
myobj["public"] = ["newkey", "newval"];
}

JavaScript for in loop, but in reverse?

Taking a JavaScript object with 4 properties:
function Object() {
this.prop1;
this.prop2;
this.prop3;
this.prop4;
}
var obj = new Object();
I use a for(in) loop to inspect each property since I don't know the number or name of the properties:
for(property in obj) {
var prop = obj[property];
}
However I would like to process the properties starting with the last (prop4 in this example). I suppose I would like a reverse-for-in-loop.
How can I do this?
Thanks,
Jack
Adding: The object I am referring to is the one returned from JSON.parse. The properties seem to be consistently ordered. There is no keys() method.
A for (x in y) does not process the properties in any specific order so you cannot count on any desired order.
If you need to process the properties in a specific order, you will need to get all the properties into an array, sort the array appropriately and then use those keys in the desired order.
Using ES5 (or an ES5 shim), you can get all properties into an array with:
var keys = Object.keys(obj);
You could then sort them either in standard lexical order or sort with your own custom function:
keys.sort(fn);
And, then you could access them in your desired order:
for (var i = 0; i < keys.length; i++) {
// process obj[keys[i]]
}
The ECMAScript standard does not define an order to iteration for for in loops. You will want an array, if your datatypes are to be sorted.
Arrays are ordered objects. Properties in objects are inherently unordered. However, if you have some specific reason that you want to work from back to front of whatever the for..in construct would have produced, you could do:
var arr = [];
for (prop in obj) {
arr.push(prop);
}
for (var n=arr.length; n--; ){
var prop = obj[arr[n]];
}

Categories