צוות 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
אני רוצה לעקוב אחרי השינוי הזה באופן כללי
- הבאג המקורי משנת 2010: https://bugs.chromium.org/p/chromium/issues/detail?id=43394 – הערה: רוב העבודה בוצעה בו.
- בדיקת קוד לפני השמירה