ניתן להתייחס למזהי אלמנטים בעלי שם כ-JavaScript Globals PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

ניתן להתייחס למזהי אלמנטים בעלי שם כ-Global JavaScript

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

אם זו הפעם הראשונה שאתה שומע על זה, תתאמן! אנו יכולים לראות את זה בפעולה פשוט על ידי הוספת מזהה לרכיב ב-HTML:

בדרך כלל, היינו מגדירים משתנה חדש באמצעות querySelector("#cool") or getElementById("cool") כדי לבחור את האלמנט הזה:

var el = querySelector("#cool");

אבל למעשה כבר יש לנו גישה אליו #cool בלי הטיגמורל הזה:

אז, כל id - או name תכונה, לצורך העניין - ב-HTML ניתן לגשת ל-JavaScript באמצעות window[ELEMENT_ID]. שוב, זה לא בדיוק "חדש" אבל זה ממש נדיר לראות.

כפי שאתה יכול לנחש, גישה להיקף הגלובלי עם הפניות בשמות אינו הרעיון הגדול ביותר. יש אנשים שבאו לקרוא לזה "המזהם בהיקף הגלובלי". ניכנס למה זה, אבל קודם...

קצת הקשר

גישה זו היא מתואר במפרט HTML, שם זה מתואר כ"גישה בשם ב- Window לְהִתְנַגֵד."

Internet Explorer היה הראשון שהטמיע את התכונה. כל שאר הדפדפנים הוסיפו אותו גם כן. Gecko היה הדפדפן היחיד באותה תקופה שלא תמך בו ישירות במצב סטנדרטים, ובמקום זאת בחר להפוך אותו לתכונה ניסיונית. היה היסוס ליישם את זה בכלל, אבל זה התקדם בשם תאימות הדפדפן (שממית אפילו ניסתה לשכנע את WebKit כדי להעביר אותו ממצב סטנדרטים) ובסופו של דבר עבר למצב סטנדרטים בפיירפוקס 14.

דבר אחד שאולי לא ידוע היטב הוא שדפדפנים היו צריכים להפעיל כמה אמצעי זהירות - בדרגות שונות של הצלחה - כדי להבטיח שגלובליות שנוצרו לא ישברו את דף האינטרנט. אמצעי אחד כזה הוא…

הצללה משתנה

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


  
    window.foo = "bar";
  


  
I won't override window.foo
console.log(window.foo); // Prints "bar"

וגם ההפך הוא הנכון:

I will be overridden :(
window.foo = "bar"; console.log(window.foo); // Prints "bar"

התנהגות זו חיונית מכיוון שהיא מבטלת עקיפות מסוכנות כגון

, שאחרת תיצור התנגשות על ידי ביטול התוקף של alert ממשק API. טכניקת ההגנה הזו עשויה מאוד להיות הסיבה לכך שאתה - אם אתה כמוני - לומד על זה בפעם הראשונה.

התיק נגד גלובלים בעלי שם

קודם לכן, אמרתי ששימוש באלמנטים בעלי שם גלובלי בתור הפניות אולי לא יהיה הרעיון הכי טוב. יש הרבה סיבות לכך, אשר TJ VanToll סיקר יפה בבלוג שלו ואני אסכם כאן:

  • אם ה-DOM משתנה, אז גם ההפניה משתנה. זה גורם לכמה באמת "שבירים" (המונח של המפרט עבורו) קוד שבו ההפרדה בין החששות בין HTML ל-JavaScript עשויה להיות גדולה מדי.
  • הפניות מקריות הן קלות מדי. שגיאת הקלדה פשוטה עשויה להסתיים בהתייחסות לגלובלי בעל שם ולתת לך תוצאות בלתי צפויות.
  • זה מיושם אחרת בדפדפנים. לדוגמה, אנחנו אמורים להיות מסוגלים לגשת לעוגן עם id - למשל - אבל כמה דפדפנים (כלומר Safari ו-Firefox) מחזירים א ReferenceError בקונסולה.
  • אולי זה לא יחזיר את מה שאתה חושב. לפי המפרט, כאשר ישנם מספר מופעים של אותו אלמנט בעל שם ב-DOM - נניח, שני מופעים של

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

  • אולי יש עלות ביצוע? כלומר, הדפדפן חייב להכין את רשימת ההפניות הזו ולתחזק אותה. כמה אנשים ערכו בדיקות בשרשור StackOverflow זה, שם היו למעשה גלובלים יותר ביצועים במבחן אחד ו פחות ביצועים בבדיקה עדכנית יותר.

שיקולים נוספים

נניח שאנו זורקים את הביקורות נגד השימוש בגלובלים בעלי שם ונשתמש בהם בכל מקרה. הכל טוב. אבל יש כמה דברים שאולי תרצה לקחת בחשבון בזמן שאתה עושה.

פיליפס

עד כמה שזה יישמע, סוגים אלה של בדיקות גלובליות הן דרישת הגדרה אופיינית לפולימילוי. בדוק את הדוגמה הבאה שבה אנו מגדירים קובץ Cookie באמצעות החדש CookieStore API, מילוי זה בדפדפנים שעדיין אינם תומכים בו:


  
  
    // Polyfill the CookieStore API if not yet implemented.
    // https://developer.mozilla.org/en-US/docs/Web/API/CookieStore
    if (!window.cookieStore) {
      window.cookieStore = myCookieStorePolyfill;
    }
    cookieStore.set("foo", "bar");
  

הקוד הזה עובד מצוין ב-Chrome, אבל זורק את השגיאה הבאה ב-Safari.

TypeError: cookieStore.set is not a function

לספארי אין תמיכה עבור CookieStore API נכון לכתיבת שורות אלה. כתוצאה מכך, הפוליפיל אינו מוחל בגלל ה img מזהה אלמנט יוצר משתנה גלובלי שמתנגש עם ה- cookieStore גלובלי

עדכוני JavaScript API

אנו יכולים להפוך את המצב ולמצוא בעיה נוספת שבה עדכונים למנוע ה-JavaScript של הדפדפן יכולים לשבור את ההפניות הגלובליות של רכיב בעל שם.

לדוגמה:


  
  
    window.BarcodeDetector.focus();
  

הסקריפט הזה תופס הפניה לרכיב הקלט ומפעיל focus() על זה. זה עובד כמו שצריך. ובכל זאת, אנחנו לא יודעים איך ארוך זה ימשיך לעבוד.

אתה מבין, המשתנה הגלובלי שבו אנו משתמשים כדי להתייחס לרכיב הקלט יפסיק לפעול ברגע שהדפדפנים יתחילו לתמוך ב- BarcodeDetector API. בשלב זה, ה window.BarcodeDetector global לא יהווה עוד התייחסות לרכיב הקלט ו .focus() יזרוק "window.BarcodeDetector.focus אינו פונקציה" שגיאה.

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

רוצים לשמוע משהו מצחיק? כדי להוסיף עלבון לפציעה, אלמנטים בעלי שם נגישים כמשתנים גלובליים רק אם השמות אינם מכילים אלא אותיות. דפדפנים לא ייצרו הפניה גלובלית לרכיב עם מזהה שמכיל תווים ומספרים מיוחדים, כמו hello-world ו item1.

סיכום

בואו נסכם איך הגענו לכאן:

  • כל הדפדפנים הגדולים יוצרים באופן אוטומטי הפניות גלובליות לכל רכיב DOM עם id (או, במקרים מסוימים, א name תְכוּנָה).
  • גישה לאלמנטים אלה באמצעות הפניות גלובליות שלהם אינה אמינה ועלולה להיות מסוכנת. להשתמש querySelector or getElementById במקום.
  • מכיוון שהפניות גלובליות נוצרות אוטומטית, עשויות להיות להן כמה תופעות לוואי על הקוד שלך. זו סיבה טובה להימנע משימוש ב id תכונה אלא אם כן אתה באמת צריך את זה.

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

ככלל, הסתמכות על זה תוביל לקוד שביר. אילו מזהים בסופו של דבר מיפויים ל-API זה יכולים להשתנות לאורך זמן, מכיוון שתכונות חדשות מתווספות לפלטפורמת האינטרנט, למשל. במקום זה, השתמש document.getElementById() or document.querySelector().

אני חושב שהעובדה שמפרט ה-HTML עצמו ממליץ להתרחק מהפיצ'ר הזה מדבר בעד עצמו.

בול זמן:

עוד מ טריקים של CSS