(Isso foi adicionado à minha biblioteca no GitHub )
Reinventando a roda aqui! Nenhuma dessas soluções funcionou para a minha situação. Então, rapidamente identifiquei a resposta de wilsonpage . Este não é para impressão em tela (via console, campo de texto ou o que for). Funciona bem nessas situações e funciona bem como o OP solicitou alert
. Muitas respostas aqui não tratam do uso alert
conforme o OP solicitado. De qualquer forma, ele é formatado para o transporte de dados. Esta versão parece retornar um resultado muito semelhante ao toSource()
. Ainda não testei JSON.stringify
, mas presumo que isso seja a mesma coisa. Esta versão é mais como um poly-fil, para que você possa usá-lo em qualquer ambiente. O resultado dessa função é uma declaração de objeto Javascript válida.
Eu não duvido que algo assim já esteja no SO em algum lugar, mas foi mais curto do que gastar um tempo procurando respostas anteriores. E já que essa pergunta foi o meu maior sucesso no google, quando comecei a pesquisar sobre isso; Imaginei que colocá-lo aqui pode ajudar os outros.
De qualquer forma, o resultado dessa função será uma representação de string do seu objeto, mesmo que ele tenha objetos e matrizes incorporados, e mesmo que esses objetos ou matrizes tenham ainda mais objetos e matrizes incorporados. (Ouvi dizer que você gosta de beber? Então, apertei seu carro com um refrigerador. E então, apertei seu refrigerador com um refrigerador. Então, seu refrigerador pode beber enquanto você é legal.)
As matrizes são armazenadas com em []
vez de {}
e, portanto, não têm pares de chave / valor, apenas valores. Como matrizes regulares. Portanto, eles são criados como matrizes.
Além disso, todas as cadeias (incluindo nomes de chaves) são citadas, isso não é necessário, a menos que essas cadeias tenham caracteres especiais (como um espaço ou uma barra). Mas não tive vontade de detectar isso apenas para remover algumas aspas que, de outra forma, ainda funcionariam bem.
Essa cadeia resultante pode então ser usada com eval
ou apenas despejando-a em uma manipulação de cadeia variável. Assim, recrie seu objeto novamente, a partir de texto.
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)+"]";
}
Deixe-me saber se eu estraguei tudo, funciona bem nos meus testes. Além disso, a única maneira de pensar em detectar o tipo array
era verificar a presença de length
. Como o Javascript realmente armazena matrizes como objetos, não posso realmente verificar o tipo array
(não existe esse tipo!). Se alguém souber de uma maneira melhor, eu adoraria ouvi-la. Porque, se o seu objeto também tiver uma propriedade nomeada length
, essa função o tratará por engano como uma matriz.
EDIT: Adicionada verificação para objetos com valor nulo. Obrigado Brock Adams
EDIT: Abaixo está a função fixa para poder imprimir objetos infinitamente recursivos. Isso não imprime da mesma forma que a toSource
partir de FF, porque toSource
imprime a recursão infinita uma vez, onde, como, essa função a mata imediatamente. Essa função é mais lenta que a acima, então estou adicionando-a aqui em vez de editar a função acima, pois só é necessária se você planeja passar objetos que se vinculam de volta a si mesmos, em algum lugar.
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)+"]";
}
Teste:
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());
Resultado:
{'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}})
NOTA: Tentar imprimir document.body
é um exemplo terrível. Por um lado, o FF apenas imprime uma string de objeto vazia ao usar toSource
. E ao usar a função acima, o FF trava SecurityError: The operation is insecure.
. E o Chrome falhará Uncaught RangeError: Maximum call stack size exceeded
. Claramente, document.body
não era para ser convertido em string. Porque é muito grande ou é contra a política de segurança acessar determinadas propriedades. A menos que eu estraguei algo aqui em cima, conte!