如何以字符串格式显示JavaScript对象的内容,就像我们警告变量时一样?

与显示对象的格式相同。


当前回答

循环引用解决方案

要从包含重复引用(在许多地方对同一对象的引用)(包括循环引用)的对象中生成不包含冗余信息的字符串,请使用JSON.stringify和replacer(在代码段中显示),如下所示

let s = JSON.stringify(obj, refReplacer(), 4);

函数refReplacer(){设m=new Map(),v=new Map),init=null;返回函数(字段,值){让p=m.get(this)+(Array.isArray(this)`[${field}]“:”.“+字段);让isComplex=value==对象(值)如果(isComplex)m.set(值,p);让pp=v.get(value)||'';let path=p.replace(/未定义\.\?/,“”);让val=pp`#REF:${pp[0]==“[”?“$”:“$.”}${pp}“:value;!初始化?(init=value):(val===init?val=“#REF:$”:0);if(!pp&&isComplex)v.set(value,path);返回值;}}// ---------------//测试// ---------------//具有重复引用的gen obj设a={a1:1,a2:2};设b={b1:3,b2:“4”};让obj={o1:{o2:a},b,a};//重复引用a.a3=[1,2,b];//循环引用b.b3=a;//循环引用让s=JSON.stringify(obj,refReplacer(),4);console.log;警报;

基于此(更多信息)的此解决方案为每个对象值创建类似JSONPath的路径,如果同一对象出现两次(或更多),则使用此路径的引用来引用该对象,例如#REF:$.bar.arr[3].foo(其中$表示主对象),而不是“渲染”整个对象(冗余度较低)

奖金:倒置

函数parseRefJSON(json){let objToPath=新映射();let pathToObj=新映射();let o=JSON.parse(JSON);让遍历=(父级,字段)=>{让obj=父级;let path=“#REF:$”;if(字段!==未定义){obj=父[字段];path=objToPath.get(父)+(Array.isArray(父)`[${field}]`:`${field?'。'+字段:''}`);}objToPath.set(obj,路径);pathToObj.set(路径,对象);let ref=路径目标获取(obj);如果(ref)父[字段]=ref;for(让f在obj中)if(obj==对象(obj))遍历(obj,f);}横向(o);返回o;}// ------------//测试// ------------设s=`{“o1”:{“o2”:{“a1”:1,“a2”:2,“a3”:[1.2.{“b1”:3,“b2”:“4”,“b3”:“#REF:$.o1.o2”}]}},“b”:“#REF:$.o1.o2.a3[2]”,“a”:“#REF:$.o1.o2”}`;console.log('打开Chrome控制台查看嵌套字段');let obj=parseRefJSON;console.log(obj);

其他回答

(这已添加到我的GitHub库中)

在这里重塑车轮!这些解决方案都不适合我的情况。所以,我很快修改了威尔森佩奇的答案。这一个不适用于打印到屏幕(通过控制台、文本字段或其他方式)。在这些情况下,它确实工作得很好,而且正如OP所要求的那样,工作得很正常。这里的许多答案没有解决OP请求的使用警报的问题。无论如何,它是为数据传输而格式化的。此版本似乎返回了与toSource()非常相似的结果。我没有针对JSON.stringify进行过测试,但我认为这也是一回事。这个版本更像是一个poly-fil,因此您可以在任何环境中使用它。此函数的结果是有效的Javascript对象声明。

我不会怀疑这样的事情是否已经在某个地方发生了,但这比花一段时间搜索过去的答案要短得多。因为当我开始搜索这个问题时,这个问题是我在谷歌上的热门话题;我想把它放在这里可能会帮助其他人。

无论如何,该函数的结果将是对象的字符串表示,即使对象具有嵌入的对象和数组,即使这些对象或数组具有更进一步的嵌入对象和数组。(我听说你喜欢喝酒?所以,我用冷却器给你的车拉皮条。然后,我用冰箱给你的冷却器拉皮条,所以,你的冷却器可以在你保持凉爽的同时喝酒。)

数组用[]而不是{}存储,因此没有键/值对,只有值。像常规数组一样。因此,它们的创建方式与数组相同。

此外,所有字符串(包括键名)都被引用,除非这些字符串具有特殊字符(如空格或斜线),否则这是不必要的。但是,我不想检测到这一点,只是为了删除一些引用,否则这些引用仍然可以正常工作。

然后,这个生成的字符串可以与eval一起使用,也可以通过字符串操作将其转储到var中。因此,从文本重新创建对象。

function ObjToSource(o){
    if (!o) return 'null';
    var k="",na=typeof(o.length)=="undefined"?1:0,str="";
    for(var p in o){
        if (na) k = "'"+p+ "':";
        if (typeof o[p] == "string") str += k + "'" + o[p]+"',";
        else if (typeof o[p] == "object") str += k + ObjToSource(o[p])+",";
        else str += k + o[p] + ",";
    }
    if (na) return "{"+str.slice(0,-1)+"}";
    else return "["+str.slice(0,-1)+"]";
}

如果我搞砸了,让我知道,在我的测试中效果很好。此外,我能想到的检测类型数组的唯一方法是检查长度的存在。因为Javascript确实将数组存储为对象,所以我实际上无法检查数组类型(没有这样的类型!)。如果其他人知道更好的方法,我很乐意听到。因为,如果您的对象也有一个名为length的属性,那么这个函数将错误地将其视为数组。

EDIT:添加了对空值对象的检查。谢谢布罗克·亚当斯

EDIT:下面是能够打印无限递归对象的固定函数。这与从FF打印toSource不同,因为toSource将打印一次无限递归,其中as,此函数将立即终止它。这个函数的运行速度比上面的慢,所以我在这里添加它,而不是编辑上面的函数,因为只有当你计划在某个地方传递链接到自己的对象时,才需要它。

const ObjToSource=(o)=> {
    if (!o) return null;
    let str="",na=0,k,p;
    if (typeof(o) == "object") {
        if (!ObjToSource.check) ObjToSource.check = new Array();
        for (k=ObjToSource.check.length;na<k;na++) if (ObjToSource.check[na]==o) return '{}';
        ObjToSource.check.push(o);
    }
    k="",na=typeof(o.length)=="undefined"?1:0;
    for(p in o){
        if (na) k = "'"+p+"':";
        if (typeof o[p] == "string") str += k+"'"+o[p]+"',";
        else if (typeof o[p] == "object") str += k+ObjToSource(o[p])+",";
        else str += k+o[p]+",";
    }
    if (typeof(o) == "object") ObjToSource.check.pop();
    if (na) return "{"+str.slice(0,-1)+"}";
    else return "["+str.slice(0,-1)+"]";
}

测试:

var test1 = new Object();
test1.foo = 1;
test1.bar = 2;

var testobject = new Object();
testobject.run = 1;
testobject.fast = null;
testobject.loop = testobject;
testobject.dup = test1;

console.log(ObjToSource(testobject));
console.log(testobject.toSource());

结果:

{'run':1,'fast':null,'loop':{},'dup':{'foo':1,'bar':2}}
({run:1, fast:null, loop:{run:1, fast:null, loop:{}, dup:{foo:1, bar:2}}, dup:{foo:1, bar:2}})

注意:试图打印document.body是一个可怕的例子。首先,FF在使用toSource时只打印一个空对象字符串。当使用上述函数时,FF在SecurityError上崩溃:操作不安全。。Chrome将在UncaughtRangeError上崩溃:超过了最大调用堆栈大小。显然,document.body并不是要转换为字符串。因为它要么太大,要么违反安全策略访问某些财产。除非,我把这里搞砸了,告诉我!

我需要一种递归打印对象的方法,pagewil提供了答案(谢谢!)。我对它进行了一点更新,以包括一种打印到某个级别的方法,并添加间距,以便根据当前级别正确缩进,以便更易于阅读。

// Recursive print of object
var print = function( o, maxLevel, level ) {
    if ( typeof level == "undefined" ) {
        level = 0;
    }
    if ( typeof level == "undefined" ) {
        maxLevel = 0;
    }

    var str = '';
    // Remove this if you don't want the pre tag, but make sure to remove
    // the close pre tag on the bottom as well
    if ( level == 0 ) {
        str = '<pre>';
    }

    var levelStr = '';
    for ( var x = 0; x < level; x++ ) {
        levelStr += '    ';
    }

    if ( maxLevel != 0 && level >= maxLevel ) {
        str += levelStr + '...</br>';
        return str;
    }

    for ( var p in o ) {
        if ( typeof o[p] == 'string' ) {
            str += levelStr +
                p + ': ' + o[p] + ' </br>';
        } else {
            str += levelStr +
                p + ': { </br>' + print( o[p], maxLevel, level + 1 ) + levelStr + '}</br>';
        }
    }

    // Remove this if you don't want the pre tag, but make sure to remove
    // the open pre tag on the top as well
    if ( level == 0 ) {
        str += '</pre>';
    }
    return str;
};

用法:

var pagewilsObject = {
    name: 'Wilson Page',
    contact: {
        email: 'wilson@hotmail.com',
        tel: '123456789'
    }  
}

// Recursive of whole object
$('body').append( print(pagewilsObject) ); 

// Recursive of myObject up to 1 level, will only show name 
// and that there is a contact object
$('body').append( print(pagewilsObject, 1) ); 

Javascript函数

<script type="text/javascript">
    function print_r(theObj){ 
       if(theObj.constructor == Array || theObj.constructor == Object){ 
          document.write("<ul>") 
          for(var p in theObj){ 
             if(theObj[p].constructor == Array || theObj[p].constructor == Object){ 
                document.write("<li>["+p+"] => "+typeof(theObj)+"</li>"); 
                document.write("<ul>") 
                print_r(theObj[p]); 
                document.write("</ul>") 
             } else { 
                document.write("<li>["+p+"] => "+theObj[p]+"</li>"); 
             } 
          } 
          document.write("</ul>") 
       } 
    } 
</script>

正在打印对象

<script type="text/javascript">
print_r(JAVACRIPT_ARRAY_OR_OBJECT);
</script> 

通过Javascript中的print_r

功能:

var print = function(o){
    var str='';

    for(var p in o){
        if(typeof o[p] == 'string'){
            str+= p + ': ' + o[p]+'; </br>';
        }else{
            str+= p + ': { </br>' + print(o[p]) + '}';
        }
    }

    return str;
}

用法:

var myObject = {
    name: 'Wilson Page',
    contact: {
        email: 'wilson@hotmail.com',
        tel: '123456789'
    }  
}

$('body').append( print(myObject) );

例子:

http://jsfiddle.net/WilsonPage/6eqMn/

我总是使用console.log(“对象将是:”,obj,obj1)。这样我就不需要用JSON来解决字符串问题。对象的所有财产都将很好地展开。