Navigation

Web Development

Javascript Object To String

Being able to visualize the exact structure and data of an object can be very useful during debugging or development. The following function is a general purpose "toString" function for objects. It will generate a string containing a properly indented snapshot of an object, including all its properties and methods. The function will also mark object members that are inherited from the object's prototype and will keep track of the child members it has already walked thus marking recursive nodes and mapping to their corresponding parent by id.

This function can also be used to visualize the data within multidimensional arrays.

Since I just yanked this function out of my Javascript library, it makes use of three other functions: strPad, isArray, isDomNode which are also listed on this page.

function objectToString (objRef, expandedFlag, parseLevel, recurChain)
{
	if (typeof objRef != 'object')
		return 'Not Object';
	
	parseLevel = parseLevel ? parseLevel : 0;
	var indent = parseLevel ? strPad ('', parseLevel, String.fromCharCode (9)) : '';
	var subIndent = indent + String.fromCharCode (9);
	
	var funcHeader = '';
	
	if (!recurChain) recurChain = [objRef];
	else
	{
		for (var i = 0; i < recurChain.length; i ++)
			if (objRef == recurChain [i])
				return '[recursion #' + i + ']\n';
		
		recurChain [recurChain.length] = objRef;
	}
	
	var outStr = '';
	if (isArray (objRef)) outStr += 'Array';
	else outStr += 'Object #' + (recurChain.length - 1);
	outStr += '\n' + indent + '{\n';
	
	for (var handle in objRef)
	{
		outStr += subIndent + handle + (objRef.hasOwnProperty (handle) ? '' : ' [inherited]') + ' : ';
		
		if (objRef [handle] == null) outStr += 'null\n';
		else if (typeof objRef [handle] == objRef) outStr += '[recursion #0]\n';
		else if (isDomNode (objRef [handle])) outStr += '[DOM Node: ' + objRef [handle].nodeName + ']\n';
		else if (typeof objRef [handle] == 'object' && typeof objRef [handle].constructor == 'function') outStr += objectToString (objRef [handle], expandedFlag, parseLevel + 1, recurChain);
		else if (typeof objRef [handle] == 'function')
		{
			if (expandedFlag) outStr += objRef [handle].toString ().replace (/\s+/g, ' ') + '\n';
			else if (funcHeader = objRef [handle].toString ().match (/^function\s\(.*\)/)) outStr += funcHeader + '\n';
			else outStr += '[function]\n';
		}
		else outStr += objRef [handle].toString ().replace (/\n+/g, '\\n') + '\n';
	}
	
	return outStr + indent + '}\n';
}

function strPad (inputStr, padLength, padStr, padType)
{
	if (!padStr) padStr = ' ';
	
	if (padType != 'left' && padType != 'both' && padType != 'right')
		padType = 'right';
	
	var padSize = padLength - inputStr.length;
	if (!(padSize > 0)) return inputStr;
	
	if (padType == 'both' && padSize == 1)
		padType == 'right';
	
	var ii = 0;
	var padBlock = '';
	for (var i = 0; i < (padType == 'both' ? Math.floor (padSize / 2) : padSize); i ++)
	{
		if (!padStr [ii]) ii = 0;
		padBlock += padStr [ii];
		ii ++;
	}
	
	var reminderBlock = '';
	if (padType == 'both' && padSize % 2)
		reminderBlock = padStr [ii] ? padStr [ii] : padStr [0];
	
	return ((padType == 'left' || padType == 'both') ? padBlock : '') + inputStr + ((padType == 'right' || padType == 'both') ? padBlock : '') + reminderBlock;
}

function isArray (objRef)
{
	if (objRef == null || typeof objRef != 'object')
		return false;
	
	return (objRef.constructor === Array) ? true : false;
}

function isDomNode (objRef)
{
	return (typeof Node == 'object' ? typeof objRef == 'object' && objRef instanceof Node : typeof objRef == 'object' && typeof objRef.nodeType == 'number' && typeof objRef.nodeName == 'string');
}
That's it, I hope you find this function useful and you enjoy using it as much as I enjoyed writing it.