[עמוד ראשי]   [נושא קודם]
JavaScript בדפדפני רשת


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

היררכית האובייקטים של צד הלקוח.

המודל : event-driven programming

ה-Window כהקשר הביצוע הגלובלי

המטלה העיקרית של דפדפן רשת היא להציג מסמכי HTML בחלון. בצד הלקוח של JS, האובייקט Document מייצג מסמך HTML, והאובייקט Window מייצג את החלון (או המסגרת) אשר מציג את המסמך. בעוד שהאובייקטים Window ו- Document חשובים לצד הלקוח של ב-JS, האובייקט Window חשוב יותר, וזאת מסיבה אחת עיקרית: האובייקט Window הוא האובייקט הגלובלי בתכנות צד הלקוח.

בכל יישום של JS יש תמיד אובייקט גלובלי בראש שרשרת הטווח. התכונות של אובייקט גלובלי זה הם משתנים גלובליים. בצד הלקוח של JS, האובייקט Window הוא האובייקט הגלובלי.
האובייקט Window מגדיר מספר תכונות ומתודות, אשר מאפשרות לתפעל את חלון דפדפן הרשת. הוא אף מגדיר תכונות המתייחסות לאובייקטים חשובים אחרים, כמו התכונה document עבור האובייקט Document.
האובייקט Window הוא בעל שתי תכונות עצמיות (window, (self-referential ו- self. ניתן להשתמש בכל אחד מהמשתנים הגלובליים הללו על מנת להתייחס ישירות לאובייקט Window.

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

var answer = 42;     // הגדרה ואתחול של משתנה גלובלי.                
window.answer = 42;  // .Window יצירת תכונה חדשה של האובייקט  
    
האובייקט Window מייצג חלון דפדפן רשת או מסגרת שבחלון. עבור צד הלקוח ב-JS, חלונות בשכבה הגבוהה ומסגרות זהים במהותם. מקובל לכתוב אפליקציות שמשתמשות בריבוי חלונות. כל חלון או מסגרת, המעורב באפליקציה, הם בעלי אובייקט Window ייחודי, המגדיר הקשר ביצוע ייחודי עבור קוד בצד הלקוח של JS. במילים אחרות, משתנה גלובלי, המוגדר ע"י קוד JS במסגרת אחת אינו משתנה גלובלי במסגרת אחרת. בכל אופן, המסגרת השניה יכולה לגשת למשתנה הגלובלי של המסגרת הראשונה.

היררכית האובייקטים בצד הלקוח

האובייקט Window הוא האובייקט המרכזי בצד הלקוח של JS. כל האובייקטים בצד הלקוח האחרים מקושרים לאובייקט זה. למשל, כל אובייקט Window מכיל את התכונה document שמתייחסת לאובייקט Document המשויך לחלון, ואת התכונה location אשר מתייחסת לאובייקט Location המשויך לחלון.
האובייקט Window מכיל מערך [ ]frames המתייחס לאובייקטי Window המייצגים את המסגרות של החלון המקורי. כך, document מייצג את האובייקט Document של החלון הנוכחי, ו- frames[1].document מתייחס לאובייקט Document של מסגרת הבת השניה של החלון הנוכחי.
מצביע לאובייקט דרך החלון הנוכחי או דרך אובייקטי Window אחרים יכול בעצמו להתייחס לאובייקטים אחרים. למשל, כל אובייקט Document בעל מערך [ ]forms המכיל אובייקטי Form המייצגים את כל טופסי HTML המופיעים במסמך. על מנת להתייחס לאחד מהטפסים הללו, ניתן לכתוב כך:
self.document.forms[0]
בהמשך לדוגמא זו, כל אובייקט Form הינו בעל מערך [ ]elements, המכיל אובייקטים המיצגים את האלמנטים השונים של טופס HTML (שדות קלט, כפתורים וכ"ו) המופיעים בו. במיקרים קיצוניים, ניתן לכתוב קוד המתייחס לאובייקט שבסוף שרשרת האובייקטים, עם ביטויים מורכבים כמו:
parent.frames[0].document.forms[0].elements[3].options[2].text
קיימת היררכיה של אובייקטי JS כשהאובייקט Window עומד בשורש ההיררכיה.
המודל Event-Driven Programming

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

בימנו, עם תצוגות גרפיות והתקני pointing כמו mice, הסיטואציה שונה. תוכניות הן באופן כללי אירועים מונעים (event driven). הן מגיבות לקלט משתמש אסינכרוני בצורה של קליק עכבר ו-keystrokes בדרך שתלויה במיקום של מצביע העכבר. דפדפן רשת הוא רק סביבה גרפית. מסמך HTML מכיל GUI משובץ כך שצד הלקוח של JS משתמש במודל התכנות של האירוע המונע.

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

בצד הלקוח של JS, דפדפן הרשת מודיע לתוכנית על קלט משתמש ע"י הפעלת אירועים. ישנו מספר סוגים שונים של אירועים, כמו keystroke, תנועת העכבר וכ'ו. כאשר מתרחש אירוע, דפדפן הרשת מנסה לקרוא לפונקצית event handler מתאימה על מנת להגיב לאירוע. לכן, על מנת לכתוב באופן דינמי, תוכניות JS אינטראקטיביות בצד הלקוח, יש להגדיר event handlers מתאימים ולרשום אותם עם המערכת, כך שהדפדפן יוכל לקרוא להם בזמן המתאים.

במודל הישן, נכתב בלוק בודד של קוד, שבא אחרי מספר הגדרות של בקרה ורץ בשלמות מתחילתו ועד סופו. במודל Event-Driven Programming כותבים מספר event handlers בלתי תלויים. לא קוראים ל- handlers הללו באופן ישיר, אך מתאפשר למערכת לקרוא להם בזמנים הרצויים. מאחר והם מופעלים ע"י קלט המשתמש, ה- handlers יקראו בזמנים בלתי צפויים, אסינכרוניים. ברוב הזמן התוכנית אינה רצה כלל, אלא רק מחכה למערכת שתקרא לאחד מה- event handlers.
2. שיבוץ JS ב-HTML
אם דפדפן הרשת תומך ב-JS, דרישה ברורה היא שקוד JS ישובץ במסמכים שמוצגים ע"י דפדפן הרשת. יש למעשה שבע דרכים בהן ניתן לשבץ קוד JS בתוך מסמכי HTML:

בין זוג תוויות <SCRIPT></SCRIPT>

מתוך קובץ חיצוני המוגדר ע"י התכונות SRC או ARCHIVE של התווית <SCRIPT>.

ב- event handler , מוגדר כערך של תכונת HTML כמו onClick , onMouseOver.

כגוף המשתמש בפרוטוקול המיוחד URL :java script

בתוך style sheet , בין התווית <STYLE TYPE = "text/javascript"> ו- <STYLE/>.

בישות של JS, כערך של תכונת HTML .

בהערה מותנית המכילה טקסט אשר מוציאה תוכן זה מהתוכנית, אלא אם כן ביטוי JS נתון מוערך כ- true.

א. התווית <SCRIPT>

תסריטי JS של צד הלקוח הם חלק מקובץ HTML ובדר"כ מקודדים בתוך התוויות <SCRIPT> ו- </SCRIPT>. ניתן למקם כל מספר של הצהרות JS בין תוויות אלו, אשר מבוצעות עפ"י סדר הופעתן, כחלק מתהליך טעינת המסמך. התוויות <SCRIPT> יכולות להופיע ב- <HEAD>
או ב- <BODY> של מסמך HTML.

מסמך HTML בודד יכול להכיל מספר כלשהו של זוגות התוויות <SCRIPT> ו- </SCRIPT> שאינם חופפים זה לזה. תסריטים מופרדים מתבצעים בסדר בו הם מופיעים במסמך.
בעוד שתסריטים מופרדים בקובץ בודד מתבצעים בזמנים שונים במשך הטעינה והניתוח של קובץ ה- HTML, הם יוצרים חלק של אותה תוכנית JS, פונקציות ומשתנים המוגדרים בתסריט אחד זמינים לכל התסריטים העוקבים באותו הקובץ. לדוגמא, נניח כי התסריט הבא מופיע במקום כלשהו בעמוד HTML:
<SCRIPT>var x = 1;</SCRIPT>
מאוחר יותר באותו עמוד HTML, ניתן להתייחס ל- x, למרות שהוא נמצא בבלוק תסריט אחר. ההקשר החשוב הוא עמוד ה- HTML, ולא בלוק התסריט:
<SCRIPT>document.write(x);</SCRIPT>
הדוגמא הבאה מראה קובץ HTML פשוט הכולל תוכנית JS פשוטה. דוגמא זו בניגוד לקודמותיה משולבת עם קובץ HTML ובעלת הקשר ברור למקום ריצתה.
<HTML>
  <HEAD>
    <TITLE>Today's Data</TITLE>
    <SCRIPT LANGUAGE = "JavaScript">
      function print_todays_date()
      {
        var d = new Date();
        document.write(d.toLocalestring());
      }
    </SCRIPT>
  </HEAD>
  <BODY>
    <HR>The date and time are:<BR>
    <B>
      <SCRIPT LANGUAGE = "JavaScript">
        print_todays_date();
      </SCRIPT>
    </B><HR>
  </BODY>
<HTML>
    

התכונה LANGUAGE

התווית <SCRIPT> בעלת תכונה אופציונלית LANGUAGE אשר מגדירה את שפת התסריט עבור התסריט. תכונה זו הכרחית מכיוון שיש יותר מגרסה אחת של JS ,יש יותר משפת תסריט אחת שיכולה להיות משובצת בין התווית :<SCRIPT> ו- </SCRIPT>. ע"י הגדרת השפה בה ייכתב התסריט, אומרים לדפדפן אם הוא צריך לנסות לפענח/לפרש את התסריט, או אם התסריט כתוב בשפה שהדפדפן אינו מבין, ולכן עליו להתעלם.

בכתיבת קוד JS, יש להשתמש בתכונה LANGUAGE כך:
<SCRIPT LANGUAGE = "JavaScript">
  // JS code goes here.
</SCRIPT>
    
מצד שני, בכתיבת תסריט בשפת VBScript של Microsoft, יש להשתמש בתכונה כך:
<SCRIPT LANGUAGE = "VBScript">
    VBScript code goes here (' is a comment character like' // in JavaScript)
</SCRIPT>
    
כאשר מגדירים את התכונה LANGUAGE = "JavaScript" עבור תסריט,
כל דפדפן התומך ב-JS יריץ את התסריט, בעוד שדפדפנים המבינים את התווית <SCRIPT> אבל אינם מבינים JS יתעלמו מהתסריט.
ניתן להשתמש בתכונה LANGUAGE על מנת להגדיר יותר מאשר את שפת התסריט שבשימוש, ניתן גם להגדיר את גרסת השפה.
למשל, אם מגדירים LANGUAGE = "JavaScript1.1", רק דפדפנים התומכים ב 1.1 JS ומעלה יריצו את התסריט. דפדפנים אחרים יתעלמו.

השימוש במחרוזת "JavaScript1.1" בתכונה LANGUAGE ראוי לאזכור מיוחד. כאשר 4 N הוכן לשחרור, התגלה שהופעת הסטנדרט
ECMA-262 דורשת מספר שינויים שאינם מתאימים עבור מאפיינים מסוימים של השפה.
על מנת למנוע שינויים אלו מל"שבור" תסריטים קיימים, המעצבים של JS ב- Netscape נקטו באמצעי זהירות נבון: יישום השינויים רק כאשר
"JavaScript1.2" הוגדרה במפורש בתכונה LANGUAGE. זה הבטיח שרק קוד שנכתב במפורש עבור הפלטפורמה החדשה יקבל את ההתנהגות החדשה. קוד JS שנכתב עבור דפדפנים קודמים יקבל עדיין את סגנון ההתנהגות הישנה המצופה.

למרבה הצער, הסטנדרט ECMA לא הושלם לפני ש-4 N שוחרר, ולאחר השחרור, השינויים הבלתי מתאימים שהוצעו עבור השפה הוצאו מהסטנדרט. לכן, הגדרת התכונה LANGUAGE של "JavaScript1.2" גורמת ל-4 N להתנהג בדרכים שאינן תואמות לגרסאות קודמות ואינן תואמות למפרט ECMA. מסיבה זו, רצוי להימנע מלהגדיר את הערך של התכונה LANGUAGE כ-"JavaScript1.2".

אם מתעלמים מהתכונה LANGUAGE, ברירת המחדל הן ב-N והן באינטרנט אקספלורר היא הערך " JavaScript". בכל זאת, מכיוון שכיום יש הרבה שפות תסריטים זמינות, זהו מנהג טוב להשתמש תמיד בתכונה LANGUAGE על מנת להגדיר בדיוק באיזו שפה (או גרסה) התסריט נכתב.

התווית <SCRIPT/>

אם כותבים תסריט הכותב תסריט לחלון דפדפן אחר או למסגרת, יש צורך לכתוב תווית <SCRIPT/> על מנת לסיים את התסריט שכותבים. יש להיות זהירים- מנתח תוכנית HTML אינו יודע על מחרוזות מצוטטות, לכן אם כותבים מחרוזת אשר מכילה את התווים " <SCRIPT/>", מפענח ה-HTML מסיים את התסריט הרץ הנוכחי. על מנת להימנע מבעיה זו, יש לחתוך את התווית לחתיכות ולכתוב זאת בעזרת ביטוי כמו
"</" + "SCRIPT>" :
<SCRIPT>
  f1.document.write("<SCRIPT>");
  f1.document.write("document.write("<H2>This is the quoted script</H2>')");
  f1.document.write("</" + "SCRIPT>");
</SCRIPT>
    
דרך אלטרנטיבית, ניתן "להימלט" מ-/ שב-<SCRIPT/> ע"י backslash :
f1.document.write("<\ / SCRIPT>");

ב. הכללת קבצי JS

התווית <SCRIPT> תומכת בתכונה SRC. הערך של תכונה זו מגדיר את ה-URL של קובץ בעל קוד JS. משתמשים בתכונה כך:
<SCRIPT SRC = "../../javascript/util.js"></SCRIPT>
קובץ JS הוא JS טהור, ללא התוויות <SCRIPT> או תוויות HTML אחרות. קובץ JS הוא בעל סיומת js. , וצריך להיות מיוצא ע"י שרת רשת מסוג MIME : application/x - javascript. נקודה זו היא חשובה, שרת הרשת יכול לדרוש תצורה מיוחדת על מנת להשתמש בהצלחה בקבצי JS בדרך זו.

התווית <SCRIPT> עם התכונה SRC מגדירה התנהגות זהה לזו שבה התוכן של קובץ JS מופיע ישירות בין התווית <SCRIPT> ו-
<SCRIPT/>. בקוד המופיע בין התוויות הללו מתעלמים דפדפנים התומכים בתכונה SRC. יש לשים לב, שתווית הסגירה <SCRIPT/> נדרשת גם כאשר התכונה SRC מוגדרת ואין קוד JS בין התוויות.

ישנם מספר יתרונות לשימוש בתווית SRC:
מפשט את קבצי HTML ע"י מתן האפשרות להסיר בלוקים גדולים של קוד JS מתוכם.

כאשר יש פונקציות או קוד אחר של JS המשמש מספר קבצי HTML, ניתן לשמור אותו בקובץ אחד ולקרוא אותו לתוך כל קובץ HTML הזקוק לו.
זה מפחית את ניצולת הדיסק ועושה את הקוד קל יותר לתחזוקה.

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

בגלל שהתכונה SRC לוקחת URL שרירותי, תוכנית JS או דף רשת משרת רשת אחד יכול להפעיל קוד המיוצא ע"י שרתי רשת אחרים.

התכונה ARCHIVE

ב-4 N ואינטרנט אקספלורר 4, התכונה SRC של התווית <SCRIPT> מושלמת ע"י התכונה ARCHIVE. ARCHIVE מגדירה קובץ java archive ) JAR )שמכיל מספר קבצי JAVA דחוסים (ויכול להכיל גם קבצי עזר, כמו חתימות דיגיטליות). כאשר התוכנית משתמשת במספר קבצי JS, יהיה יעיל יותר לשלב אותם לתוך קובץ JAR דחוס בודד שיכול להיטען על פני הרשת.
יש לשים לב שהתכונה ARCHIVE מגדירה רק את שם ה-archive, ולא את השם של קובץ js. אינדיבידואלי שרוצים להשתמש בו בתוכה, לכן, חייבים להשתמש בתכונה ARCHIVE עם התכונה SRC. לדוגמא:
<SCRIPT ARCHIVE = "utils.jar" SRC = "animation.js"></SCRIPT>
קובץ JAR הוא למעשה קובץ ZIP עם אינפורמציה ברורה נוספת.

ג. Event Handlers

קוד JS ב- <SCRIPT> מתבצע פעם אחת, כאשר קובץ ה- HTML שמכיל אותו נקרא לתוך דפדפן הרשת. תוכנית המשתמשת רק בסוג זה של תסריטים סטטיים אינה יכולה להגיב באופן דינמי למשתמש. יותר תוכניות דינמיות מגדירות event handlers שנקראים אוטומטית ע"י דפדפן הרשת כאשר אירוע מסוים מתרחש, למשל, כאשר המשתמש מקליק על כפתור בטופס. מכיוון שאירועים נוצרים מצד הלקוח של JS מתוך אובייקטי HTML (כמו כפתורים), event handlers מוגדרים כתכונות של אובייקטים אלו.

על מנת לאפשר להגדיר event handlers כחלק מהגדרת אובייקטי HTML, JS מרחיבה את HTML ע"י הוספת תכונות event handlers חדשות לתוויות HTML שונות. למשל, על מנת להגדיר event handler שנקרא כאשר המשתמש מקליק על checkbox בטופס, מגדירים את קוד ה-handler כתכונה של תווית HTML המגדירה אתה checkbox:
<INPUT TYPE = "checkbox" NAME = "opts" VALUE = "ignore-case" OnClick = "ignore_case = this.checked;">
מה שמעניין היא התכונה onClick. ערך המחרוזת של התכונה onClick יכול להכיל הצהרה אחת או יותר של JS. אם יש יותר מהצהרה אחת, ההצהרות חייבות להיות מופרדות אחת מהשנייה ע"י פסיקים. כאשר האירוע המוגדר- במקרה זה, קליק- מתרחש ב-checkbox, קוד ה-JS שבמחרוזת מתבצע.

בעוד שניתן לכלול מספר כלשהו של הצהרות JS בהגדרת event handler, טכניקה נפוצה כאשר הצהרה אחת או שתי הצהרות פשוטות נדרשות, היא להגדיר את הגוף של ה- event handler כפונקציה בין התוויות <SCRIPT> ו- <SCRIPT/>, ואז ניתן לקרוא בפשטות לפונקציה זו מתוך ה-event handler. כך נשמר רוב קוד JS הממשי בתסריטים ומפחית את הצורך למזג JS ו-HTML.

Event Handlers בתוויות <SCRIPT>

באינטרנט אקספלורר, אבל לא ב-N , יש תחביר אלטרנטיבי עבור הגדרת event handlers, הכרוך בשימוש בתכונות החדשות :FOR ו-EVENT לתווית <SCRIPT> על מנת להגדיר קוד שיוצר event handler עבור אובייקט בעל שם ואירוע בעל שם. ניתן לכתוב את הדוגמא הקודמת של ה- checkbox ע"י שימוש בטכניקה זו כך:
<INPUT TYPE = "checkbox" NAME = "opts" VALUE = "ignore_case">
<SCRIPT FOR = "opts" EVENT = "onClick">
  ignore_case = this.checked;
</SCRIPT>
    
יש לשים לב שהערך של התכונה FOR חייב להיות אובייקט בעל שם שהוצב ע"י התכונה NAME כשהאובייקט הוגדר. והערך של התכונה EVENT הוא השם של ה-event handler (אבל לא השם של האירוע עצמו).

ישנה דרך להגדיר event handlers בדרך זו המונעת את הצורך להוסיף תכונות JS חדשות לכל אובייקטי HTML. בכל אופן, טכניקה זו להגדרת event handlers, בדר"כ שימושית יותר למתכנתי VBScript מאשר למתכנתי JS, ומאחר ואינה נתמכת ע"י N, השימוש בה אינו מומלץ.

ד. JS ב- URLs

דרך אחרת בה קוד JS יכול להיכלל בצד השרת היא בתוך "javascript: URL" -פרוטוקול פסאודו. פרוטוקול מיוחד זה מגדיר שהגוף של ה-URL הוא קוד JS שרירותי שירוץ ע"י מפרש JS. אם קוד JS שבתוך "javascript: URL" מכיל מספר של הצהרות, ההצהרות חיבות להיות מופרדות אחת מהשניה ע"י פסיקים. URL כזה יכול להראות כך:
Javascript : var now = new Date(); "<h1>The time is:</h1>" + now;
כאשר הדפדפן טוען אחד מה-URLs הללו, הוא מפעיל את קוד JS המוכל בתוך ה-URL ומציג את המסמך שמתייחס אליו ה-URL. המחרוזת מפורמטת ומוצגת כמו מסמך אחר שנטען לדפדפן.

בדרך כלל, "javascript: URL" מכיל הצהרות JS המבצעות פעולות אך אינן מחזירות ערך. לדוגמא:
Javascript:alert("Hello World!")
כאשר סוג כזה של URL נטען, הדפדפן מפעיל את קוד JS, אך מכיוון שאין ערך המהווה את המסמך החדש להצגה, הוא אינו מעדכן את המסמך המוצג הנוכחי.

יש לשים לב שהחל מגרסא 1.1, ניתן להשתמש באופרטור void על מנת לכפות על ביטוי להיות חסר ערך. זה שימושי כאשר רוצים להפעיל משימת הצהרה, למשל, אבל לא רוצים להציג את הערך המוצב בחלון הדפדפן.

"Javascript:URL" ניתן לשימוש בכל מקום בו משתמשים ב-URL רגיל. ב-N דרך אחת חשובה להשתמש בתחביר זה, היא להציב באופן ישיר לתוך השדה Location של הדפדפן, כך הדפדפן מאפשר לבחון קוד JS שרירותי ללא הכרח לצאת מהעורך וליצור קובץ HTML המכיל את הקוד.

למעשה, רעיון זה אף מורחב ב-N. אם מכניסים את ה- javascript: alone :URL, ללא קוד JS אחריו, N מציג עמוד של מפרש JS שמאפשר להיכנס ברציפות ולהפעיל שורות של קוד. אף אחת מטכניקות אלו עובדות באינטרנט אקספלורר.

ניתן להשתמש ב- javascript: URLs גם בהקשרים אחרים. למשל, כמטרה של קישור היפר טקסט. כאשר המשתמש מקליק על הקישור, קוד ה-JS המוגדר מופעל. אם מגדירים javascript: URLs כערך של התכונה ACTION של התווית <FORM>, קוד ה-JS שב-URL מופעל כאשר המשתמש מאשר את הטופס. בהקשרים כאלו, javascript: URLs הוא בעיקרו תחליף ל- event handler. ניתן להשתמש ב- event handler ו-
javascript: URLs לחילופין- הבחירה ביניהם היא ענין של סיגנון.

ישנם מספר נסיבות בהם ניתן להשתמש ב- javascript: URLs ולא ב- event handlers. כאשר משתמשים באוביקטים שאינם תומכים ב- event handlers. למשל, התווית <AREA> אינה תומכת ב- onClick event handler בפלטפורמת Windows ב-N 3. לכן, אם רוצים להפעיל קוד JS כאשר המשתמש מקליק על תמונה משורטטת הקודמת ל- 4 N, חייבים להשתמש ב- javascript: URLs.

ה. תחביר סגנון הדף ב-JS

ב- 4 N, קוד יכול להופיע ב- style sheet נתונים מסוים, בין התווית <STYLE TYPE = "text/javascript"> ו- <STYLE/>. כל קוד JS כזה צריך להופיע ב- <HEAD> של מסמך HTML. מטרתו היא להגדיר סגנון דף ע"י הצבת התכונות classes, tags, ids. לדוגמא, הסגנון הבא משתמש בקוד JS על מנת להגדיר שכל הכותרות <H1> במסמך יופיעו כטקסט אדום מודגש:
<STYLE TYPE = "text/javascript">
  tags.H1.fontstyle = "bold";
  tags.H1.color = "red";
</STYLE>
    

ו. ישויות JS

ב-N 3 ומעלה, קוד JS יכול להופיע כערך תכונת HTML בצורה מיוחדת הידועה כ-JavaScript entity.ישות HTML זוהי סדרת תווים כמו: ;lt& אשר מייצגת תו מיוחד כמו >. ישות JS היא דומה, ובעלת התחביר הבא:
&{JavaScript-statements};
הישות יכולה להכיל מספר כלשהו של הצהרות JS , אשר חיבות להיות מופרדות אחת מהשניה ע"י פסיק. הישות חייבת להתחיל באמפרסנד(&) וסוגר מסולסל פותח ובסוף סוגר מסולסל ונקודה-פסיק.

כאשר נתקלים בישות ב- HTML , היא מוחלפת בערכה . ערך ישות JS הוא הערך של הביטוי או ההצהרה האחרונה שבישות, מומורת למחרוזת.

באופן כללי, ניתן להשתמש בישות בכל מקום בתוך קוד HTML. ישויות JS, יכולות להופיע רק בתוך הערך של תכונות HTML. ישויות אלו מאפשרות, לכתוב HTML מותנה. שימוש טיפוסי יכול להראות כך:
<BODY BGCOLOR = "&{favorite_color();};">
  <INPUT TYPE = "text"  NAME = "lastname" VALUE = "&{defaults.lastname};">
    

ז. הערות מותנות

ב-4 N ומעלה, ניתן להשתמש בישות JS בתחביר משתנה של הערת HTML, על מנת ליצר conditional comment. אם ביטוי JS המשובץ בישות מחושב לערך true, מתעלמים מההערה, וגוף ההערה ממשיך כרגיל. אם הביטוי מחושב לערך false, ההתנהגות היא רגילה ע"י שימוש בהערה והתעלמות מתוכנה.

הערות מותנות מאפשרות לכתוב קוד JS שרץ רק על פלטפורמות שיכולות לתמוך בו. הקוד הבא, למשל, ירוץ רק אם התכונה navigator.platform שווה למחרוזת "win95" :
<! - - &{navigator.platform = = "win95"};
  <SCRIPT>
    … // JavaScript code goes here.
  </SCRIPT>
- - >
    
3. ביצוע תוכניות JS

תסריטים

הצהרות JS אשר מופיעות בין התוויות <SCRIPT> ו- <SCRIPT/> מתבצעות על פח סדר הופעתן, וכאשר יותר מתסריט אחד מופיע בקובץ, תסריטים אלו מתבצעים גם כן על פי סדר הופעתם. אותו חוק תקף גם לגבי תסריטים הנכללים מתוך קבצים שונים עם התכונה SRC. ביצוע התסריטים מתרחש כחלק מתהליך ניתוח HTML של הדפדפן. כך, אם תסריט מופיע בחלק של ה- <HEAD> של מסמך HTML, אף אחד מחלקי ה- <BODY> של המסמך עדיין לא הוגדר. כלומר, אובייקטי JS אשר מיצגים את התוכן של המסמך, כמו Form או Link, לא נוצרו עדיין והקוד לא יכול להשתמש בהם.

התסריטים לא צריכים לנסות להפעיל אובייקטים שלא נוצרו עדיין. למשל, לא ניתן לכתוב תסריט אשר מפעיל את התוכן של טופס HTML אם התסריט מופיע לפני הטופס בקובץ ה-HTML. חוקים דומים תקפים על בסיס case-by-case. לדוגמא, ישנן תכונות של האובייקט Document שניתן להציבן רק מתוך תסריט שבחלק ה- <HEAD> של מסמך HTML ,לפני שהדפדפן התחיל לנתח את תוכן המסמך שבחלק ה- <BODY>.

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

כפי שהוזכר קודם, תסריטים המשתמשים בתכונה SRC על מנת לקרוא קבצי JS חיצוניים, מתבצעים כמו תסריטים שכוללים את הקוד שלהם באופן ישיר בתוך הקובץ. כלומר, מפענח ה-HTML ומפרש JS חייבים שניהם לעצור ולחכות עד שקובץ ה-JS החיצוני נטען – תסריטים אינם יכולים להטען במקביל. הורדת קובץ חיצוני של קוד JS, אפילו על פני חיבור מודם מהיר יחסית, יכולה לגרום עיכובים ניכרים בטעינה ובביצוע של דף רשת. כמובן, שאם קוד JS ממופה ב-cache מקומי, בעיה זו נעלמת.

4 N מאפשר לקוד JS להיכלל ב-style sheet בתוך זוג התוויות <STYLE> ו- <STYLE/>. הצהרות JS שבתוך style sheet מתבצעות כמו הצהרות JS שבתוך <SCRIPT>, פרט לכך ששרשרת הטווח מעודכנת כך שאת המשתנים מחפשים כתכונות של האובייקט Document לפני שמחפשים אותם כתכונות של האובייקט Window. כלומר style sheet JS יכול להתיחס לתוויות, מחלקות ותכונות זהות של האובייקט Document כאילו היו משתנים גלובליים, במקום להשתמש בביטויים כמו: document.tags.

ב-2 N, יש באג המתיחס לריצת תסריטים, בכל מקום בו הדפדפן משנה את גודלו, כל התסריטים שבו מפורשים שוב.

פונקציות

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

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

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

Event Handlers

הגדרת event handler יוצרת פונקצית JS. פונקציות אלו מוגדרות כחלק מתהליך פענוח HTML, אבל כמו פונקציות המוגדרות ישירות ע"י תסריטים, event handlers אינם מתבצעים מיד. ביצוע event handlers הוא אסינכרוני, מאחר ו-events בדר"כ מתרחשים בהתאם לבקשת המשתמש פועל על אובייקטי HTML, אין דרך לחזות מתי event handler יקרא.

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

אם מסיבה כלשהי, חיבים לבצע פעולה ארוכה ב- event handler, יש להבטיח שהמשתמש ביקש במפורש את הפעולה ואז יש לידעו שתתכן המתנה. ניתן לידעו ע"י תיבת דו שיח ( )alert, או ע"י הדפסת טקסט בשורת המצב. כמו כן, אם התוכנית דורשת הרבה תהליכים ברקע, ניתן לתזמן פונקציה שתקרא שוב ושוב במשך זמן סרק, ע"י המתודה ( )setTimeout.

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

העובדה ש-event handlers יכולים להקרא לפני שהמסמך נטען בשלמותו, בעלת שתי משמעויות חשובות. ראשית, אם ה-event handler קורא לפונקציה, יש להיות בטוחים שהפונקציה כבר הוגדרה לפני שה-handler קורא לה. דרך אחת להבטיח זאת היא להגדיר את כל הפונקציות בחלק של ה- <HEAD> של מסמך HTML. חלק זה של המסמך תמיד מפוענח בשלמותו לפני חלק ה- <BODY>. מאחר וכל האובייקטים שמגדירים event handlers חייבים בעצמם להיות מוגדרים בחלק ה- <BODY> ,מובטח שפונקציות שבחלק ה- <HEAD> יהיו מוגדרות לפני כל event handler שנקרא.

המשמעות השניה היא שחיבים להיות בטוחים שה- event handler אינו מנסה להפעיל אובייקטי HTML שעדיין לא פוענחו ונוצרו. Event handler יכול תמיד להפעיל את האובייקט שלו, כמובן, וגם כל אובייקט שהוגדר לפניו בקובץ ה- HTML. אסטרטגיה אחת היא להגדיר את דף הרשת של ממשק המשתמש בדרך כזו שה- event handlers מתייחסים רק לאובייקטים שהוגדרו קודם. למשל, אם מגדירים טופס שמשתמש ב-event handlers רק עבור הכפתורים Submit ו-Reset, צריך למקם את הכפתורים הללו בתחתית הטופס.

בתוכניות מורכבות יותר, יתכן שלא נוכל להבטיח שה-event handlers פועלים רק על אובייקטים שהוגדרו לפניהם, לכן יש לתת תשומת לב רבה יותר. אם event handler פועל רק על אובייקטים המוגדרים באותו טופס, בדר"כ לא יהיו בעיות. כאשר הוא פועל על אובייקטים שבטפסים אחרים או במסגרות אחרות, זה מתחיל להיות מדאיג. טכניקה אחת היא לבחון את הקיום של האובייקט שרוצים להפעיל לפני שמפעילים אותו. ניתן לעשות זאת בפשטות ע"י השוואתו לערך null. לדוגמא:
<SCRIPT>
  function set_name_other_frame(name)
  {
    if(parent.frames[1] = = null) return;    // מסגרת אחרת לא הוגדרה עדיין
    if(!parent.frames[1].document) return;    // מסמך לא נטען לתוכה עדיין
    if(!parent.frames[1].document.myform) return;    // טופס לא הוגדר עדיין
    if(!parent.frames[1].document.myform.name) return;  // שדה לא הוגדר
    parent.frames[1].document.myform.name.value = name;
  }
</SCRIPT>
<INPUT TYPE = "text" NAME = "lastname" onChange = "set_name_other_frame(this.value)";>
    
טכניקה אחרת ש-event handler יכול להשתמש על מנת להבטיח שכל האובייקטים הנדרשים הוגדרו, מערבת את ה-onLoad event handler. ה-event handler הזה מוגדר בתוך התוויות <BODY> או <FRAMESET> של קובץ HTML ונקרא כאשר מסמך או frameset נטען בשלמותו. אם מאתחלים דגל (flag) בתוך ה- onLoad event handlers, event handlers אחרים יכולים לבחון דגל זה על מנת לבדוק אם הם יכולים לרוץ בבטחה, עם הידיעה שהמסמך נטען בשלמותו וכל האובייקטים שהוא מכיל הוגדרו. לדוגמא:
<BODY onLoad = "window.loaded = true;">
  <FORM>
    <INPUT TYPE = "button" VALUE = "Press Me" onClick = "if(window.loaded != true) return; doit();">
  </FORM>
</BODY>
    

ה- onLoad( ) event handlers ו- ( )onUnload

ה- onLoad event handler ו- onUnload מוגדרים בתוך התוויות <BODY> או <FRAMESET> של קובץ HTML. ה-onLoad handler רץ כאשר המסמך או frameset נטען במלואו, כלומר, כל התמונות הורדו והוצגו, כל תתי המסגרות נטענו, כל ישומוני java ו-plugins התחילו לרוץ וכ'ו. ה- onUnload handler רץ רק לפני שהדף נטען, וזה מתרחש כאשר הדפדפן מתכוון להמשיך לעמוד חדש. יש להיות מודעים שכאשר עובדים עם ריבוי מסגרות, אין הבטחה של סדר קריאת ה- onLoad event handler עבור המסגרות השונות, חוץ מה- hendler עבור מסגרת האב שנקרא לאחר ה- handlers של כל ילדיו.

ה-onLoad event handler מאפשר לבצע איתחולים עבור דף הרשת, בעוד שה- ה-onUnload event handler מאפשר לבטל כל אפקט מתמשך של איתחול או לבצע כל "ניקוי" הכרחי אחר של העמוד. למשל, onLoad יכול לאתחל את התכונה Window.defaultStatus כך שתציג הודעה מיוחדת ב- status bar. לאחר מכן ה- onUnload handler יאחסן את התכונה defaultStatus כבררית המחדל שלו (המחרוזת הריקה), כך שההודעה לא תמשיך בעמודים אחרים.

יש לשים לב שה- onUnload event handler לא צריך להריץ כל סוג של פעולה מתמשכת, ולא להציג תיבות דו-שיח. הוא קיים על מנת לבצע פעולת ניקוי מהירה. הרצתו לא מאיטה את המעבר לעמוד חדש.

JavaScript URLs

קוד JS ב-"javascript : URL" אינו מתבצע כאשר המסמך שמכיל ה-URL נטען. הקוד אינו מפוענח עד שהדפדפן מנסה לטעון את המסמך שאליו מתיחס ה-URL. זה קורה כאשר המשתמש מקליד URL של JS, או, יותר נפוץ, כאשר המשתמש עוקב אחר קישור, מקליק על תמונה בצד הלקוח, או מאשר טופס.
"javascript : URL" בדר"כ שווה ל-event handlers, וכמו ב- event handlers, הקוד שב-URLs הללו יכול לרוץ לפני שהמסמך נטען בשלמותו, לכן, חיבים לנקוט באותם אמצעי זהירות עם " javascript : URL " כמו עם event handlers, על מנת להבטיח שאינם מנסים להתיחס לאובייקטים שטרם הוגדרו.

ישויות JS והערות מותנות

ישות JS, המשמשת כערך של תכונת HTML או כחלק מהערה מותנית, חיבת להיות מחושבת כחלק מתהליך פיענוח HTML. למעשה, מאחר וקוד JS שבישות מייצר ערך שהופך לחלק מה-HTML עצמו,תהליך פענוח ה-HTML תלוי במפענח JS. ישויות JS יכולות להיות מוחלפות תמיד ע"י תסריטים מסורבלים אשר כותבים את תוויות ה- HTML המושפעות, באופן דינמי. לדוגמא:
<INPUT TYPE = "text" NAME = "lastname" VALUE = "&{defaults.lastname};">
שורת קוד זו יכולה להיות מוחלפת בשורות הבאות:
<SCRIPT>
  document.write('<INPUT TYPE = "text" NAME = "lastname" VALUE = " ' + defaults.lastname + ' ">');
</SCRIPT>
    
באופן דומה, כל הערה מותנת יכולה להיות מוחלפת ע"י תסריט אשר באופן דינמי מוציא כפלט את תוכן ה-HTML שבתוך ההערה, רק אם הישות מחושבת כ-true.

זמן החיים של חלון ומשתנה

האובייקט Window הוא האובייקט הגלובלי של צד הלקוח ב- JS, וכל המשתנים הגלובליים הם תכונות שלו. מה קורה לאובייקטי Window ולמשתנים שהם מכילים, כאשר הדפדפן עובר מדף רשת אחד לאחר ?

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

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

זמן החיים של אובייקט Window יכול להיות ארוך מדפי הרשת שהוא מכיל ומציג, וארוך יותר מזמן החיים של התסריטים המוכלים בדפי הרשת שהוא מציג.

כאשר דף רשת, המכיל תסריט מבוטל משום שהמשתמש הצביע לדפדפן על דף חדש, התסריט מבוטל לבדו עם הדף המכיל אותו. ( אם התסריט לא בוטל, הדפדפן עלול להיות מוצף בתסריטים מתמשכים שונים). המשתנים המוגדרים ע"י התסריט הם למעשה תכונות של האובייקט Window המכיל את התסריט, ולכן ניתן לחשוב שהם נשארים מוגדרים. מצד שני, השארתם מוגדרים נראית מסוכנת- תסריט חדש שנטען לא יתחיל עם פעולת הניקוי, ולמעשה, לא יוכל לדעת לעולם אלו סוגי תכונות (וכתוצאה מכך גם משתנים) הוגדרו כבר.

למעשה, כל ההגדרות של תכונות ע" המשתמש (אשר כוללות את כל המשתנים) נמחקות בכל פעם שדף רשת מבוטל. התסריטים שבמסמכים שנטענו לאחרונה מופעלים בתחילה ללא משתנים מוגדרים וללא תכונות מוגדרות באובייקט Window שלהם, חוץ מהתכונות המרכזיות הסטנדרטיות ותכונות המוגדרות ע"י המערכת בצד הלקוח של JS.
כלומר, זמן החיים של תסריטים ושל המשתנים שהם מגדירים, זהה לזמן החיים של המסמך המכיל את התסריטים. זמן זה באופן פוטנציאלי קצר יותר מזמן החיים של החלון או המסגרת, אשר מציג את המסמך המכיל את התסריטים. ישנן סיבות אבטחה חשובות מדוע זה חייב להיות כך.

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