Atribut DOM sekarang ada di rantai prototipe

Tim Chrome baru-baru ini mengumumkan bahwa kami akan memindahkan properti DOM ke rantai prototipe. Perubahan ini, yang diterapkan di Chrome 43 - (Beta per pertengahan April 2015) - membuat Chrome lebih sesuai dengan Web IDL Spec dan implementasi browser lainnya, seperti IE dan Firefox. Edit: mengklarifikasi Browser berbasis WebKit versi lama, saat ini tidak kompatibel dengan spesifikasi, namun Safari sekarang kompatibel.

Perilaku baru ini positif dalam banyak hal. Persyaratan ini:

  • Meningkatkan kompatibilitas di seluruh web (IE dan Firefox sudah melakukannya) melalui kepatuhan terhadap spesifikasi.
  • Memungkinkan Anda membuat pengambil/penyetel secara konsisten dan efisien pada setiap Objek DOM.
  • Meningkatkan kemudahan peretasan pemrograman DOM. Misalnya, Anda dapat mengimplementasikan polyfill yang memungkinkan Anda mengemulasikan fungsi yang hilang di beberapa browser dan library JavaScript secara efisien yang mengganti perilaku atribut DOM default.

Misalnya, spesifikasi W3C fiktif mencakup beberapa fungsi baru yang disebut isSuperContentEditable dan Browser Chrome tidak menerapkannya, tetapi dimungkinkan untuk "polyfill" atau mengemulasi fitur dengan library. Sebagai developer library, Anda tentu ingin menggunakan prototype sebagai berikut untuk membuat polyfill yang efisien:

Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
    get: function() { return true; },
    set: function() { /* some logic to set it up */ },
});

Sebelum perubahan ini - agar konsisten dengan properti DOM lainnya di Chrome - Anda harus membuat properti baru di setiap instance, yang untuk setiap HTMLDivElement di halaman akan sangat tidak efisien.

Perubahan ini penting untuk konsistensi, performa, dan standardisasi platform web, tetapi juga dapat menyebabkan masalah bagi developer. Jika Anda mengandalkan perilaku ini karena kompatibilitas lama antara Chrome dan WebKit, sebaiknya periksa situs Anda dan lihat ringkasan perubahan di bawah.

Ringkasan perubahan

Menggunakan hasOwnProperty pada instance Objek DOM sekarang akan menampilkan false

Terkadang developer akan menggunakan hasOwnProperty untuk memeriksa keberadaan properti pada objek. Ini tidak akan berfungsi lagi sesuai spesifikasi karena atribut DOM sekarang menjadi bagian dari rantai prototipe dan hasOwnProperty hanya memeriksa objek saat ini untuk melihat apakah objek telah didefinisikan di dalamnya.

Sebelum dan termasuk Chrome 42, hal berikut akan menampilkan true.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

true

Di Chrome 43 dan seterusnya, false akan ditampilkan.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

false

Artinya, jika ingin memeriksa apakah isContentEditable tersedia pada elemen, Anda harus memeriksa prototipe pada objek HTMLElement. Misalnya, HTMLDivElement mewarisi dari HTMLElement yang menentukan properti isContentEditable.

> HTMLElement.prototype.hasOwnProperty("isContentEditable");

true

Anda tidak terkunci untuk menggunakan hasOwnProperty. Sebaiknya gunakan operand in yang jauh lebih sederhana karena tindakan ini akan memeriksa properti di seluruh rantai prototipe.

if("isContentEditable" in div) {
    // We have support!!
}

Object.getOwnPropertyDescriptor pada Instance Objek DOM tidak akan lagi menampilkan deskriptor properti untuk Atribut

Jika situs Anda perlu mendapatkan deskriptor properti untuk atribut pada Objek DOM, Anda sekarang harus mengikuti rantai prototipe tersebut.

Jika ingin mendapatkan deskripsi properti di Chrome 42 dan versi sebelumnya, Anda perlu melakukan hal-hal berikut:

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

Object {value: "", writable: true, enumerable: true, configurable: true}

Chrome 43 dan seterusnya akan menampilkan undefined dalam skenario ini.

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

undefined

Artinya, untuk mendapatkan deskripsi properti untuk properti isContentEditable, Anda harus mengikuti rantai prototipe sebagai berikut:

> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");

Object {get: function, set: function, enumerable: false, configurable: false}

JSON.stringify tidak akan lagi membuat serialisasi Atribut DOM

JSON.stringify tidak melakukan serialisasi properti DOM yang ada di prototipe. Misalnya, hal ini dapat memengaruhi situs Anda jika Anda mencoba melakukan serialisasi objek seperti PushSubscription Notifikasi Push.

Chrome 42 dan versi sebelumnya, berikut ini akan berfungsi:

> JSON.stringify(subscription);

{
    "endpoint": "https://something",
    "subscriptionId": "SomeID"
}

Chrome 43 dan seterusnya tidak akan melakukan serialisasi properti yang ada di ditentukan di prototipe dan Anda akan dikembalikan objek kosong.

> JSON.stringify(subscription);

{}

Anda harus memberikan metode serialisasi sendiri, misalnya, Anda dapat melakukan hal berikut:

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);

Menulis ke properti hanya baca dalam mode ketat akan memunculkan error

Menulis ke properti hanya-baca seharusnya menampilkan pengecualian saat Anda menggunakan mode ketat. Misalnya, perhatikan hal berikut:

function foo() {
    "use strict";
    var d = document.createElement("div");
    console.log(d.isContentEditable);
    d.isContentEditable = 1;
    console.log(d.isContentEditable);
}

Chrome 42 dan yang lebih lama, fungsi tersebut akan terus berjalan, dan secara diam-diam menjalankan fungsi, meskipun isContentEditable tidak akan diubah.

// Chrome 42 and earlier behavior
> foo();

false // isContentEditable
false // isContentEditable (after writing to read-only property)

Kini di Chrome 43 dan seterusnya akan ada pengecualian yang ditampilkan.

// Chrome 43 and onwards behavior
> foo();

false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter

Saya mengalami masalah, apa yang harus saya lakukan?

Ikuti panduannya, atau tulis komentar di bawah ini dan mari berdiskusi.

Saya melihat situs yang bermasalah, apa yang harus saya lakukan?

Pertanyaan bagus. Sebagian besar masalah pada situs akan didasarkan pada fakta yang dipilih situs untuk melakukan Deteksi kehadiran atribut dengan metode getOwnProperty. Hal ini sebagian besar dilakukan jika pemilik situs hanya menargetkan browser WebKit lama. Ada beberapa hal yang dapat dilakukan developer:

  • Laporkan masalah tentang situs yang terpengaruh di issue tracker (Chrome) kami
  • Laporkan masalah di radar WebKit dan referensikan https://bugs.webkit.org/show_bug.cgi?id=49739

Secara umum saya tertarik untuk mengikuti perubahan ini