เทคนิค "eval ()" และ "JSON.parse ()" ใช้รูปแบบที่ไม่ซ้ำกัน
- ด้วย "EVAL ()" วงเล็บจะต้อง
- ด้วย "JSON.parse ()" วงเล็บจะต้องห้าม
ระวังมีฟังก์ชัน "stringify ()" ที่สร้างรูปแบบ "eval" สำหรับ ajax คุณควรใช้เฉพาะรูปแบบ JSON
แม้ว่า "eval" จะรวมภาษา JavaScript ทั้งหมดไว้ด้วยกัน แต่ JSON จะใช้ภาษาเพียงบางส่วนเท่านั้น ในบรรดาโครงสร้างในภาษา JavaScript ที่ "eval" ต้องรับรู้คือ"Block statement" (aka "compound statement") ; ซึ่งเป็นวงเล็บปีกกาคู่หรือหยิก "{}" ที่มีข้อความอยู่ข้างใน แต่ยังใช้วงเล็บปีกกาในไวยากรณ์ของตัวอักษรของวัตถุ การตีความแตกต่างกันไปตามบริบทที่โค้ดปรากฏ บางสิ่งอาจดูเหมือนเป็นอ็อบเจกต์ลิเทอรัลสำหรับคุณ แต่ "eval" จะเห็นว่าเป็นคำสั่งผสม
ในภาษา JavaScript ตัวอักษรออบเจ็กต์จะอยู่ทางด้านขวาของงาน
var myObj = { ...some..code..here... };
วัตถุตามตัวอักษรไม่ได้เกิดขึ้นเอง
{ ...some..code..here... }
ย้อนกลับไปที่คำถามเดิมของ OP ซึ่งถามในปี 2008 เขาถามว่าทำไมสิ่งต่อไปนี้จึงล้มเหลวใน "eval ()":
{ title: "One", key: "1" }
คำตอบคือมันดูเหมือนคำสั่งประกอบ ในการแปลงเป็นวัตถุคุณต้องใส่ไว้ในบริบทที่คำสั่งผสมเป็นไปไม่ได้ ซึ่งทำได้โดยใส่วงเล็บรอบ ๆ
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
OP ยังถามว่าเหตุใดคำสั่งที่คล้ายกันจึงประสบความสำเร็จในการประเมิน:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
คำตอบเดียวกันนี้ใช้ได้ - วงเล็บปีกกาอยู่ในบริบทที่ไม่สามารถใช้คำสั่งผสมได้ นี่คือบริบทอาร์เรย์ " [...]
" และอาร์เรย์สามารถมีออบเจ็กต์ได้ แต่ไม่สามารถมีคำสั่งได้
ซึ่งแตกต่างจาก "eval ()" ตรงที่ JSON มีขีดความสามารถที่ จำกัด มาก ข้อ จำกัด คือเจตนา ผู้ออกแบบ JSON ตั้งใจให้เป็นชุดย่อยของ JavaScript แบบเรียบง่ายโดยใช้เฉพาะไวยากรณ์ที่ปรากฏทางด้านขวามือของงาน ดังนั้นหากคุณมีโค้ดที่แยกวิเคราะห์ใน JSON ได้อย่างถูกต้อง ...
var myVar = JSON.parse("...some...code...here...");
... นั่นหมายความว่ามันจะแยกวิเคราะห์ทางขวามือของงานเช่นนี้ด้วย ..
var myVar = ...some..code..here... ;
แต่นั่นไม่ใช่ข้อ จำกัด เพียงอย่างเดียวใน JSON ข้อกำหนดภาษา BNF สำหรับ JSONเป็นเรื่องง่ายมาก ตัวอย่างเช่นไม่อนุญาตให้ใช้เครื่องหมายคำพูดเดี่ยวเพื่อระบุสตริง (เช่น JavaScript และ Perl do) และไม่มีวิธีแสดงอักขระเดี่ยวเป็นไบต์ (เช่น 'C') น่าเสียดายที่ไม่อนุญาตให้แสดงความคิดเห็น (ซึ่งจะดีมากเมื่อสร้างไฟล์กำหนดค่า) ข้อดีของข้อ จำกัด เหล่านี้คือการแยกวิเคราะห์ JSON นั้นรวดเร็วและไม่มีโอกาสในการแทรกโค้ด (ภัยคุกคามด้านความปลอดภัย)
เนื่องจากข้อ จำกัด เหล่านี้ JSON จึงไม่ใช้วงเล็บ ดังนั้นวงเล็บในสตริง JSON จึงเป็นอักขระที่ไม่ถูกต้อง
ใช้รูปแบบ JSON กับ ajax เสมอด้วยเหตุผลต่อไปนี้:
- ไปป์ไลน์ ajax ทั่วไปจะถูกกำหนดค่าสำหรับ JSON
- การใช้ "eval ()" จะถูกวิพากษ์วิจารณ์ว่าเป็นความเสี่ยงด้านความปลอดภัย
ดังตัวอย่างของไปป์ไลน์ของ ajax ให้พิจารณาโปรแกรมที่เกี่ยวข้องกับเซิร์ฟเวอร์โหนดและไคลเอ็นต์ jQuery โปรแกรมไคลเอนต์ที่ใช้โทร jQuery $.ajax({dataType:'json',...etc.});
มีแบบฟอร์ม JQuery สร้างออบเจ็กต์ jqXHR เพื่อใช้ในภายหลังจากนั้นแพ็กเกจและส่งคำขอที่เกี่ยวข้อง เซิร์ฟเวอร์ยอมรับคำขอประมวลผลและพร้อมที่จะตอบสนอง โปรแกรมเซิร์ฟเวอร์จะเรียกใช้เมธอดres.json(data)
เพื่อทำแพ็กเกจและส่งการตอบกลับ กลับไปที่ฝั่งไคลเอ็นต์ jQuery ยอมรับการตอบสนองปรึกษาอ็อบเจ็กต์ jqXHR ที่เกี่ยวข้องและประมวลผลข้อมูลที่จัดรูปแบบ JSON ทั้งหมดนี้ใช้งานได้โดยไม่ต้องมีการแปลงข้อมูลด้วยตนเอง การตอบกลับไม่เกี่ยวข้องกับการเรียกใช้ JSON.stringify () อย่างชัดเจนบนเซิร์ฟเวอร์ Node และไม่มีการเรียกใช้ JSON.parse () บนไคลเอ็นต์อย่างชัดเจน ที่จัดการทั้งหมดสำหรับคุณ
การใช้ "eval" เกี่ยวข้องกับความเสี่ยงด้านความปลอดภัยในการแทรกโค้ด คุณอาจคิดว่าไม่มีทางเกิดขึ้นได้ แต่แฮกเกอร์สามารถสร้างสรรค์ได้ นอกจากนี้ "eval" ยังเป็นปัญหาสำหรับการเพิ่มประสิทธิภาพของ Javascript
หากคุณพบว่าตัวเองใช้ฟังก์ชัน "stringify ()" โปรดทราบว่าบางฟังก์ชันที่มีชื่อนั้นจะสร้างสตริงที่เข้ากันได้กับ "eval" ไม่ใช่กับ JSON ตัวอย่างเช่นใน Node สิ่งต่อไปนี้จะให้ฟังก์ชันที่สร้างสตริงในรูปแบบที่เข้ากันได้กับ "eval":
var stringify = require('node-stringify');
สิ่งนี้มีประโยชน์ แต่ถ้าคุณไม่มีความต้องการเฉพาะก็อาจไม่ใช่สิ่งที่คุณต้องการ