ตอนนี้แอตทริบิวต์ DOM อยู่ในเชนต้นแบบแล้ว

เมื่อเร็วๆ นี้ ทีม 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

โดยทั่วไปแล้วฉันสนใจที่จะทำตามการเปลี่ยนแปลงนี้