เมื่อเร็วๆ นี้ ทีม Chrome ได้ประกาศว่าเรากำลังย้ายพร็อพเพอร์ตี้ DOM ไปยังเชนต้นแบบ การเปลี่ยนแปลงนี้ซึ่งนำมาใช้ใน Chrome 43 (รุ่นเบต้า ณ กลางเดือนเมษายน 2015) ทำให้ Chrome สอดคล้องกับข้อกำหนด Web IDL และการใช้งานเบราว์เซอร์อื่นๆ เช่น IE และ Firefox แก้ไข: อธิบาย เบราว์เซอร์ที่ใช้ WebKit รุ่นเก่าๆ ยังใช้งานไม่ได้กับข้อกำหนดเฉพาะ อย่างไรก็ตาม ตอนนี้สามารถใช้ Safari ได้แล้ว
พฤติกรรมใหม่จะเป็นไปในเชิงบวกในหลายๆ ด้าน ดังนี้
- ปรับปรุงความเข้ากันได้กับเว็บต่างๆ (ซึ่งทำได้อยู่แล้วใน IE และ Firefox) ด้วยการปฏิบัติตามข้อกำหนด
- ช่วยให้คุณสร้าง Getter/Setter ในออบเจ็กต์ DOM ทุกรายการได้อย่างมีประสิทธิภาพและมีประสิทธิภาพ
- เพิ่มความสามารถในการแฮ็กของ DOM Programming เช่น ช่วยให้ใช้ Polyfill ที่ให้คุณจำลองฟังก์ชันการทำงานที่ขาดหายไปในเบราว์เซอร์บางตัวและไลบรารี JavaScript ที่ลบล้างพฤติกรรมของแอตทริบิวต์ DOM เริ่มต้นได้อย่างมีประสิทธิภาพ
ตัวอย่างเช่น ข้อกำหนด W3C สมมติประกอบด้วยฟังก์ชันใหม่ที่เรียกว่า isSuperContentEditable
และเบราว์เซอร์ Chrome ไม่ได้ติดตั้งใช้งานดังกล่าว แต่สามารถ "polyfill" หรือจำลองฟีเจอร์นี้โดยใช้ไลบรารีได้ ในฐานะนักพัฒนาไลบรารี ปกติแล้วคุณต้องใช้ 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 Object จะส่งกลับ 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 Object ตอนนี้คุณต้องปฏิบัติตามเชนต้นแบบ
หากต้องการดูคำอธิบายพร็อพเพอร์ตี้ใน 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
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 และอ้างอิง https://bugs.webkit.org/show_bug.cgi?id=49739
โดยทั่วไปฉันสนใจที่จะติดตามการเปลี่ยนแปลงนี้
- ข้อบกพร่องเดิมจากปี 2010: https://bugs.chromium.org/p/chromium/issues/detail?id=43394 - หมายเหตุ: งานส่วนใหญ่ได้รับการแก้ไขแล้ว
- การตรวจสอบโค้ดสำหรับคอมมิต