מאפייני DOM נמצאים עכשיו בשרשרת אב הטיפוס

צוות Chrome הודיע לאחרונה שאנחנו מעבירים את מאפייני ה-DOM לשרשרת האבות הטיפוסים. השינוי הזה, שהוטמע ב-Chrome 43 (גרסת בטא החל מאמצע אפריל 2015), מביא את Chrome לקו אחד עם מפרט Web IDL והטמעות של דפדפנים אחרים, כמו IE ו-Firefox. עריכה: הבהרה   דפדפנים ישנים יותר שמבוססים על WebKit לא תואמים כרגע למפרט, אבל דפדפן Safari כן תואם.

ההתנהגות החדשה חיובית במובנים רבים. התיוג האוטומטי:

  • שיפור התאימות באינטרנט (דפדפני IE ו-Firefox כבר עושים זאת) באמצעות תאימות למפרט.
  • מאפשרת ליצור באופן עקבי ויעיל פונקציות getter/setter בכל אובייקט DOM.
  • מגדילה את האפשרות לפרוץ לתכנות DOM. לדוגמה, תוכלו להטמיע רכיבי Polyfill שמאפשרים לדמות ביעילות פונקציונליות חסרה בדפדפנים מסוימים ובספריות JavaScript שמבטלות את התנהגויות ברירת המחדל של מאפייני DOM.

לדוגמה, מפרט היפותטי של W3C כולל פונקציונליות חדשה בשם isSuperContentEditable, ודפדפן Chrome לא מטמיע אותה, אבל אפשר לבצע 'פוליפילינג' או לדמות את התכונה באמצעות ספרייה. כמפתחי הספרייה, אתם רוצים להשתמש ב-prototype באופן הבא כדי ליצור polyfill יעיל:

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

לפני השינוי הזה – כדי לשמור על עקביות עם מאפייני DOM אחרים ב-Chrome – היה צריך ליצור את הנכס החדש בכל מכונה, וזה היה לא יעיל במיוחד לכל HTMLDivElement בדף.

השינויים האלה חשובים ליציבות, לביצועים ולסטנדרטיזציה של פלטפורמת האינטרנט, אבל הם עלולים לגרום לבעיות מסוימות למפתחים. אם הסתמכתם על ההתנהגות הזו בגלל תאימות מדור קודם בין Chrome ל-WebKit, מומלץ לבדוק את האתר שלכם ולעיין בסיכום השינויים שבהמשך.

סיכום השינויים

שימוש ב-hasOwnProperty במופע של אובייקט DOM יחזיר עכשיו את false

לפעמים מפתחים משתמשים ב-hasOwnProperty כדי לבדוק אם נכס מסוים קיים באובייקט. הקוד הזה לא יפעל יותר בהתאם למפרט כי מאפייני DOM הם עכשיו חלק משרשור האבות הטיפוס, ו-hasOwnProperty בודק רק את האובייקטים הנוכחיים כדי לראות אם הוא מוגדר בהם.

לפני Chrome 42, כולל Chrome 42, הפונקציה הזו הייתה מחזירה את הערך true.

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

true

בגרסה 43 ואילך, הפונקציה תחזיר את הערך false.

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

false

כלומר, עכשיו אם רוצים לבדוק אם isContentEditable זמין ברכיב, צריך לבדוק את אב הטיפוס באובייקט HTMLElement. לדוגמה, HTMLDivElement יורש מ-HTMLElement שמגדיר את המאפיין isContentEditable.

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

true

אין לכם התחייבות לשימוש ב-hasOwnProperty. מומלץ להשתמש באופרטור הפשוט הרבה יותר in, כי הוא יבדוק את הנכס בכל שרשרת האב טיפוס.

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

Object.getOwnPropertyDescriptor ב-DOM Object Instance לא יחזיר יותר מאפיין מתאר למאפיינים

אם באתר שלכם צריך לקבל את מתאר המאפיין של מאפיין באובייקט DOM, עכשיו תצטרכו לפעול לפי שרשרת האב טיפוס.

כדי לקבל את תיאור הנכס ב-Chrome 42 ובגרסאות קודמות, הייתם צריכים לבצע את הפעולות הבאות:

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

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

בגרסה 43 ואילך של Chrome, המערכת תחזיר את הערך undefined בתרחיש הזה.

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

undefined

כלומר, כדי לקבל עכשיו את מתאר המאפיין של המאפיין isContentEditable, צריך לפעול לפי שרשרת האב טיפוס באופן הבא:

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

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

JSON.stringify לא יבצע יותר סריאליזציה של מאפייני DOM

JSON.stringify לא מבצע סריאליזציה של מאפייני DOM שנמצאים באב טיפוס. לדוגמה, זה יכול להשפיע על האתר שלכם אם אתם מנסים לבצע סריאליזציה של אובייקט כמו PushSubscription של התראות דחיפה.

ב-Chrome 42 ובגרסאות קודמות, האפשרויות הבאות היו פועלות:

> JSON.stringify(subscription);

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

החל מגרסה 43 של Chrome, לא תתבצע סריאליזציה של המאפיינים שמוגדרים באב טיפוס, ויוחזר אובייקט ריק.

> JSON.stringify(subscription);

{}

תצטרכו לספק שיטת סריאליזציה משלכם. לדוגמה, תוכלו לבצע את הפעולות הבאות:

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

כתיבת בנכסים לקריאה בלבד במצב קפדני תגרום להצגת שגיאה

כשיוצרים כתיבה במאפיינים לקריאה בלבד, אמורה להופיע חריגה כשמשתמשים במצב קפדני. לדוגמה:

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

ב-Chrome 42 ובגרסאות קודמות, הפונקציה הייתה ממשיכה לפעול בשקט, למרות ש-isContentEditable לא היה משתנה.

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

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

עכשיו, בגרסה 43 ואילך של Chrome, תופיע חריגה.

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

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

יש לי בעיה, מה עליי לעשות?

אפשר לפעול לפי ההנחיות או להשאיר תגובה למטה ונדבר.

ראיתי אתר עם בעיה, מה עליי לעשות?

שאלה מצוינת. רוב הבעיות באתרים נובעות מהעובדה שבעלי האתר בחרו לבצע זיהוי נוכחות של מאפיין באמצעות השיטה getOwnProperty. בדרך כלל, הבעיה הזו מתרחשת כשבעלי האתר מטרגטים רק דפדפני WebKit ישנים יותר. יש כמה דברים שמפתחים יכולים לעשות:

  • לדווח על בעיה באתר המושפע במערכת המעקב שלנו אחר בעיות (ב-Chrome)
  • דיווח על הבעיה ב-WebKit Radar והפניה אל https://bugs.webkit.org/show_bug.cgi?id=49739

אני רוצה לעקוב אחרי השינוי הזה באופן כללי