เมื่อเร็วๆ นี้ ทีม Chrome ได้ประกาศว่าเราจะย้ายพร็อพเพอร์ตี้ DOM ไปยังเชนโปรโตไทป์ การเปลี่ยนแปลงนี้ซึ่งนำมาใช้ใน Chrome 43 (เบต้าในช่วงกลางเดือนเมษายน 2015) จะช่วยให้ Chrome สอดคล้องกับข้อกำหนด Web IDL มากขึ้น รวมถึงการใช้งานของเบราว์เซอร์อื่นๆ เช่น IE และ Firefox แก้ไข: ชี้แจง ปัจจุบันเบราว์เซอร์ที่ใช้ WebKit รุ่นเก่ายังไม่รองรับข้อกำหนดนี้ แต่ Safari รองรับแล้ว
ลักษณะการทํางานแบบใหม่นี้ส่งผลดีในหลายๆ ด้าน ได้แก่
- ปรับปรุงความเข้ากันได้ในเว็บ (IE และ Firefox ทําเช่นนี้อยู่แล้ว) ผ่านการปฏิบัติตามข้อกําหนด
- ช่วยให้คุณสร้าง getter/setter บนออบเจ็กต์ DOM แต่ละรายการได้อย่างมีประสิทธิภาพและสอดคล้องกัน
- เพิ่มโอกาสในการแฮ็กการเขียนโปรแกรม DOM เช่น จะช่วยให้คุณใช้โพลีฟิลล์ที่จำลองฟังก์ชันการทำงานที่ขาดหายไปในบางเบราว์เซอร์และไลบรารี JavaScript ที่ลบล้างลักษณะการทํางานของแอตทริบิวต์ DOM เริ่มต้นได้อย่างมีประสิทธิภาพ
ตัวอย่างเช่น ข้อกำหนด W3C สมมติฐานมีฟังก์ชันการทำงานใหม่บางอย่างที่เรียกว่า isSuperContentEditable
และเบราว์เซอร์ Chrome ไม่ได้นำมาใช้ แต่สามารถ "โพลีฟีล" หรือจำลองฟีเจอร์ด้วยไลบรารีได้ ในฐานะนักพัฒนาไลบรารี คุณย่อมต้องการใช้ prototype
ดังต่อไปนี้เพื่อสร้าง polyfill ที่มีประสิทธิภาพ
Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
get: function() { return true; },
set: function() { /* some logic to set it up */ },
});
ก่อนการเปลี่ยนแปลงนี้ คุณต้องสร้างพร็อพเพอร์ตี้ใหม่ในทุกอินสแตนซ์เพื่อให้สอดคล้องกับพร็อพเพอร์ตี้ DOM อื่นๆ ใน Chrome ซึ่งจะทําให้ HTMLDivElement
แต่ละรายการในหน้าเว็บมีประสิทธิภาพต่ำมาก
การเปลี่ยนแปลงเหล่านี้มีความสําคัญต่อความสอดคล้อง ประสิทธิภาพ และมาตรฐานของแพลตฟอร์มเว็บ แต่ก็อาจก่อให้เกิดปัญหาบางอย่างสําหรับนักพัฒนาซอฟต์แวร์ หากคุณใช้ลักษณะการทํางานนี้เนื่องจากความเข้ากันได้เดิมระหว่าง Chrome กับ WebKit เราขอแนะนําให้คุณตรวจสอบเว็บไซต์และดูสรุปการเปลี่ยนแปลงด้านล่าง
สรุปการเปลี่ยนแปลง
ตอนนี้การใช้ hasOwnProperty
ในอินสแตนซ์ออบเจ็กต์ DOM จะแสดงผลเป็น false
บางครั้งนักพัฒนาซอฟต์แวร์จะใช้ hasOwnProperty
เพื่อตรวจสอบว่ามีพร็อพเพอร์ตี้อยู่ในออบเจ็กต์หรือไม่ การดำเนินการนี้จะใช้งานไม่ได้อีกต่อไปตามข้อกำหนด เนื่องจากตอนนี้แอตทริบิวต์ DOM เป็นส่วนหนึ่งของเชนโปรโตไทป์ และ hasOwnProperty
จะตรวจสอบเฉพาะออบเจ็กต์ปัจจุบันเพื่อดูว่ามีการกำหนดค่าไว้หรือไม่
ก่อนและรวมถึง Chrome 42 คำสั่งต่อไปนี้จะแสดงผลเป็น true
> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");
true
ใน Chrome 43 ขึ้นไป ระบบจะแสดงผลเป็น false
> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");
false
ซึ่งหมายความว่าตอนนี้หากต้องการตรวจสอบว่า isContentEditable
พร้อมใช้งานในองค์ประกอบหรือไม่ คุณจะต้องตรวจสอบโปรโตไทป์ในออบเจ็กต์ HTMLElement เช่น HTMLDivElement
รับค่ามาจาก HTMLElement
ซึ่งกำหนดพร็อพเพอร์ตี้ isContentEditable
> HTMLElement.prototype.hasOwnProperty("isContentEditable");
true
คุณไม่จำเป็นต้องใช้ hasOwnProperty
เสมอไป เราขอแนะนำให้ใช้โอเปอเรนด์ in
ที่ง่ายกว่ามาก เนื่องจากจะตรวจสอบพร็อพเพอร์ตี้ในทั้งเชนโปรโตไทป์
if("isContentEditable" in div) {
// We have support!!
}
Object.getOwnPropertyDescriptor ในอินสแตนซ์ออบเจ็กต์ DOM จะไม่แสดงผลตัวบ่งชี้พร็อพเพอร์ตี้สำหรับแอตทริบิวต์อีกต่อไป
หากเว็บไซต์ต้องการรับตัวบ่งชี้พร็อพเพอร์ตี้สำหรับแอตทริบิวต์บนออบเจ็กต์ DOM คุณจะต้องทําตามเชนโปรโตไทป์
หากต้องการดูคำอธิบายที่พักใน Chrome 42 และเวอร์ชันก่อนหน้า คุณจะต้องดำเนินการดังนี้
> Object.getOwnPropertyDescriptor(div, "isContentEditable");
Object {value: "", writable: true, enumerable: true, configurable: true}
Chrome 43 ขึ้นไปจะแสดงผลเป็น undefined
ในสถานการณ์นี้
> Object.getOwnPropertyDescriptor(div, "isContentEditable");
undefined
ซึ่งหมายความว่าตอนนี้หากต้องการรับตัวบ่งชี้พร็อพเพอร์ตี้สำหรับพร็อพเพอร์ตี้ isContentEditable
คุณจะต้องทําตามเชนโปรโตไทป์ดังนี้
> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");
Object {get: function, set: function, enumerable: false, configurable: false}
JSON.stringify จะไม่แปลงแอตทริบิวต์ DOM เป็นรูปแบบอนุกรมอีกต่อไป
JSON.stringify
จะไม่จัดรูปแบบพร็อพเพอร์ตี้ DOM ที่อยู่ในโปรโตไทป์ ตัวอย่างเช่น การดำเนินการนี้อาจส่งผลต่อเว็บไซต์หากคุณพยายามจัดรูปแบบออบเจ็กต์ เช่น PushSubscription ของ Push Notification
สำหรับ Chrome 42 และเวอร์ชันก่อนหน้า คุณจะดำเนินการต่อไปนี้ได้
> JSON.stringify(subscription);
{
"endpoint": "https://something",
"subscriptionId": "SomeID"
}
Chrome 43 ขึ้นไปจะไม่จัดรูปแบบพร็อพเพอร์ตี้ที่กําหนดไว้ในโปรโตไทป์ และระบบจะแสดงผลออบเจ็กต์ว่าง
> JSON.stringify(subscription);
{}
คุณจะต้องระบุวิธีการจัดรูปแบบของคุณเอง เช่น คุณอาจทําดังนี้
function stringifyDOMObject(object)
{
function deepCopy(src) {
if (typeof src != "object")
return src;
var dst = Array.isArray(src) ? [] : {};
for (var property in src) {
dst[property] = deepCopy(src[property]);
}
return dst;
}
return JSON.stringify(deepCopy(object));
}
var s = stringifyDOMObject(domObject);
การเขียนไปยังพร็อพเพอร์ตี้ที่อ่านอย่างเดียวในโหมดที่เข้มงวดจะแสดงข้อผิดพลาด
การเขียนลงในพร็อพเพอร์ตี้ที่อ่านอย่างเดียวควรทำให้เกิดข้อยกเว้นเมื่อคุณใช้โหมดที่เข้มงวด ตัวอย่างเช่น โปรดดูตัวอย่างต่อไปนี้
function foo() {
"use strict";
var d = document.createElement("div");
console.log(d.isContentEditable);
d.isContentEditable = 1;
console.log(d.isContentEditable);
}
ใน Chrome 42 และเวอร์ชันก่อนหน้า ฟังก์ชันจะยังคงทำงานต่อไปโดยไม่มีการแจ้งเตือน แม้ว่า isContentEditable
จะไม่มีการเปลี่ยนแปลงก็ตาม
// Chrome 42 and earlier behavior
> foo();
false // isContentEditable
false // isContentEditable (after writing to read-only property)
ใน Chrome 43 ขึ้นไป ระบบจะแสดงข้อยกเว้น
// Chrome 43 and onwards behavior
> foo();
false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter
ฉันพบปัญหา ฉันควรทำอย่างไร
โปรดทำตามคำแนะนำ หรือแสดงความคิดเห็นด้านล่างเพื่อพูดคุยกัน
ฉันเห็นเว็บไซต์ที่มีปัญหา ฉันควรทำอย่างไร
เป็นคำถามที่ดีนะ ปัญหาส่วนใหญ่เกี่ยวกับเว็บไซต์จะขึ้นอยู่กับข้อเท็จจริงที่ว่าเว็บไซต์เลือกที่จะทำการตรวจหาการแสดงผลแอตทริบิวต์ด้วยวิธีการ getOwnProperty
ซึ่งส่วนใหญ่เกิดขึ้นเมื่อเจ้าของเว็บไซต์กําหนดเป้าหมายเป็นเบราว์เซอร์ WebKit รุ่นเก่าเท่านั้น สิ่งที่นักพัฒนาแอปทำได้มีดังนี้
- รายงานปัญหาเกี่ยวกับเว็บไซต์ที่ได้รับผลกระทบในเครื่องมือติดตามปัญหา (ของ Chrome)
- รายงานปัญหาใน WebKit Radar และอ้างอิง https://bugs.webkit.org/show_bug.cgi?id=49739
โดยทั่วไปแล้วฉันสนใจที่จะทำตามการเปลี่ยนแปลงนี้
- ข้อบกพร่องเดิมจากปี 2010: https://bugs.chromium.org/p/chromium/issues/detail?id=43394 - หมายเหตุ: มีการทํางานส่วนใหญ่แล้ว
- การตรวจสอบโค้ดสำหรับคอมมิต