出于某种原因,我似乎无法在DOMWindow对象上使用JSON.stringify。例如:
console.log(window.self); // Outputs a hierarchical DOMWindow object
console.log(JSON.stringify(window.self)); // Outputs nothing - not even an error
alert(window.self); // Alerts "[object DOMWindow]"
alert(JSON.stringify(window.self)); // Again nothing - not even an error
在Safari和Chrome上测试过。有没有人有任何想法我怎么能做到这一点?
修改:
将编辑移至新问题,因为它并不特定于此。
答案 0 :(得分:5)
为什么要对DOM进行序列化?如果必须,Crescent的链接是您需要查看的地方。您无法序列化(stringify)窗口对象的原因是因为它包含循环引用,并且JSON.stringify
默认情况下不支持它们。
答案 1 :(得分:3)
正如其他人所说,stringify不支持DOMWindow
包含的循环引用。通常,循环引用可以使用Douglas Cockford的JSON cycle.js转换为JSON。
但是,我只是在window
上尝试过此操作,无论如何都会导致堆栈溢出。虽然这可能是cycle.js代码中的一个错误,但似乎window
更可能是一个对象太大了。
答案 2 :(得分:2)
你没有收到错误?我得到TypeError: Converting circular structure to JSON
。我会说,它无法完成。
此外,window
和window.self
指向同一个对象(Global对象),因此您不需要使用该属性...
答案 3 :(得分:2)
在Chrome 8开发中,我得到TypeError: Converting circular structure to JSON
(窗口通常包含自引用self
,window
和top
引用,如果您不在框架),因此直接使用JSON.stringify
将无效。
听起来你正在使用它来进行调试输出。如果您只关心某些信息,可以将该信息复制到对象,然后对其进行字符串化。然后将其封装在一个函数中,以便从window
中获取您认为您将关注的所有信息。
var data = JSON.stringify({
'location': window.location
// etc
});
答案 4 :(得分:2)
这个答案不是我的,但我在这里是为了同样的事情,并在其他地方找到了答案。 我不再打开该页面 - 我确实打开了github页面...
JSON.stringify deep objects - 谢谢,@ Bergi。 https://github.com/Canop/JSON.prune
// JSON.prune : a function to stringify any object without overflow
// two additional optional parameters :
// - the maximal depth (default : 6)
// - the maximal length of arrays (default : 50)
// You can also pass an "options" object.
// examples :
// var json = JSON.prune(window)
// var arr = Array.apply(0,Array(1000)); var json = JSON.prune(arr, 4, 20)
// var json = JSON.prune(window.location, {inheritedProperties:true})
// Web site : http://dystroy.org/JSON.prune/
// JSON.prune on github : https://github.com/Canop/JSON.prune
// This was discussed here : https://stackoverflow.com/q/13861254/263525
// The code is based on Douglas Crockford's code : https://github.com/douglascrockford/JSON-js/blob/master/json2.js
// No effort was done to support old browsers. JSON.prune will fail on IE8.
(function () {
'use strict';
var DEFAULT_MAX_DEPTH = 6;
var DEFAULT_ARRAY_MAX_LENGTH = 50;
var seen; // Same variable used for all stringifications
var iterator; // either forEachEnumerableOwnProperty, forEachEnumerableProperty or forEachProperty
// iterates on enumerable own properties (default behavior)
var forEachEnumerableOwnProperty = function(obj, callback) {
for (var k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) callback(k);
}
};
// iterates on enumerable properties
var forEachEnumerableProperty = function(obj, callback) {
for (var k in obj) callback(k);
};
// iterates on properties, even non enumerable and inherited ones
// This is dangerous
var forEachProperty = function(obj, callback, excluded) {
if (obj==null) return;
excluded = excluded || {};
Object.getOwnPropertyNames(obj).forEach(function(k){
if (!excluded[k]) {
callback(k);
excluded[k] = true;
}
});
forEachProperty(Object.getPrototypeOf(obj), callback, excluded);
};
Date.prototype.toPrunedJSON = Date.prototype.toJSON;
String.prototype.toPrunedJSON = String.prototype.toJSON;
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
function quote(string) {
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder, depthDecr, arrayMaxLength) {
var i, k, v, length, partial, value = holder[key];
if (value && typeof value === 'object' && typeof value.toPrunedJSON === 'function') {
value = value.toPrunedJSON(key);
}
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
return String(value);
case 'object':
if (!value) {
return 'null';
}
if (depthDecr<=0 || seen.indexOf(value)!==-1) {
return '"-pruned-"';
}
seen.push(value);
partial = [];
if (Object.prototype.toString.apply(value) === '[object Array]') {
length = Math.min(value.length, arrayMaxLength);
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value, depthDecr-1, arrayMaxLength) || 'null';
}
return '[' + partial.join(',') + ']';
}
iterator(value, function(k) {
try {
v = str(k, value, depthDecr-1, arrayMaxLength);
if (v) partial.push(quote(k) + ':' + v);
} catch (e) {
// this try/catch due to forbidden accessors on some objects
}
});
return '{' + partial.join(',') + '}';
}
}
JSON.prune = function (value, depthDecr, arrayMaxLength) {
if (typeof depthDecr == "object") {
var options = depthDecr;
depthDecr = options.depthDecr;
arrayMaxLength = options.arrayMaxLength;
iterator = options.iterator || forEachEnumerableOwnProperty;
if (options.allProperties) iterator = forEachProperty;
else if (options.inheritedProperties) iterator = forEachEnumerableProperty
} else {
iterator = forEachEnumerableOwnProperty;
}
seen = [];
depthDecr = depthDecr || DEFAULT_MAX_DEPTH;
arrayMaxLength = arrayMaxLength || DEFAULT_ARRAY_MAX_LENGTH;
return str('', {'': value}, depthDecr, arrayMaxLength);
};
JSON.prune.log = function() {
console.log.apply(console, Array.prototype.slice.call(arguments).map(function(v){return JSON.parse(JSON.prune(v))}));
}
JSON.prune.forEachProperty = forEachProperty; // you might want to also assign it to Object.forEachProperty
}());