Het Chrome-team heeft onlangs aangekondigd dat we DOM-eigenschappen naar de prototypeketen verplaatsen . Deze wijziging, geïmplementeerd in Chrome 43 (bètaversie medio april 2015), brengt Chrome meer in lijn met de Web IDL-specificatie en de implementaties van andere browsers, zoals Internet Explorer en Firefox. Bewerking: verduidelijkt: oudere WebKit-gebaseerde browsers zijn momenteel niet compatibel met de specificatie, maar Safari is dat nu wel.
Het nieuwe gedrag is in veel opzichten positief. Het:
- Verbetert de compatibiliteit op het web (IE en Firefox doen dit al) door te voldoen aan de specificatie.
- Hiermee kunt u op consistente en efficiënte wijze getters/setters op elk DOM-object maken.
- Verhoogt de hackbaarheid van DOM-programmering. Het stelt u bijvoorbeeld in staat om polyfills te implementeren waarmee u efficiënt functionaliteit kunt emuleren die ontbreekt in sommige browsers en JavaScript-bibliotheken die standaard DOM-attribuutgedrag overschrijven.
Een hypothetische W3C-specificatie bevat bijvoorbeeld een nieuwe functionaliteit genaamd isSuperContentEditable
en de Chrome-browser implementeert deze niet. Het is echter wel mogelijk om de functie te "polyfillen" of te emuleren met een bibliotheek. Als bibliotheekontwikkelaar zou je het prototype
natuurlijk als volgt willen gebruiken om een efficiënte polyfill te maken:
Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
get: function() { return true; },
set: function() { /* some logic to set it up */ },
});
Vóór deze wijziging moest u - ter wille van de consistentie met andere DOM-eigenschappen in Chrome - in elk exemplaar een nieuwe eigenschap aanmaken. Dit was zeer inefficiënt voor elk HTMLDivElement
op de pagina.
Deze wijzigingen zijn belangrijk voor de consistentie, prestaties en standaardisatie van het webplatform, maar kunnen ook problemen opleveren voor ontwikkelaars. Als u op dit gedrag vertrouwde vanwege de verouderde compatibiliteit tussen Chrome en WebKit, raden we u aan uw site te controleren en het onderstaande overzicht van de wijzigingen te bekijken.
Samenvatting van wijzigingen
Het gebruik van hasOwnProperty
op een DOM-objectinstantie retourneert nu false
Soms gebruiken ontwikkelaars hasOwnProperty
om te controleren of een eigenschap aanwezig is op een object. Dit werkt niet meer volgens de specificaties , omdat DOM-attributen nu deel uitmaken van de prototypeketen en hasOwnProperty
alleen de huidige objecten inspecteert om te zien of deze erop gedefinieerd is.
Vóór en inclusief Chrome 42 zou het volgende true
retourneren.
> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");
true
Vanaf Chrome 43 wordt false
geretourneerd.
> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");
false
Dit betekent dat als u wilt controleren of isContentEditable
beschikbaar is op het element, u het prototype op het HTMLElement-object moet controleren. HTMLDivElement
erft bijvoorbeeld van HTMLElement
, dat de eigenschap isContentEditable
definieert.
> HTMLElement.prototype.hasOwnProperty("isContentEditable");
true
Je bent niet verplicht hasOwnProperty
te gebruiken. We raden aan om de veel eenvoudigere in
operand te gebruiken, omdat deze de eigenschap op de gehele prototypeketen controleert.
if("isContentEditable" in div) {
// We have support!!
}
Object.getOwnPropertyDescriptor op DOM-objectinstantie retourneert geen eigenschapsdescriptor meer voor kenmerken
Als uw site de eigenschapsdescriptor voor een kenmerk van een DOM-object nodig heeft, moet u nu de prototypeketen volgen.
Als u de beschrijving van een eigenschap in Chrome 42 en ouder wilde ophalen, had u het volgende gedaan:
> Object.getOwnPropertyDescriptor(div, "isContentEditable");
Object {value: "", writable: true, enumerable: true, configurable: true}
Chrome 43 en hoger retourneren in dit scenario undefined
.
> Object.getOwnPropertyDescriptor(div, "isContentEditable");
undefined
Om nu de eigenschapsdescriptor voor de eigenschap isContentEditable
te verkrijgen, moet u de prototypeketen als volgt volgen:
> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");
Object {get: function, set: function, enumerable: false, configurable: false}
JSON.stringify zal DOM-attributen niet langer serialiseren
JSON.stringify
serialiseert geen DOM-eigenschappen die zich op het prototype bevinden. Dit kan bijvoorbeeld van invloed zijn op uw site als u een object zoals PushSubscription van Push Notification probeert te serialiseren.
In Chrome 42 en ouder zou het volgende hebben gewerkt:
> JSON.stringify(subscription);
{
"endpoint": "https://something",
"subscriptionId": "SomeID"
}
Vanaf Chrome 43 worden de eigenschappen die in het prototype zijn gedefinieerd, niet meer geserialiseerd. U ontvangt dan een leeg object.
> JSON.stringify(subscription);
{}
U moet uw eigen serialisatiemethode opgeven. U kunt bijvoorbeeld het volgende doen:
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);
Schrijven naar alleen-lezen eigenschappen in de strikte modus zal een fout opleveren
Schrijven naar alleen-lezen eigenschappen zou een uitzondering moeten genereren wanneer u de strikte modus gebruikt. Neem bijvoorbeeld het volgende:
function foo() {
"use strict";
var d = document.createElement("div");
console.log(d.isContentEditable);
d.isContentEditable = 1;
console.log(d.isContentEditable);
}
In Chrome 42 en ouder zou de functie nog steeds actief zijn en de uitvoering ervan in stilte voortzetten, hoewel isContentEditable
niet zou zijn gewijzigd.
// Chrome 42 and earlier behavior
> foo();
false // isContentEditable
false // isContentEditable (after writing to read-only property)
Vanaf Chrome 43 wordt er een uitzondering gegenereerd.
// Chrome 43 and onwards behavior
> foo();
false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter
Ik heb een probleem, wat moet ik doen?
Volg de instructies of laat hieronder een reactie achter, dan praten we verder.
Ik heb een site gezien met een probleem, wat moet ik doen?
Goede vraag. De meeste problemen met websites worden veroorzaakt doordat een website ervoor heeft gekozen om Attribute Presence Detection uit te voeren met de getOwnProperty
-methode. Dit gebeurt meestal wanneer een website-eigenaar alleen oudere WebKit-browsers gebruikt. Een ontwikkelaar kan een aantal dingen doen:
- Meld een probleem met de getroffen site op onze (Chrome's) issue tracker
- Meld een probleem op de WebKit-radar en verwijs naar https://bugs.webkit.org/show_bug.cgi?id=49739
Ik ben over het algemeen geïnteresseerd in het volgen van deze verandering
- Oorspronkelijke bug uit 2010: https://bugs.chromium.org/p/chromium/issues/detail?id=43394 - opmerking: bevat het meeste werk.
- Codebeoordeling voor commit