Das Chrome-Team hat vor Kurzem angekündigt, dass wir DOM-Properties in die Prototyp-Kette verschieben. Diese Änderung, die in Chrome 43 (Betaversion, Stand Mitte April 2015) implementiert wurde, bringt Chrome mehr in Einklang mit der Web IDL-Spezifikation und der Implementierung anderer Browser wie IE und Firefox. Änderung: Klarstellung: Ältere WebKit-basierte Browser sind derzeit nicht mit der Spezifikation kompatibel, Safari ist es aber.
Das neue Verhalten hat viele Vorteile. Die DSGVO hat folgenden Zweck:
- Verbesserte Kompatibilität im Web (IE und Firefox bieten dies bereits) durch Einhaltung der Spezifikation.
- Ermöglicht es, für jedes DOM-Objekt einheitlich und effizient Getter/Setter zu erstellen.
- Erhöht die Hackbarkeit der DOM-Programmierung. So können Sie beispielsweise Polyfills implementieren, mit denen Sie Funktionen, die in einigen Browsern fehlen, effizient emulieren, und JavaScript-Bibliotheken, die das Standardverhalten von DOM-Attributen überschreiben.
Angenommen, eine hypothetische W3C-Spezifikation enthält eine neue Funktion namens isSuperContentEditable
, die im Chrome-Browser nicht implementiert ist. Es ist jedoch möglich, die Funktion mit einer Bibliothek zu „polyfillen“ oder zu emulieren. Als Bibliotheksentwickler möchten Sie natürlich die prototype
so verwenden, um eine effiziente polyfill zu erstellen:
Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
get: function() { return true; },
set: function() { /* some logic to set it up */ },
});
Vor dieser Änderung mussten Sie die neue Property aus Gründen der Konsistenz mit anderen DOM-Properties in Chrome in jeder Instanz erstellen. Das wäre für jede HTMLDivElement
auf der Seite sehr ineffizient gewesen.
Diese Änderungen sind wichtig für Konsistenz, Leistung und Standardisierung der Webplattform, können aber einige Probleme für Entwickler verursachen. Wenn Sie sich auf dieses Verhalten verlassen haben, weil Chrome und WebKit bisher kompatibel waren, sollten Sie Ihre Website prüfen und sich die Zusammenfassung der Änderungen unten ansehen.
Zusammenfassung der Änderungen
Wenn hasOwnProperty
auf eine DOM-Objektinstanz angewendet wird, wird jetzt false
zurückgegeben.
Manchmal verwenden Entwickler hasOwnProperty
, um zu prüfen, ob eine Property bei einem Objekt vorhanden ist. Das funktioniert nicht mehr gemäß der Spezifikation, da DOM-Attribute jetzt Teil der Prototypkette sind und hasOwnProperty
nur die aktuellen Objekte prüft, um festzustellen, ob das Attribut dort definiert ist.
In Chrome 42 und niedriger wurde für die folgende Anfrage 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. Beispiel: HTMLDivElement
wird von HTMLElement
abgeleitet, das das Attribut isContentEditable
definiert.
> HTMLElement.prototype.hasOwnProperty("isContentEditable");
true
Sie sind nicht verpflichtet, hasOwnProperty
zu verwenden. Wir empfehlen, den viel einfacheren Operanden in
zu verwenden, da damit die Property in der gesamten Prototyp-Kette geprüft wird.
if("isContentEditable" in div) {
// We have support!!
}
Object.getOwnPropertyDescriptor für DOM-Objektinstanz gibt keinen Property-Descriptor für Attribute mehr zurück
Wenn Ihre Website den Property-Descriptor für ein Attribut eines DOM-Objekts abrufen muss, müssen Sie jetzt der Prototyp-Kette folgen.
So haben Sie in Chrome 42 und niedriger die Property-Beschreibung abgerufen:
> 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
Wenn Sie also den Property-Descriptor für die Property isContentEditable
abrufen möchten, müssen Sie die Prototyp-Kette so durchlaufen:
> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");
Object {get: function, set: function, enumerable: false, configurable: false}
DOM-Attribute werden nicht mehr von JSON.stringify serialisiert
JSON.stringify
serialisiert keine DOM-Attribute, die sich im Prototyp befinden. Das kann sich beispielsweise auf Ihre Website auswirken, wenn Sie versuchen, ein Objekt wie die PushSubscription von Push-Benachrichtigungen zu serialisieren.
In Chrome 42 und niedriger funktionierte Folgendes:
> JSON.stringify(subscription);
{
"endpoint": "https://something",
"subscriptionId": "SomeID"
}
Ab Chrome 43 werden die im Prototyp definierten Eigenschaften nicht mehr serialisiert und es wird ein leeres Objekt zurückgegeben.
> JSON.stringify(subscription);
{}
Sie müssen Ihre eigene Serializationsmethode bereitstellen. Sie können beispielsweise Folgendes tun:
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);
Wenn im strengen Modus in read-only-Properties geschrieben wird, wird ein Fehler ausgegeben.
Wenn Sie im strengen Modus schreibgeschützte Properties schreiben, sollte eine Ausnahme ausgelöst werden. Beispiel:
function foo() {
"use strict";
var d = document.createElement("div");
console.log(d.isContentEditable);
d.isContentEditable = 1;
console.log(d.isContentEditable);
}
In Chrome 42 und niedrigeren Versionen würde die Funktion fortgesetzt und im Hintergrund ausgeführt, auch wenn isContentEditable
nicht geändert wurde.
// Chrome 42 and earlier behavior
> foo();
false // isContentEditable
false // isContentEditable (after writing to read-only property)
In Chrome 43 und höher wird nun 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?
Folge der Anleitung oder hinterlasse unten einen Kommentar.
Ich habe eine Website mit einem Problem gefunden. Was soll ich tun?
Gute Frage. Die meisten Probleme mit Websites sind darauf zurückzuführen, dass die Erkennung der Attributenpräsenz mit der Methode getOwnProperty
ausgewählt wurde. Dies geschieht in der Regel, wenn ein Websiteinhaber nur ältere WebKit-Browser anvisiert hat. Entwickler haben dabei verschiedene Möglichkeiten:
- Melden Sie das Problem mit der betroffenen Website in unserem Chrome-Problem-Tracker.
- Melden Sie ein Problem im WebKit-Radar und verweisen Sie auf https://bugs.webkit.org/show_bug.cgi?id=49739.
Ich bin grundsätzlich an dieser Änderung interessiert.
- Ursprünglicher Fehler aus dem Jahr 2010: https://bugs.chromium.org/p/chromium/issues/detail?id=43394 – Hinweis: Der Großteil der Arbeit wurde bereits erledigt.
- Codeüberprüfung für Commit