【问题标题】:Stringify DOMWindow object字符串化 DOMWindow 对象
【发布时间】:2011-05-04 00:57:18
【问题描述】:

由于某种原因,我似乎无法在 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 上测试。有谁知道我该如何实现这一目标?

编辑

将编辑移至一个新问题,因为它并不具体针对此问题。

【问题讨论】:

标签: javascript json


【解决方案1】:

您没有收到错误消息吗?我得到TypeError: Converting circular structure to JSON。我会说,这是不可能的。

另外,windowwindow.self 指向同一个对象(全局对象),因此您不需要使用该属性...

【讨论】:

    【解决方案2】:

    在 Chrome 8 开发中,我得到 TypeError: Converting circular structure to JSON(窗口通常包含自引用 selfwindowtop 引用,如果您不在框架中),所以直接使用 @987654325 @ 将不起作用。

    听起来您正在使用它进行调试输出。如果您只关心某些信息,您可以将该信息复制到一个对象,然后对其进行字符串化。然后将其封装在一个函数中,以从window 中获取您认为您会关心的所有信息。

    var data = JSON.stringify({
        'location': window.location
        // etc
    });
    

    【讨论】:

      【解决方案3】:

      为什么要序列化 ​​DOM?如果必须,Crescent 的链接是您需要查看的地方。不能序列化(字符串化)window对象的原因是它包含循环引用,JSON.stringify默认不支持。

      【讨论】:

      • @dosboy 注意“你为什么要这样做”。序列化 DOM 几乎没有任何充分的理由。
      • @Alex 很多时间过去了,你们知道有什么方法可以通过 IPC 模块发送 DOM 对象吗?
      • OP为什么要序列化DOM并不重要。他们只是想知道如何做到这一点。这个“答案”没有为 OP 的问题提供任何解决方案(有)。
      【解决方案4】:

      正如其他人所说,stringify 不支持 DOMWindow 包含的循环引用。通常,循环引用可以使用 Douglas Cockford 的 JSON cycle.js 转换为 JSON。

      但是,我刚刚在window 上尝试过这个,无论如何它都会导致堆栈溢出。虽然这可能是 cycle.js 代码中的一个错误,但 window 似乎更有可能是一个太大的对象。

      【讨论】:

        【解决方案5】:

        这个答案不是我的,但我来这里是为了同样的事情,并在其他地方找到了这个答案。 我没有打开那个页面了——我确实有 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
        
        }());
        

        【讨论】:

        • 这个好像是从this answer复制过来的
        • @Bergi:该帖子保留了完整的代码 cmets,这似乎指向所有相关来源。看来回购实际上是基于答案。
        • 布拉德,Bergi 所链接的答案很可能是您从哪里获得原始代码。
        • @BoltClock:哦,对了,我没有注意到 cmets 包含了属性。谢谢!
        猜你喜欢
        • 2013-08-25
        • 2012-12-24
        • 2021-12-02
        • 2021-03-12
        • 2019-10-03
        • 1970-01-01
        • 1970-01-01
        • 2018-07-06
        • 2012-10-08
        相关资源
        最近更新 更多