Escape สตริงในบริบท eval ด้วย JSON.stringify

Nov 13 2020

ก่อนอื่น: ฉันรู้ว่ามีคำถามมากมายที่เกี่ยวข้องกับการหลบหนี แต่จนถึงขณะนี้ฉันยังไม่พบคำตอบที่ใช้ได้ สมมติว่าฉันมีฟังก์ชั่นของเล่นง่ายๆสำหรับการสาธิต:

function f(somePOJO) {
  var s = eval("'" + JSON.stringify(somePOJO) + "';"); // for demonstration only
  return JSON.parse(s);
}
const clone = f({a: 1, b: "c"});

ระบุอ็อบเจ็กต์ลิเทอรัลเช่น{a: 1, b: "c"}(POJO) fควรส่งคืน "โคลน" ของมัน (โปรดทราบว่าฉันไม่ได้ใช้วิธีนี้ในการโคลนนิ่งหรือสิ่งที่คล้ายกันจริงๆและฉันตระหนักดีว่านั่นevalเป็นสิ่งที่ชั่วร้ายและยังไม่จำเป็นต้องใช้ที่นี่ด้วยซ้ำมันเป็นเพียงการสาธิตการแก้ปัญหา

ใช้งานได้ดี แต่ตราบใดที่ค่า POJO ไม่มี a '. แน่นอนว่าตอนนี้ฉันสามารถหลีกเลี่ยง JSON ได้โดยใช้JSON.stringify(somePOJO).replace(/'/g, "\\'")ไฟล์. นี้ทำงานได้ถ้าค่า POJO มีแต่ไม่ถ้าพวกเขามี' \\'และสิ่งนี้ก่อให้เกิดการหลบหนี ...

มีวิธีแก้ปัญหานี้หรือไม่?

คำตอบ

1 traktor Nov 13 2020 at 14:01

ฟังก์ชั่นการหลบหนีเพื่อรักษาสตริง JSON ผ่านการประเมินโดยevalฟังก์ชั่นคอมไพเลอร์ JavaScript ภายใต้สถานการณ์บางหรือโดยฟังก์ชั่นที่เป็นจริงJSON.parse วิธีJSON.stringifyนี้JSONจะทำให้ค่าสตริงมีความสุขไม่ใช่แค่ชนิดข้อมูลออบเจ็กต์

function f(somePOJO) {
  var s = eval( JSON.stringify(JSON.stringify(somePOJO)) );
  return JSON.parse(s);
}
const obj = {a: 1, b: "c", d: "back\\, forward/"}
const clone = f(obj);
console.log(obj);
console.log(clone);

เหตุผลที่ไม่ใช่หนึ่งในescape/encodeURI/encodeURIComponentตระกูลของฟังก์ชันคือสิ่งเหล่านี้มีไว้สำหรับการหลีกเลี่ยงอักขระเพื่อรวมไว้ใน URL ในขณะที่กรณีนี้เกี่ยวกับการหลีกเลี่ยงอักขระที่จะแยกวิเคราะห์โดยโปรแกรมแยกวิเคราะห์ JavaScipt

ในกรณีส่วนใหญ่โดยเฉพาะอย่างยิ่งในการแยกวิเคราะห์ข้อความ JSON โดยใช้การJSON.parseสตริงข้อความ JSON เป็นครั้งที่สองและแยกวิเคราะห์สองครั้งนั้นไม่จำเป็น

ตอนนี้ค่อนข้างน่าสนใจทางวิชาการ แต่ก่อนที่จะมีการนำJSONเข้าสู่ Javascript เราสามารถผูกสตริงได้โดยการตรวจสอบอักขระและแบ็กสแลชที่หลบหนีแบ็กสแลชอย่างต่อเนื่องเครื่องหมายคำพูดอย่างน้อยหนึ่งชนิดและรหัสควบคุม Unicode ที่หลบหนีคำถามที่โพสต์อาจขาดหายไปบางส่วน เกี่ยวกับความจำเป็นในการหลีกเลี่ยงอักขระแบ็กสแลชและเครื่องหมายคำพูด