Tôi biết đây là một chủ đề cũ, nhưng có lẽ vẫn còn một số liên quan trong đó?
Lấy cảm hứng từ giải pháp tốt của Jacky Li, tôi đã thử một biến thể nhỏ của riêng mình với vật kính để có thể quan tâm đến các kết hợp tùy ý của các mảng và đối tượng làm đầu vào. Tôi đã xem xét cách PHP sẽ làm điều đó và cố gắng làm cho một cái gì đó "tương tự" diễn ra. Đây là mã của tôi:
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;
}
Nếu hàm được gọi mà không có str
-argument, nó sẽ được coi window.location.search.slice(1)
là đầu vào.
Vài ví dụ:
['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')
kết quả trong
{"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
Trong khi giải pháp của Jacky Li sẽ tạo ra hộp đựng bên ngoài a
như một vật thể đơn giản
{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output
getargs()
nhìn vào chỉ mục đã cho đầu tiên cho bất kỳ mức nào để xác định xem mức này sẽ là một đối tượng (chỉ số không phải số) hay một mảng (số hoặc trống), do đó dẫn đến kết quả như được hiển thị trong bove danh sách (số 6).
Nếu đối tượng hiện tại là một mảng thì null
s được chèn vào bất cứ nơi nào cần thiết để biểu diễn các vị trí trống. Mảng luôn được đánh số liên tục và dựa trên 0).
Lưu ý rằng trong ví dụ không có. 8 "autoincrement" cho các chỉ số trống vẫn hoạt động, ngay cả khi chúng ta đang xử lý một đối tượng chứ không phải một mảng.
Theo như tôi đã thử nghiệm, getargs()
hành vi của tôi khá giống với $.deparam()
plugin jQuery tuyệt vời của Chriss Roger được đề cập trong câu trả lời được chấp nhận. Sự khác biệt chính là getargs
chạy mà không có jQuery và nó tự động tăng các đối tượng trong khi $.deparam()
sẽ không làm điều đó:
JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);
kết quả trong
{"3":["7","99"],"x":"hi","undefined":"13"}
Trong $.deparam()
chỉ mục []
được hiểu là một undefined
thay vì một chỉ mục số tự động tăng.
+
. Bây giờ nó thay thế tất cả chúng!