Safe Stringify
This code follows links once and only once, so, there should be no circular references.
Note that large objects should NOT be output to the console, as this will be super slow.
Assign the safeStringify to a variable and save it to a file using console.save below.
See the sample usage at the end of this article.
var safeStringify = function(obj, replacer, indent) {
var printedObjects = [];
var printedObjectKeys = [];
function is_scalar(obj){return (/string|number|boolean/).test(typeof obj);}
function printOnceReplacer(key, value) {
if (value === null || value === undefined || is_scalar(value))
return value;
if (printedObjects.length > 10000) {
return 'object too long';
}
// try to find the current object in "printedObjects"
var printedObjIndex = false;
printedObjects.forEach(function(obj, index) {
if (obj === value) {
printedObjIndex = index;
}
});
// handle root case
if (key == '') {
//root element
printedObjects.push(obj);
printedObjectKeys.push("root");
return value;
}
// hadle case previously found reference case
else if (printedObjIndex + "" != "false" && typeof (value) == "object") {
if (printedObjectKeys[printedObjIndex] == "root") {
return "(pointer to root)";
} else {
return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase() : typeof (value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
}
}
// hanle newly found reference case, and calling the replacer
else {
var qualifiedKey = key || "(empty key)";
printedObjects.push(value);
printedObjectKeys.push(qualifiedKey);
if (replacer) {
return replacer(key, value);
} else {
return value;
}
}
}
return JSON.stringify(obj, printOnceReplacer, indent);
};
ref: modified from http://stackoverflow.com/a/17773553/279393console.save
(function(console){
console.save = function(data, filename){
if(!data) {
console.error('Console.save: No data')
return;
}
if(!filename) filename = 'console.json'
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
})(console)
ref: http://bgrins.github.io/devtools-snippets/#console-saveSimple Usage
var BNes = safeStringify(myVariableToStringify, undefined, 4); console.save(BNes);
More Complex Usage
var BNes = safeStringify(myVariableToStringify, (k, v) => {
let replacements = {"_parent": "[CIRCULAR]", "domElem": "[DOM ELEMENT]"};
// Replace references to HTML elements with a string
if (v && v.constructor) {
let cn = v.constructor.name.toLowerCase();
if (cn.indexOf("element") === cn.length - 7 && cn.indexOf("html") !== -1)
return "HTML ELEMENT";
}
if (replacements[k] !== undefined)
return replacements[k];
else
return v;
}, 4);
console.save(BNes);