DOM-Attribute jetzt in der Prototypkette

Das Chrome-Team hat vor Kurzem bekannt gegeben, dass wir DOM-Eigenschaften in die Prototypenkette verschieben. Diese Änderung, die in Chrome 43 (Beta seit Mitte April 2015) implementiert wurde, bringt Chrome mehr an die Web-IDL-Spezifikation und die Implementierungen anderer Browser wie IE und Firefox. Bearbeitung: Klarstellung Ältere WebKit-basierte Browser sind derzeit nicht mit der Spezifikation kompatibel, Safari jetzt jedoch schon.

Das neue Verhalten ist in vielerlei Hinsicht positiv. Die DSGVO hat folgenden Zweck:

  • Verbessert die Kompatibilität im Web (in IE und Firefox ist dies bereits möglich) durch Einhaltung der Spezifikation.
  • Ermöglicht das konsistente und effiziente Erstellen von Getter/Setter für jedes DOM-Objekt.
  • Erhöht die Hackbarkeit der DOM-Programmierung. Sie können beispielsweise Polyfills implementieren, mit denen Sie Funktionen, die in einigen Browsern und JavaScript-Bibliotheken, die das standardmäßige DOM-Attribut-Verhalten überschreiben, effizient emulieren können.

Eine hypothetische W3C-Spezifikation enthält beispielsweise einige neue Funktionen mit dem Namen isSuperContentEditable, die vom Chrome-Browser nicht implementiert werden. Es ist jedoch möglich, die Funktion mit einer Bibliothek zu „polyfill“ oder zu emulieren. Als Bibliotheksentwickler sollten Sie prototype wie folgt verwenden, um ein effizientes Polyfill zu erstellen:

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

Bisher mussten Sie aus Gründen der Konsistenz mit anderen DOM-Eigenschaften in Chrome die neue Eigenschaft auf jeder Instanz erstellen, was für jedes HTMLDivElement-Element auf der Seite sehr ineffizient wäre.

Diese Änderungen sind wichtig für die Einheitlichkeit, Leistung und Standardisierung der Webplattform, können aber für Entwickler Probleme verursachen. Wenn Sie sich aufgrund der älteren Kompatibilität zwischen Chrome und WebKit auf dieses Verhalten verlassen haben, sollten Sie Ihre Website überprüfen und sich die Zusammenfassung der Änderungen unten ansehen.

Zusammenfassung der Änderungen

Bei Verwendung von hasOwnProperty für eine DOM-Objektinstanz wird jetzt false zurückgegeben.

Manchmal verwenden Entwickler hasOwnProperty, um zu prüfen, ob eine Eigenschaft in einem Objekt vorhanden ist. Dies funktioniert nicht mehr wie gemäß den Spezifikationen, da DOM-Attribute jetzt Teil der Prototypkette sind und hasOwnProperty nur die aktuellen Objekte überprüft, um zu sehen, ob sie darin definiert sind.

Vor einschließlich Chrome 42 wird true zurückgegeben.

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

true

Ab Chrome 43 wird false zurückgegeben.

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

false

Wenn Sie also prüfen möchten, ob isContentEditable für das Element verfügbar ist, müssen Sie den Prototyp im HTMLElement-Objekt prüfen. HTMLDivElement übernimmt beispielsweise die Property HTMLElement, wodurch die Eigenschaft isContentEditable definiert wird.

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

true

Sie sind nicht an die Nutzung von hasOwnProperty gebunden. Wir empfehlen die Verwendung des viel einfacheren Operanden in, da dadurch die Eigenschaften in der gesamten Prototypkette geprüft werden.

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

„Object.getOwnPropertyDescriptor“ der DOM-Objektinstanz gibt keinen Eigenschaftsdeskriptor für Attribute mehr zurück

Wenn Ihre Website den Eigenschaftsdeskriptor für ein Attribut eines DOM-Objekts abrufen muss, müssen Sie nun der Prototypkette folgen.

So rufen Sie die Beschreibung der Eigenschaften in Chrome 42 und früheren Versionen ab:

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

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

Ab Chrome 43 wird in diesem Szenario undefined zurückgegeben.

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

undefined

Um nun den Attributdeskriptor für das Attribut isContentEditable abzurufen, müssen Sie der Prototypkette folgen:

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

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

„JSON.stringify“ serialisiert keine DOM-Attribute mehr

JSON.stringify serialisiert keine DOM-Eigenschaften, die sich im Prototyp befinden. Dies kann sich beispielsweise auf Ihre Website auswirken, wenn Sie versuchen, ein Objekt wie PushSubscription von Push-Benachrichtigungen zu serialisieren.

Mit Chrome 42 und früheren Versionen hätte Folgendes funktioniert:

> JSON.stringify(subscription);

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

Ab Chrome 43 werden die Eigenschaften, die im Prototyp definiert sind, nicht serialisiert und Sie erhalten ein leeres Objekt.

> JSON.stringify(subscription);

{}

Sie müssen Ihre eigene Serialisierungsmethode angeben, zum Beispiel so:

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

Beim Schreiben in schreibgeschützte Attribute im strikten Modus wird ein Fehler ausgegeben

Beim Schreiben in schreibgeschützte Attribute sollte eine Ausnahme ausgelöst werden, wenn Sie den strikten Modus verwenden. Nehmen wir zum Beispiel Folgendes:

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

In Chrome 42 und früheren Versionen wurde die Funktion fortgesetzt und ohne Rückmeldung weiter ausgeführt, auch wenn isContentEditable nicht geändert worden wäre.

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

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

Ab Chrome 43 wird jetzt eine Ausnahme ausgelöst.

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

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

Ich habe ein Problem. Was soll ich tun?

Folgen Sie der Anleitung oder hinterlassen Sie einen Kommentar unten, damit wir uns darüber unterhalten können.

Ich habe eine Website mit einem Problem gefunden. Was soll ich tun?

Gute Frage. Die meisten Probleme mit Websites beruhen darauf, dass eine Website die Attribut-Präsenzerkennung mit der getOwnProperty-Methode aktiviert hat. Dies geschieht meistens, wenn ein Websiteinhaber nur ältere WebKit-Browser ausgewählt hat. Entwickler haben verschiedene Möglichkeiten:

  • Melden Sie Probleme mit der betroffenen Website über unseren Issue Tracker für Chrome.
  • Melden Sie ein Problem zu WebKit-Radar und verweisen Sie auf https://bugs.webkit.org/show_bug.cgi?id=49739.

Ich bin im Allgemeinen daran interessiert, dieser Änderung zu folgen.