Create Object in Object - javascript

I'm confuse the way how Google Chrome developer tool console is displaying if the (A) is the actual object created in the loop, why are the (B) contains 3 objects?
Does it means (A) will contain 3 objects?
Demo: https://jsfiddle.net/LygmkgLm/
var test={}
for(var i=0;i<3;i++){
test[i]={}
test[i].y="111"
console.log("test",test)
}

You're misinterpreting the console output. It correctly and and as expected shows the increasing contents of the object within the loop, hence the 1, 2 and 3 members in the output. At the end however the variable 'test' is the fully filled object, and when you expand the first line it shows the contents at the time of expansion. Being the fully filled object with 3 children.
Your confusion arises from the fact that the logging does not store the state of the object at logging time.

Chrome console shows the final object in console. It shows whatever the values have gone through the object. So in console first it will show you
test Object {0: Object}
But when you extend, it will have three object which has passed through it.
test Object {0: Object}0: Object1: Object2: Object__proto__: Object
One thing to note that, at first iteration of the loop, you may see three object in console but only one object i.e.
test Object {0: Object}
is actually accessible. If you want to check actual state of object in each iteration, you have to clone it like below
var newObject = jQuery.extend(true, {}, test);
Here is the fiddle which will give you an idea of my points https://jsfiddle.net/qtdurtzc/

Related

JavaScript prototype chain probable infinite cycle lookup

I have a query regarding JavaScript object prototype chains. Suppose I create an Object
var first = { a: 1};var second = Object.create(first);
Now I know that if I look up for the attribute a on the second object, due to the prototypal inheritance I would get the value 1. But if suppose I assign second to the hidden __ proto__ attribute of the first object, shouldn't the lookup get stuck in a look up cycle?
Here is what I mean:
first.__proto__ = second;cosole.log(second.z); //Would it keep looking for both objects in a cycle?
It does not enter into an infinite loop because it doesn't HAVE to look into what the second object has in it. Instead it shows that there IS a second object and then if you want to look further into it you can do so in separate steps.
Here is a quick example of what I mean in a pseudo code in order to make it more understandable:
OBJ 1 = {a:1}
OBJ 2 = Prototype of OBJ 1
Prototype of OBJ 1 = OBJ 2
print OBJ 2
Shows:
// Once again for clarity:
// The reason it is not entering into an infinite loop is because
// it doesn't iterate through the prototype object and instead it SHOWS the prototype.
// If you later want to see what's inside of it you can do so with an extra step.
// But it gives you minimal available information and so you see this:
a: 1
proto: OBJ 1

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);

nodejs `arguments` is object but in the browser, it is an `array`

When I access arguments from inside called function in nodejs...
echo '!function(){ console.log(arguments) }(1,2,3)' | node
... it outputs an object ...
{ '0': 1, '1': 2, '2': 3 }
... but in google chrome ...
!function(){ console.log(arguments) }(1,2,3)
... outputs ...
[1, 2, 3]
Why is it not consistent? What other js environments have this different behaviour? Is it ok for me to use arguments? How can I ensure it is always an array before I use it?
There are no rules for console output. The output doesn't represent anything that has to do with the language standard.
If you create a program that logs values from within a JS program, you're free to display those values however you want.
The arguments object is the same in both places. Only how it's being displayed is different.
How can I ensure it is always an array before I use it?
It's never an array. It's always an array-like object. In both cases its showing a value at object members 0, 1 and 2. Just uses different display syntax to do it.
In Chrome, try creating an object like this:
var my_obj = {
"0": 1,
"2": 3,
"1": 2,
length: 3,
splice: function(){},
};
And the log it in the console. It'll probably look like an Array literal, though it's obviously not.
It's not an Array in the browser, either. The arguments object has actually been in JavaScript longer than Arrays have, and when Arrays were first added to JavaScript (back in its 1.1 days), they didn't update arguments to be an Array. They haven't done it since then either, because of worries about backward-compatibility. It shows up in some browser consoles as though it were an Array because the debug console knows that most people plan to treat it as one anyway.
But the arguments object is close enough to an Array that it's easy to convert. One way to do it is like this:
var args = Array.prototype.slice.call(arguments, 0);
Array.prototype.slice, like most of Array.prototype's methods, is written to be generic: you can call it on Objects that aren't Arrays, and as long as they have properties with numeric names and a length property that's a Number, it'll work. The arguments object has both of these things, so these functions will work on it.
The slice function returns an Array which is a shallow copy of whatever object was passed into it, starting and ending at whatever numbers you specify. We tell it to start at zero, and because we didn't say where to stop, it assumes we want it to stop at the end, wherever that might be. This way, we copy all of the elements of arguments into a new Array, and now you can do whatever other Array things you want with it.

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.

What's the difference between console.dir and console.log?

In Chrome the console object defines two methods that seem to do the same thing:
console.log(...)
console.dir(...)
I read somewhere online that dir takes a copy of the object before logging it, whereas log just passes the reference to the console, meaning that by the time you go to inspect the object you logged, it may have changed. However some preliminary testing suggests that there's no difference and that they both suffer from potentially showing objects in different states than when they were logged.
Try this in the Chrome console (Ctrl+Shift+J) to see what I mean:
> o = { foo: 1 }
> console.log(o)
> o.foo = 2
Now, expand the [Object] beneath the log statement and notice that it shows foo with a value of 2. The same is true if you repeat the experiment using dir instead of log.
My question is, why do these two seemingly identical functions exist on console?
In Firefox, these function behave quite differently: log only prints out a toString representation, whereas dir prints out a navigable tree.
In Chrome, log already prints out a tree -- most of the time. However, Chrome's log still stringifies certain classes of objects, even if they have properties. Perhaps the clearest example of a difference is a regular expression:
> console.log(/foo/);
/foo/
> console.dir(/foo/);
* /foo/
global: false
ignoreCase: false
lastIndex: 0
...
You can also see a clear difference with arrays (e.g., console.dir([1,2,3])) which are logged differently from normal objects:
> console.log([1,2,3])
[1, 2, 3]
> console.dir([1,2,3])
* Array[3]
0: 1
1: 2
2: 3
length: 3
* __proto__: Array[0]
concat: function concat() { [native code] }
constructor: function Array() { [native code] }
entries: function entries() { [native code] }
...
DOM objects also exhibit differing behavior, as noted on another answer.
Another useful difference in Chrome exists when sending DOM elements to the console.
Notice:
console.log prints the element in an HTML-like tree
console.dir prints the element in a JSON-like tree
Specifically, console.log gives special treatment to DOM elements, whereas console.dir does not. This is often useful when trying to see the full representation of the DOM JS object.
There's more information in the Chrome Console API reference about this and other functions.
None of the 7 prior answers mentioned that console.dir supports extra arguments: depth, showHidden, and whether to use colors.
Of particular interest is depth, which (in theory) allows travering objects into more than the default 2 levels that console.log supports.
I wrote "in theory" because in practice when I had a Mongoose object and ran console.log(mongoose) and console.dir(mongoose, { depth: null }), the output was the same. What actually recursed deeply into the mongoose object was using util.inspect:
import * as util from 'util';
console.log(util.inspect(myObject, {showHidden: false, depth: null}));
I think Firebug does it differently than Chrome's dev tools. It looks like Firebug gives you a stringified version of the object while console.dir gives you an expandable object. Both give you the expandable object in Chrome, and I think that's where the confusion might come from. Or it's just a bug in Chrome.
In Chrome, both do the same thing. Expanding on your test, I have noticed that Chrome gets the current value of the object when you expand it.
> o = { foo: 1 }
> console.log(o)
Expand now, o.foo = 1
> o.foo = 2
o.foo is still displayed as 1 from previous lines
> o = { foo: 1 }
> console.log(o)
> o.foo = 2
Expand now, o.foo = 2
You can use the following to get a stringified version of an object if that's what you want to see. This will show you what the object is at the time this line is called, not when you expand it.
console.log(JSON.stringify(o));
Use console.dir() to output a browse-able object you can click through instead of the .toString() version, like this:
console.dir(obj/this/anything)
How to show full object in Chrome console?
From the firebug site
http://getfirebug.com/logging/
Calling console.dir(object) will log an interactive listing of an object's properties, like > a miniature version of the DOM tab.
Following Felix Klings advice I tried it out in my chrome browser.
console.dir([1,2]) gives the following output:
Array[2]
0: 1
1: 2
length: 2
__proto__: Array[0]
While console.log([1,2]) gives the following output:
[1, 2]
So I believe console.dir() should be used to get more information like prototype etc in arrays and objects.
Difference between console.log() and console.dir():
Here is the difference in a nutshell:
console.log(input): The browser logs in a nicely formatted manner
console.dir(input): The browser logs just the object with all its properties
Example:
The following code:
let obj = {a: 1, b: 2};
let DOMel = document.getElementById('foo');
let arr = [1,2,3];
console.log(DOMel);
console.dir(DOMel);
console.log(obj);
console.dir(obj);
console.log(arr);
console.dir(arr);
Logs the following in google dev tools:
Well, the Console Standard (as of commit ef88ec7a39fdfe79481d7d8f2159e4a323e89648) currently calls for console.dir to apply generic JavaScript object formatting before passing it to Printer (a spec-level operation), but for a single-argument console.log call, the spec ends up passing the JavaScript object directly to Printer.
Since the spec actually leaves almost everything about the Printer operation to the implementation, it's left to their discretion what type of formatting to use for console.log().

Categories