Saya tahu ini adalah utas lama, tetapi mungkin masih ada relevansinya?
Terinspirasi oleh solusi Jacky Li yang baik, saya mencoba sedikit variasi sendiri dengan tujuan untuk juga dapat menangani kombinasi sembarang array dan objek sebagai input. Saya melihat bagaimana PHP akan melakukannya dan mencoba untuk mendapatkan sesuatu yang "serupa" terjadi. Ini kode saya:
function getargs(str){
var ret={};
function build(urlnam,urlval,obj){ // extend the return object ...
var i,k,o=obj, x, rx=/\[([^\]]*)\]/g, idx=[urlnam.replace(rx,'')];
while (x=rx.exec(urlnam)) idx.push(x[1]);
while(true){
k=idx.shift();
if(k.trim()=='') {// key is empty: autoincremented index
if (o.constructor.name=='Array') k=o.length; // for Array
else if (o===obj ) {k=null} // for first level property name
else {k=-1; // for Object
for(i in o) if (+i>k) k=+i;
k++;
}
}
if(idx.length) {
// set up an array if the next key (idx[0]) appears to be
// numeric or empty, otherwise set up an object:
if (o[k]==null || typeof o[k]!='object') o[k]=isNaN(idx[0])?{}:[];
o=o[k]; // move on to the next level
}
else { // OK, time to store the urlval in its chosen place ...
// console.log('key',k,'val',urlval);
o[k]=urlval===""?null:urlval; break; // ... and leave the while loop.
}
}
return obj;
}
// ncnvt: is a flag that governs the conversion of
// numeric strings into numbers
var ncnvt=true,i,k,p,v,argarr=[],
ar=(str||window.location.search.substring(1)).split("&"),
l=ar.length;
for (i=0;i<l;i++) {if (ar[i]==="") continue;
p=ar[i].split("=");k=decodeURIComponent(p[0]);
v=p[1];v=(v!=null)?decodeURIComponent(v.replace(/\+/g,'%20')):'';
if (ncnvt && v.trim()>"" && !isNaN(v)) v-=0;
argarr.push([k,v]); // array: key-value-pairs of all arguments
}
for (i=0,l=argarr.length;i<l;i++) build(argarr[i][0],argarr[i][1],ret);
return ret;
}
Jika fungsi dipanggil tanpa str-argumen itu akan dianggap window.location.search.slice(1)sebagai input.
Beberapa contoh:
['a=1&a=2', // 1
'x[y][0][z][]=1', // 2
'hello=[%22world%22]&world=hello', // 3
'a=1&a=2&&b&c=3&d=&=e&', // 4
'fld[2][]=2&fld[][]=3&fld[3][]=4&fld[]=bb&fld[]=cc', // 5
$.param({a:[[1,2],[3,4],{aa:'one',bb:'two'},[5,6]]}), // 6
'a[]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13',// 7
'a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13'// 8
].map(function(v){return JSON.stringify(getargs(v));}).join('\n')
menghasilkan
{"a":2} // 1
{"x":{"y":[{"z":[1]}]}} // 2
{"hello":"[\"world\"]","world":"hello"} // 3
{"a":2,"b":null,"c":3,"d":null,"null":"e"} // 4 = { a: 2, b: null, c: 3, d: null, null: "e" }
{"fld":[null,null,[2],[3,4],"bb","cc"]} // 5
{"a":[[1,2],[3,4],{"aa":"one","bb":"two"},[5,6]]} // 6
{"a":["hi",2,null,[7,99],13]} // 7
{"a":{"0":2,"3":[7,99],"4":13,"x":"hi"}} // 8
Sedangkan solusi Jacky Li akan menghasilkan wadah luar asebagai benda biasa
{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output
getargs() melihat indeks pertama yang diberikan untuk setiap level untuk menentukan apakah level ini akan menjadi objek (indeks non-numerik) atau array (numerik atau kosong), sehingga menghasilkan output seperti yang ditunjukkan pada daftar di atas (no. 6).
Jika objek saat ini adalah array maka nulls bisa disisipkan dimanapun diperlukan untuk merepresentasikan posisi kosong. Array selalu diberi nomor berurutan dan berbasis 0).
Perhatikan, bahwa dalam contoh no. 8 "autoincrement" untuk indeks kosong masih berfungsi, meskipun kita berurusan dengan objek sekarang dan bukan array.
Sejauh saya telah mengujinya, getargs()perilaku saya cukup mirip dengan $.deparam() plugin jQuery hebat Chriss Roger yang disebutkan dalam jawaban yang diterima. Perbedaan utamanya adalah bahwa getargsberjalan tanpa jQuery dan itu melakukan autoincrement pada objek sementara tidak$.deparam() akan melakukannya:
JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);
menghasilkan
{"3":["7","99"],"x":"hi","undefined":"13"}
Dalam $.deparam()indeks []diinterpretasikan sebagai undefinedbukan indeks numerik yang bertambah otomatis.
+. Sekarang menggantikan semuanya!