ฉันรู้ว่านี่เป็นกระทู้เก่า แต่อาจมีความเกี่ยวข้องอยู่บ้าง?
แรงบันดาลใจจากวิธีแก้ปัญหาที่ดีของ Jacky Li ฉันได้ลองใช้รูปแบบของตัวเองเล็กน้อยโดยมีวัตถุประสงค์เพื่อให้สามารถดูแลการรวมอาร์เรย์และวัตถุโดยพลการเป็นอินพุตได้ ฉันดูว่า PHP จะทำมันได้อย่างไรและพยายามทำให้บางอย่าง "คล้ายกัน" เกิดขึ้น นี่คือรหัสของฉัน:
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;
}
หากฟังก์ชันถูกเรียกโดยไม่มี - str
อาร์กิวเมนต์จะถือว่า window.location.search.slice(1)
เป็นอินพุต
ตัวอย่างบางส่วน:
['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')
ผลลัพธ์ใน
{"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
ในขณะที่วิธีการแก้ปัญหาของ Jacky Li จะผลิตภาชนะชั้นนอกสำหรับa
เป็นวัตถุธรรมดา
{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output
getargs()
ดูดัชนีที่กำหนดแรกสำหรับระดับใด ๆ เพื่อพิจารณาว่าระดับนี้จะเป็นวัตถุ (ดัชนีที่ไม่ใช่ตัวเลข) หรืออาร์เรย์ (ตัวเลขหรือว่างเปล่า) จึงทำให้ได้ผลลัพธ์ตามที่แสดงในรายการด้านบน (หมายเลข 6)
หากออบเจ็กต์ปัจจุบันเป็นอาร์เรย์จะnull
มีการแทรกเมื่อจำเป็นเพื่อแสดงตำแหน่งว่าง อาร์เรย์จะมีหมายเลขตามลำดับและอิง 0 เสมอ)
โปรดทราบว่าในตัวอย่างไม่มี 8 "การสร้างอัตโนมัติ" สำหรับดัชนีว่างยังคงใช้งานได้แม้ว่าตอนนี้เรากำลังจัดการกับออบเจ็กต์ไม่ใช่อาร์เรย์ก็ตาม
เท่าที่ฉันได้ทดสอบแล้วgetargs()
พฤติกรรมของฉันค่อนข้างเหมือนกับ$.deparam()
ปลั๊กอิน jQuery ที่ยอดเยี่ยมของ Chriss Roger ที่กล่าวถึงในคำตอบที่ยอมรับ ความแตกต่างที่สำคัญคือgetargs
ทำงานโดยไม่มี jQuery และมันจะสร้างอัตโนมัติในวัตถุในขณะที่$.deparam()
จะไม่ทำเช่นนั้น:
JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);
ผลลัพธ์ใน
{"3":["7","99"],"x":"hi","undefined":"13"}
ใน$.deparam()
ดัชนี[]
จะถูกตีความว่าเป็นundefined
แทนที่จะเป็นดัชนีตัวเลขที่เพิ่มอัตโนมัติ
+
เท่านั้น ตอนนี้มันแทนที่พวกเขาทั้งหมด!