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

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

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