(Zostało to dodane do mojej biblioteki na GitHub )
Odkryj na nowo koło tutaj! Żadne z tych rozwiązań nie działało w mojej sytuacji. Szybko więc udokumentowałem odpowiedź wilsonpage'a . Ten nie jest przeznaczony do drukowania na ekranie (przez konsolę, pole tekstowe lub cokolwiek innego). To działa dobrze w takich sytuacjach i działa dobrze, zgodnie z wnioskiem PO alert
. Wiele odpowiedzi tutaj nie dotyczy użycia alert
zgodnie z żądaniem PO. W każdym razie jest on jednak sformatowany do przesyłania danych. Ta wersja wydaje się zwracać bardzo podobny wynik jak toSource()
. Nie testowałem przeciwko JSON.stringify
, ale zakładam, że chodzi o to samo. Ta wersja jest bardziej jak poly-fil, dzięki czemu można go używać w dowolnym środowisku. Wynikiem tej funkcji jest poprawna deklaracja obiektu JavaScript.
Nie wątpiłbym, że coś takiego już gdzieś jest na SO, ale było to tylko krótsze, aby to zrobić, niż spędzić chwilę na szukaniu poprzednich odpowiedzi. A ponieważ to pytanie było moim największym hitem w Google, kiedy zacząłem o tym szukać; Pomyślałem, że umieszczenie go tutaj może pomóc innym.
W każdym razie wynikiem tej funkcji będzie ciąg znaków reprezentujący obiekt, nawet jeśli obiekt ma obiekty osadzone i tablice, a nawet jeśli te obiekty lub tablice mają jeszcze inne obiekty osadzone i tablice. (Słyszałem, że lubisz pić? A więc wypompowałem twój samochód chłodnicą. A potem wypchnąłem twoją lodówkę chłodnicą. Więc twoja chłodnica może pić, kiedy jesteś cool.)
Tablice są przechowywane []
zamiast, {}
a zatem nie mają par klucz / wartość, tylko wartości. Jak zwykłe tablice. Dlatego są tworzone tak jak tablice.
Również wszystkie ciągi (w tym nazwy kluczy) są cytowane, nie jest to konieczne, chyba że ciągi te zawierają znaki specjalne (takie jak spacja lub ukośnik). Ale nie chciałem tego wykrywać, aby usunąć niektóre cytaty, które w przeciwnym razie nadal działałyby dobrze.
Ten wynikowy ciąg może być następnie użyty z eval
lub po prostu zrzucony do manipulacji ciągiem var varru. W ten sposób ponownie utworzysz obiekt z tekstu.
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)+"]";
}
Daj mi znać, jeśli wszystko zepsułem, działa dobrze w moich testach. Jedynym sposobem, w jaki mogłem wymyślić typ, array
było sprawdzenie jego obecności length
. Ponieważ JavaScript naprawdę przechowuje tablice jako obiekty, nie mogę sprawdzić typu array
(nie ma takiego typu!). Jeśli ktoś inny zna lepszy sposób, chciałbym to usłyszeć. Ponieważ jeśli twój obiekt ma również właściwość o nazwie, length
funkcja ta omyłkowo potraktuje ją jako tablicę.
EDYCJA: Dodano sprawdzanie obiektów o wartości zerowej. Dzięki, Brock Adams
EDYCJA: Poniżej znajduje się stała funkcja umożliwiająca drukowanie nieskończenie rekurencyjnych obiektów. To nie jest drukowane tak samo jak toSource
z FF, ponieważ toSource
wydrukuje nieskończoną rekurencję jeden raz, gdzie jak, ta funkcja natychmiast ją zabije. Ta funkcja działa wolniej niż powyższa, więc dodaję ją tutaj zamiast edytować powyższą funkcję, ponieważ jest ona potrzebna tylko wtedy, gdy planujesz gdzieś przekazać obiekty, które łączą się z sobą.
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)+"]";
}
Test:
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());
Wynik:
{'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}})
UWAGA: Próba wydrukowania document.body
jest okropnym przykładem. Po pierwsze, FF po prostu drukuje pusty ciąg znaków obiektu podczas używania toSource
. Podczas korzystania z powyższej funkcji FF ulega awarii SecurityError: The operation is insecure.
. Chrome się zawiesi Uncaught RangeError: Maximum call stack size exceeded
. Oczywiście document.body
nie miał być konwertowany na ciąg znaków. Ponieważ jest albo za duży, albo przeciwko polityce bezpieczeństwa, aby uzyskać dostęp do niektórych właściwości. Chyba, że coś tu pomieszałem, powiedz!