How can I inspect an Object in an alert box? Normally alerting an Object just throws the nodename:
alert(document);
But I want to get the properties and methods of the object in the alert box. How can I achieve this functionality, if possible? Or are there any other suggestions?
Particularly, I am seeking a solution for a production environment where console.log and Firebug are not available.
How about alert(JSON.stringify(object)) with a modern browser?
In case of TypeError: Converting circular structure to JSON, here are more options: How to serialize DOM node to JSON even if there are circular references?
The documentation: JSON.stringify() provides info on formatting or prettifying the output.
The for-in loops for each property in an object or array. You can use this property to get to the value as well as change it.
Note: Private properties are not available for inspection, unless you use a "spy"; basically, you override the object and write some code which does a for-in loop inside the object's context.
For in looks like:
for (var property in object) loop();
Some sample code:
function xinspect(o,i){
if(typeof i=='undefined')i='';
if(i.length>50)return '[MAX ITERATIONS]';
var r=[];
for(var p in o){
var t=typeof o[p];
r.push(i+'"'+p+'" ('+t+') => '+(t=='object' ? 'object:'+xinspect(o[p],i+' ') : o[p]+''));
}
return r.join(i+'\n');
}
// example of use:
alert(xinspect(document));
Edit: Some time ago, I wrote my own inspector, if you're interested, I'm happy to share.
Edit 2: Well, I wrote one up anyway.
Use console.dir(object) and the Firebug plugin
There are few methods :
1. typeof tells you which one of the 6 javascript types is the object.
2. instanceof tells you if the object is an instance of another object.
3. List properties with for(var k in obj)
4. Object.getOwnPropertyNames( anObjectToInspect )
5. Object.getPrototypeOf( anObject )
6. anObject.hasOwnProperty(aProperty)
In a console context, sometimes the .constructor or .prototype maybe useful:
console.log(anObject.constructor );
console.log(anObject.prototype ) ;
Use your console:
console.log(object);
Or if you are inspecting html dom elements use console.dir(object). Example:
let element = document.getElementById('alertBoxContainer');
console.dir(element);
Or if you have an array of js objects you could use:
console.table(objectArr);
If you are outputting a lot of console.log(objects) you can also write
console.log({ objectName1 });
console.log({ objectName2 });
This will help you label the objects written to console.
var str = "";
for(var k in obj)
if (obj.hasOwnProperty(k)) //omit this test if you want to see built-in properties
str += k + " = " + obj[k] + "\n";
alert(str);
This is blatant rip-off of Christian's excellent answer. I've just made it a bit more readable:
/**
* objectInspector digs through a Javascript object
* to display all its properties
*
* #param object - a Javascript object to inspect
* #param result - a string of properties with datatypes
*
* #return result - the concatenated description of all object properties
*/
function objectInspector(object, result) {
if (typeof object != "object")
return "Invalid object";
if (typeof result == "undefined")
result = '';
if (result.length > 50)
return "[RECURSION TOO DEEP. ABORTING.]";
var rows = [];
for (var property in object) {
var datatype = typeof object[property];
var tempDescription = result+'"'+property+'"';
tempDescription += ' ('+datatype+') => ';
if (datatype == "object")
tempDescription += 'object: '+objectInspector(object[property],result+' ');
else
tempDescription += object[property];
rows.push(tempDescription);
}//Close for
return rows.join(result+"\n");
}//End objectInspector
Here is my object inspector that is more readable. Because the code takes to long to write down here you can download it at http://etto-aa-js.googlecode.com/svn/trunk/inspector.js
Use like this :
document.write(inspect(object));
Related
HTML:
<img src="person.png" id="person"/>
JavaScript:
var object0 = document.getElementById("person");
var i = 0;
context.drawImage(object0, object0X, object0Y);// this works
context.drawImage("object" + i, object0X, object0Y);// this doesn't
Error message:
Could not convert JavaScript argument arg 0 [nsIDOMCanvasRenderingContext2D.drawImage]
I read somewhere that the reason I get the error is that it has to be a DOM element, not a string. Well, I need to run a for loop so I can affect several objects on screen and therefore need to do some concatenation. Is there something similar to parseInt() I could use?
Referencing a variable using a string literal will result in an error because it will evaluate to a string literal.
var Object0 = document.getElementById('person'); // typeof 'object'
console.log(typeof ('Object' + i)); // This will output 'string' to the console
You could instead create an object whose properties hold references to DOM elements.
var images = {
Object0: document.getElementById('person')
// and so forth...
};
This is extremely useful because you can reference each property using bracket notation. Now, you can loop through the properties with a for loop and access the values; like so:
for (var i = 0; i < images.length; i++) {
context.drawImage(images['Object' + i], Object0X, Object0Y); // This works
console.log(typeof images['Object' + i]); // This will output 'object' to the console
}
I think you want to do:
context.drawImage(document.getElementById("object" + i), object0X, object0Y);
Which would require that you have image elements with the ids object0, object1, object2...
You can't reference JS variables via strings. The error originates from passing a string to the drawImage function, not a reference to the image. Just pass the variable to the function, and it works.
If I want to enumerate the properties of an object and want to ignore prototypes, I would use:
var instance = { ... };
for (var prop in instance) {
if (instance.hasOwnProperty(prop)) {
...
}
}
What if instance only has one property, and I want to get that property name? Is there an easier way than doing this:
var instance = { id: "foobar" };
var singleMember = (function() {
for (var prop in instance) {
if (instance.hasOwnProperty(prop)) {
return prop;
}
}
})();
Maybe Object.keys can work for you. If its length returns 1, you can use yourObject[Object.keys[0]] to get the only property of the object. The MDN-link also shows a custom function for use in environments without the keys method1. Code like this:
var obj = {foo:'bar'},
kyz = Object.keys(obj);
if (kyz.length === 1){
alert(obj[kyz[0]]); //=> 'bar'
} else {
/* loop through obj */
}
1 Some older browsers don't support Object.keys. The MDN link supplies code to to make it work in these browsers too. See header Compatibility in the aforementioned MDN page
Shortest form:
instance[Object.keys(instance)[0]];
ES6+ function:
let first = v => v[Object.keys(v)[0]];
Use the function:
first({a:'first', b:'second'}) // return 'first'
var foo = {bar: 1};
console.log(Object.keys(foo).toString());
which will print the string
"bar"
Though my answer is downvoted, it's still worth to know that there is no such thing as order of keys in javascript object. Therefore, in theory, any code build on iterating values can be inconsistent. One approach could be creating an object and to define setter which actually provides counting, ordering and so on, and provide some methods to access this fields. This could be done in modern browsers.
So, to answer you question, in general you approach is still most closs-browser. You can iterate using lodash or any other modern framework wich will hide "hasOwnProperty" complexity from you. As of August'15 Object.keys can be accepted as cross-browser and universal. After all IE8 happened years ago. Still there are some cases when you just don't wont store all set of keys in array. But I'd go with Object.keys - it's more flexible compared to iteration.
Unfortunately, there is no, "list properties" function built in, and there certainly isn't a "getFirstProperty" (especially since there is no guarantee that any property will consistently be "first").
I think you're better off writing a function like this one:
/**
* A means to get all of the keys of a JSON-style object.
* #param obj The object to iterate
* #param count maximum length of returned list (defaults to Infinity).
*/
function getProperties( obj, count )
{
if( isNaN( count ) ) count = Infinity
var keys = []
for( var it in obj )
{
if( keys.length > count ) break;
keys.push( it );
}
return keys;
}
Then, you could access the name though:
instance = {"foo":"bar"}
// String() on an array of < 2 length returns the first value as a string
// or "" if there are no values.
var prop = String(getProperties(instance, 1));
This is an old post, but I ended up writing the following helper function based on Object.keys().
It returns the key and value of the first property.
getFirstPropertyKeyAndValue(sourceObject) {
var result = null;
var ownProperties = Object.keys(sourceObject);
if (ownProperties.length > 0) {
if (ownProperties.length > 1) {
console.warn('Getting first property of an object containing more than 1 own property may result in unexpected results. Ordering is not ensured.', sourceObject);
}
var firstPropertyName = ownProperties[0];
result = {key: firstPropertyName, value: sourceObject[firstPropertyName]};
}
return result;
}
Answers in here all good, and with the caveat that the order may be unreliable (although in practice it seems the order the properties are set tends to stay that way), this quick and dirty method also works:
var obj = {foo: 1, bar: 2};
for(var key in obj) {
//you could use key here if you like
break;
}
//key now contains your first key
or a shorter version should also do it:
for(var key in obj) break;
//key now contains your first key
I'm using a JS array to Map IDs to actual elements, i.e. a key-value store. I would like to iterate over all elements. I tried several methods, but all have its caveats:
for (var item in map) {...}
Does iterates over all properties of the array, therefore it will include also functions and extensions to Array.prototype. For example someone dropping in the Prototype library in the future will brake existing code.
var length = map.lenth;
for (var i = 0; i < length; i++) {
var item = map[i];
...
}
does work but just like
$.each(map, function(index, item) {...});
They iterate over the whole range of indexes 0..max(id) which has horrible drawbacks:
var x = [];
x[1]=1;
x[10]=10;
$.each(x, function(i,v) {console.log(i+": "+v);});
0: undefined
1: 1
2: undefined
3: undefined
4: undefined
5: undefined
6: undefined
7: undefined
8: undefined
9: undefined
10: 10
Of course my IDs wont resemble a continuous sequence either. Moreover there can be huge gaps between them so skipping undefined in the latter case is unacceptable for performance reasons. How is it possible to safely iterate over only the defined elements of an array (in a way that works in all browsers and IE)?
Use hasOwnProperty within for ... in to make sure that prototype additions aren't included:
for (var item in map)
if (map.hasOwnProperty(item)) {
// do something
}
There are three issues:
You should not use for...in to iterate arrays.
You are using the wrong data type for your requirements.
You are not using for...in correctly.
If you want to have something like a hash table then use a plain object:
var map = {};
map[123] = 'something';
map.foo = 'bar';
// same as map['foo'] = 'bar';
//...
It looks like an array, but it is not. It is an object with property 123. You can use either dot notation obj.key (only if the key is a valid identifier - 123 would not be valid so you have to use the following notation) or array notation obj['key'] to access object properties.
It seems that an object would be a more appropriate data structure.
But even then you should make a call to hasOwnProperty (every time you use for...in):
for(var key in obj) {
if(obj.hasOwnProperty(key)) {
//do something
}
}
This checks whether a property is inherited from the prototype (it will return false then) or is truly an own property.
Use the EcmaScript 5 builtin Object.keys, and on non ES5 browsers, define it thus:
Object.keys = function (o) {
var keys = [];
var hasOwnProp = Object.prototype.hasOwnProperty;
if (Object.prototype.toString.call(o) === '[object Array]') {
for (var k in o) {
if (+k === (k & 0x7fffffff) && hasOwnProp.call(o, k)) {
keys[keys.length] = k;
}
}
keys.sort(keys, function (a, b) { return a - b; });
} else {
for (var k in o) {
if (hasOwnProp.call(o, k)) {
keys[keys.length] = k;
}
}
}
return keys;
};
1) use an object like already suggested, it is by far the best solution.
2) if you for some reason need to use an array - don't be scared looping over it with
for(var i, len = arr.length;len < i;i++)
it's very very fast.
3) don't use $.each or similar methods if you want performance - they create a new callstack for every iteration, which is a huge overhead.
Don't use an array. Use an object hash instead
var map = {};
map[key] = value;
...
for (var key in map) {
do something to map[key]
}
You can't do a lot without actually doing a check to see if the value is undefined and then doing operation a or operation b. It would be better to use a predicate to determine if the value is undefined:
x = $.grep(x, function(v, i) { return (typeof(v) != "undefined"); });
There isn't. The only way would be to omit the items from the collection completely, any solution you come up with would still have to do a test on each element for the value.
You could come up with different methods of adding the items key/value to object literals or what have you, but you would still need to omit undefined entries if you do not wish to enumerate over them.
In JavaScript / jQuery, if I alert some object, I get either [object] or [object Object]
Is there any way to know:
what is the difference between these two objects
what type of Object is this
what all properties does this object contains and values of each property
?
You can look up an object's keys and values by either invoking JavaScript's native for in loop:
var obj = {
foo: 'bar',
base: 'ball'
};
for(var key in obj) {
alert('key: ' + key + '\n' + 'value: ' + obj[key]);
}
or using jQuery's .each() method:
$.each(obj, function(key, element) {
alert('key: ' + key + '\n' + 'value: ' + element);
});
With the exception of six primitive types, everything in ECMA-/JavaScript is an object. Arrays; functions; everything is an object. Even most of those primitives are actually also objects with a limited selection of methods. They are cast into objects under the hood, when required. To know the base class name, you may invoke the Object.prototype.toString method on an object, like this:
alert(Object.prototype.toString.call([]));
The above will output [object Array].
There are several other class names, like [object Object], [object Function], [object Date], [object String], [object Number], [object Array], and [object Regex].
To get listing of object properties/values:
In Firefox - Firebug:
console.dir(<object>);
Standard JS to get object keys borrowed from Slashnick:
var fGetKeys = function(obj){
var keys = [];
for(var key in obj){
keys.push(key);
}
return keys;
}
// Example to call it:
var arrKeys = fGetKeys(document);
for (var i=0, n=arrKeys.length; i<n; i++){
console.log(i+1 + " - " + arrKeys[i] + document[arrKeys[i]] + "\n");
}
Edits:
<object> in the above is to be replaced with the variable reference to the object.
console.log() is to be used in the console, if you're unsure what that is, you can replace it with an alert()
i) what is the difference between these two objects
The simple answer is that [object] indicates a host object that has no internal class. A host object is an object that is not part of the ECMAScript implementation you're working with, but is provided by the host as an extension. The DOM is a common example of host objects, although in most newer implementations DOM objects inherit from the native Object and have internal class names (such as HTMLElement, Window, etc). IE's proprietary ActiveXObject is another example of a host object.
[object] is most commonly seen when alerting DOM objects in Internet Explorer 7 and lower, since they are host objects that have no internal class name.
ii) what type of Object is this
You can get the "type" (internal class) of object using Object.prototype.toString. The specification requires that it always returns a string in the format [object [[Class]]], where [[Class]] is the internal class name such as Object, Array, Date, RegExp, etc. You can apply this method to any object (including host objects), using
Object.prototype.toString.apply(obj);
Many isArray implementations use this technique to discover whether an object is actually an array (although it's not as robust in IE as it is in other browsers).
iii) what all properties does this object contains and values of each property
In ECMAScript 3, you can iterate over enumerable properties using a for...in loop. Note that most built-in properties are non-enumerable. The same is true of some host objects. In ECMAScript 5, you can get an array containing the names of all non-inherited properties using Object.getOwnPropertyNames(obj). This array will contain non-enumerable and enumerable property names.
I hope this doesn't count as spam. I humbly ended up writing a function after endless debug sessions: http://github.com/halilim/Javascript-Simple-Object-Inspect
function simpleObjInspect(oObj, key, tabLvl)
{
key = key || "";
tabLvl = tabLvl || 1;
var tabs = "";
for(var i = 1; i < tabLvl; i++){
tabs += "\t";
}
var keyTypeStr = " (" + typeof key + ")";
if (tabLvl == 1) {
keyTypeStr = "(self)";
}
var s = tabs + key + keyTypeStr + " : ";
if (typeof oObj == "object" && oObj !== null) {
s += typeof oObj + "\n";
for (var k in oObj) {
if (oObj.hasOwnProperty(k)) {
s += simpleObjInspect(oObj[k], k, tabLvl + 1);
}
}
} else {
s += "" + oObj + " (" + typeof oObj + ") \n";
}
return s;
}
Usage
alert(simpleObjInspect(anyObject));
or
console.log(simpleObjInspect(anyObject));
Get FireBug for Mozilla Firefox.
use console.log(obj);
Spotlight.js is a great library for iterating over the window object and other host objects looking for certain things.
// find all "length" properties
spotlight.byName('length');
// or find all "map" properties on jQuery
spotlight.byName('map', { 'object': jQuery, 'path': '$' });
// or all properties with `RegExp` values
spotlight.byKind('RegExp');
// or all properties containing "oo" in their name
spotlight.custom(function(value, key) { return key.indexOf('oo') > -1; });
You'll like it for this.
Scanning object for first intance of a determinated prop:
var obj = {a:'Saludos',
b:{b_1:{b_1_1:'Como estas?',b_1_2:'Un gusto conocerte'}},
d:'Hasta luego'
}
function scan (element,list){
var res;
if (typeof(list) != 'undefined'){
if (typeof(list) == 'object'){
for(key in list){
if (typeof(res) == 'undefined'){
res = (key == element)?list[key]:scan(element,list[key]);
}
});
}
}
return res;
}
console.log(scan('a',obj));
I've got an array
var assoc_pagine = new Array();
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
I tried
if (assoc_pagine[var] != "undefined") {
but it doesn't seem to work
I'm using jquery, I don't know if it can help
Thanks
Use the in keyword to test if a attribute is defined in a object
if (assoc_var in assoc_pagine)
OR
if ("home" in assoc_pagine)
There are quite a few issues here.
Firstly, is var supposed to a variable has the value "home", "work" or "about"? Or did you mean to inspect actual property called "var"?
If var is supposed to be a variable that has a string value, please note that var is a reserved word in JavaScript and you will need to use another name, such as assoc_var.
var assoc_var = "home";
assoc_pagine[assoc_var] // equals 0 in your example
If you meant to inspect the property called "var", then you simple need to put it inside of quotes.
assoc_pagine["var"]
Then, undefined is not the same as "undefined". You will need typeof to get the string representation of the objects type.
This is a breakdown of all the steps.
var assoc_var = "home";
var value = assoc_pagine[assoc_var]; // 0
var typeofValue = typeof value; // "number"
So to fix your problem
if (typeof assoc_pagine[assoc_var] != "undefined")
update: As other answers have indicated, using a array is not the best sollution for this problem. Consider using a Object instead.
var assoc_pagine = new Object();
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
var assoc_pagine = new Array();
assoc_pagine["home"]=0;
Don't use an Array for this. Arrays are for numerically-indexed lists. Just use a plain Object ({}).
What you are thinking of with the 'undefined' string is probably this:
if (typeof assoc_pagine[key]!=='undefined')
This is (more or less) the same as saying
if (assoc_pagine[key]!==undefined)
However, either way this is a bit ugly. You're dereferencing a key that may not exist (which would be an error in any more sensible language), and relying on JavaScript's weird hack of giving you the special undefined value for non-existent properties.
This also doesn't quite tell you if the property really wasn't there, or if it was there but explicitly set to the undefined value.
This is a more explicit, readable and IMO all-round better approach:
if (key in assoc_pagine)
var is a statement... so it's a reserved word... So just call it another way.
And that's a better way of doing it (=== is better than ==)
if(typeof array[name] !== 'undefined') {
alert("Has var");
} else {
alert("Doesn't have var");
}
This is not an Array.
Better declare it like this:
var assoc_pagine = {};
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
or
var assoc_pagine = {
home:0,
about:1,
work:2
};
To check if an object contains some label you simply do something like this:
if('work' in assoc_pagine){
// do your thing
};
This worked for me
if (assoc_pagine[var] != undefined) {
instead this
if (assoc_pagine[var] != "undefined") {
TLDR; The best I can come up with is this: (Depending on your use case, there are a number of ways to optimize this function.)
function arrayIndexExists(array, index){
if ( typeof index !== 'number' && index === parseInt(index).toString()) {
index = parseInt(index);
} else {
return false;//to avoid checking typeof again
}
return typeof index === 'number' && index % 1===0 && index >= 0 && array.hasOwnKey(index);
}
The other answer's examples get close and will work for some (probably most) purposes, but are technically quite incorrect for reasons I explain below.
Javascript arrays only use 'numerical' keys. When you set an "associative key" on an array, you are actually setting a property on that array object, not an element of that array. For example, this means that the "associative key" will not be iterated over when using Array.forEach() and will not be included when calculating Array.length. (The exception for this is strings like '0' will resolve to an element of the array, but strings like ' 0' won't.)
Additionally, checking array element or object property that doesn't exist does evaluate as undefined, but that doesn't actually tell you that the array element or object property hasn't been set yet. For example, undefined is also the result you get by calling a function that doesn't terminate with a return statement. This could lead to some strange errors and difficulty debugging code.
This can be confusing, but can be explored very easily using your browser's javascript console. (I used chrome, each comment indicates the evaluated value of the line before it.);
var foo = new Array();
foo;
//[]
foo.length;
//0
foo['bar'] = 'bar';
//"bar"
foo;
//[]
foo.length;
//0
foo.bar;
//"bar"
This shows that associative keys are not used to access elements in the array, but for properties of the object.
foo[0] = 0;
//0
foo;
//[0]
foo.length;
//1
foo[2] = undefined
//undefined
typeof foo[2]
//"undefined"
foo.length
//3
This shows that checking typeof doesn't allow you to see if an element has been set.
var foo = new Array();
//undefined
foo;
//[]
foo[0] = 0;
//0
foo['0']
//0
foo[' 0']
//undefined
This shows the exception I mentioned above and why you can't just use parseInt();
If you want to use associative arrays, you are better off using simple objects as other answers have recommended.
if (assoc_pagine.indexOf('home') > -1) {
// we have home element in the assoc_pagine array
}
Mozilla indexOf
function isset(key){
ret = false;
array_example.forEach(function(entry) {
if( entry == key ){
ret = true;
}
});
return ret;
}
alert( isset("key_search") );
The most effective way:
if (array.indexOf(element) > -1) {
alert('Bingooo')
}
W3Schools