DOM Özellikleri artık prototip zincirinde

Chrome ekibi kısa süre önce DOM özelliklerini prototip zincirine taşıdığımızı duyurdu. Chrome 43'te (Nisan 2015'in ortası itibarıyla Beta) uygulanan bu değişiklik, Chrome'un Web IDL Özellikleri'nin yanı sıra IE ve Firefox gibi diğer tarayıcıların uygulamalarıyla daha uyumlu hale gelmesini sağlamaktadır. Düzenleme: netleştirildi Eski WebKit tabanlı tarayıcılar şu anda bu özellikle uyumlu değildir, ancak Safari şu anda uyumludur.

Bu yeni davranış birçok açıdan olumlu. Otomatik etiketleme:

  • Özelliklere uyum sağlayarak web genelinde uyumluluğu artırır (IE ve Firefox bunu zaten yapar).
  • Her DOM Nesnesi için tutarlı ve verimli bir şekilde alıcı/belirleyici oluşturmanızı sağlar.
  • DOM programlamasının saldırıya uğrama ihtimalini artırır. Örneğin, varsayılan DOM özelliği davranışlarını geçersiz kılan bazı tarayıcılarda ve JavaScript kitaplıklarında eksik olan işlevleri verimli bir şekilde emüle etmenizi sağlayan çoklu dolgular uygulayabilmenizi sağlar.

Örneğin, varsayıma dayalı bir W3C spesifikasyonu, isSuperContentEditable adlı bazı yeni işlevler içerir ve Chrome Tarayıcı bu özellikleri uygulamaz, ancak özelliği bir kitaplıkla "çoklu doldurma" veya emülasyonla kullanmak mümkündür. Kitaplık geliştiricisi olarak, verimli bir çoklu dolgu oluşturmak için aşağıdaki gibi prototype kullanmanız gerekir:

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

Bu değişiklikten önce (Chrome'daki diğer DOM özellikleriyle tutarlılık sağlamak amacıyla), sayfadaki her HTMLDivElement için yeni özelliği her örnekte oluşturmanız gerekiyordu. Bu da sayfadaki her HTMLDivElement için çok verimsiz olurdu.

Bu değişiklikler web platformunun tutarlılığı, performansı ve standartlaştırılması açısından önemlidir ancak geliştiriciler için bazı sorunlara neden olabilir. Chrome ve WebKit arasındaki eski uyumluluk nedeniyle bu davranışa güveniyorsanız sitenizi kontrol etmenizi ve değişikliklerin özetini aşağıda incelemenizi öneririz.

Değişiklik özeti

Bir DOM Nesnesi örneğinde hasOwnProperty kullanıldığında artık false döndürülür

Bazen geliştiriciler bir nesnede özellik olup olmadığını kontrol etmek için hasOwnProperty kullanırlar. DOM özellikleri artık prototip zincirinin bir parçası olduğundan ve hasOwnProperty, mevcut nesneleri inceleyerek bunların üzerinde tanımlanıp tanımlanmadığını kontrol ettiğinden bu işlem artık spesifikasyona göre çalışmaz.

Chrome 42 sürümünden önce ve dahil edildiği sürümlerde true işlevi döndürülür.

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

true

Chrome 43'ten itibaren false değerini döndürecektir.

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

false

Bu artık öğede isContentEditable olup olmadığını kontrol etmek isterseniz prototipi HTMLElement nesnesinde kontrol etmeniz gerektiği anlamına gelir. Örneğin HTMLDivElement, isContentEditable özelliğini tanımlayan HTMLElement öğesinden devralır.

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

true

hasOwnProperty ürününü kullanmak zorunda değilsiniz. Prototip zincirinin tamamında özelliği kontrol edeceği için çok daha basit in işlenenini kullanmanızı öneririz.

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

DOM Nesne Örneğindeki Object.getOwn PropertyDescriptor, artık Özellikler için özellik tanımlayıcısı döndürmeyecek

Sitenizin, bir DOM Nesnesi'ndeki bir özelliğin özellik tanımlayıcısını alması gerekiyorsa, artık prototip zincirini izlemeniz gerekecektir.

Chrome 42 ve önceki sürümlerde özellik açıklamasını almak istediğinizde şunları yaparsınız:

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

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

Chrome 43 ve sonraki sürümler, bu senaryoda undefined değerini döndürür.

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

undefined

Bu durumda, isContentEditable özelliğinin özellik tanımlayıcısını almak için prototip zincirini aşağıdaki şekilde izlemeniz gerekir:

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

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

JSON.stringify artık DOM Özelliklerini serileştirmeyecek

JSON.stringify, prototipte bulunan DOM özelliklerini serileştirmez. Örneğin, Push Bildirimi'ndeki PushSubscription gibi bir nesneyi seri hale getirmeye çalışıyorsanız bu durum sitenizi etkileyebilir.

Chrome 42 ve önceki sürümlerde aşağıdakiler çalışır:

> JSON.stringify(subscription);

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

Chrome 43 ve sonraki sürümler, prototipte tanımlanan özellikleri seri hale getirmez ve size boş bir nesne döndürülür.

> JSON.stringify(subscription);

{}

Kendi serileştirme yönteminizi sağlamanız gerekecektir. Örneğin, aşağıdakileri yapabilirsiniz:

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

Yüksek düzey modunda salt okunur özelliklere yazmak hata verir

Yüksek düzey modu kullanırken salt okunur özelliklere yazmanın bir istisna gönderilmesi gerekir. Örneğin, aşağıdakileri ele alalım:

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

Chrome 42 ve önceki sürümlerinde işlev, isContentEditable değiştirilmese de işlevi sessiz bir şekilde yürütmeye devam ediyordu.

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

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

Şimdi Chrome 43 ve sonraki sürümlerde bir istisna olacaktır.

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

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

Sorun yaşıyorum, ne yapmalıyım?

Talimatları uygulayın veya aşağıya yorumunuzu yazın ve birlikte konuşalım.

Sorunlu bir site gördüm, ne yapmalıyım?

Harika bir soru. Sitelerle ilgili çoğu sorun, bir sitenin getOwnProperty yöntemiyle Özellik varlığı algılamayı yapmayı seçmesine dayanır. Bu, çoğunlukla bir site sahibi yalnızca eski WebKit tarayıcılarını hedeflediğinde gerçekleşir. Bir geliştiricinin yapabileceği birkaç şey vardır:

  • Etkilenen siteyle ilgili bir sorunu (Chrome) sorun izleyicimizde bildirin
  • WebKit radarında sorun bildiriminde bulunun ve https://bugs.webkit.org/show_bug.cgi?id=49739 adresine bakın.

Genel olarak bu değişikliği takip etmekle ilgileniyorum