JavaScript - 程式碼壓縮與最佳化

壓縮程式碼

在正式上線前,可以將JavaScript程式碼進行壓縮,減少檔案大小,讓使用者下載更快,也節省頻寬。方法有手動與自動兩種。

手動(效果不好):

  • 刪除「長變數名」、「註解」、「空格」、「換行」…
  • true改用1, false改用0

缺點,易產生錯誤。

自動(建議使用):

使用工具,自動化產生壓縮式的JavaScript檔案:


JavaScript自動化壓縮工具還有很多,各位可以自行上網找一套自己喜歡的來用。未來新的 Visual Studio 11 / .NET Framework 4.5 會將自動化壓縮最佳化 JavaScript 與 CSS 等特性加入。

JavaScript 程式碼最佳化

這個部份提出的都是自動化壓縮工具比較幫不上忙,有些是邏輯技巧,有些是程式技巧,順序上,應該先進行內部程式碼最佳化,然後再使用壓縮工具來加速提升。

宣告變數

JavaScript中未宣告的變數(函式中也一樣)預設為全域變數,全域變數只有在瀏覽器關閉後才釋放。

1name = Bruce;

使用內建函數

內建函數都已編譯過,執行速度會比即時編譯的JavaScript快很多。

巢狀if

將出現率最多的情況放在前面,另外,使用switch語句替代巢狀if/else if。

整合同性質工作

指令碼中程式行數越少,執行時間越快,將同性質的指令碼集中一次處理,例如,例如宣告變數:

1// 宣告方法一
2var name="Bruce";
3var age = 18;
4var birthday = new Date(2010/10/10);
5 
6// 宣告方法二
7var name="Bruce", age=18,birthday=new Date(2010/10/10);

節約使用DOM

JavaScript對DOM的處理可能是最耗時費力,盡量減少DOM的操作,例如,為ul新增10個li,我們的處理方式可以有:

1var oUL = document.getElementById("ulItem");
2for (var i=0; i<10; i++){
3  var oLI = document.createElement("li");
4  oUL.appendChild(oLI); //10次
5  oLI.appendChild(document.createTextNode("Item" + i)); //10次
6}

共執行20次DOM操作。其實我們可以有更好的選擇:

1var oUL = document.getElementById("ulItem");
2var oTemp = document.createDocumentFragment();
3for (var i=0; i<10; i++){
4  var oLI = document.createElement("li");
5  oLI.appendChild(document.createTextNode("Item" + i));
6  oTemp.appendChild(oLI);
7}
8oUL.appendChild(oTemp); //1次

共執行1次DOM操作。20 : 1,相信那段程式碼效率一眼就可以看出來。

[KKBruce補充]可多利用 document.createDocumentFragment 來最佳化相關程式碼。

最佳化的影響

壓縮程式碼與程式碼最佳化通常會大大影響「可讀性」,不佳的可讀性讓後續「維護」困難度升高,所以正常做法是分為上線和開發兩個版本。

  • 上線:使用壓縮及最佳化,加速下載速度,提高執行效能。
  • 開發:保持良好程式架構和註解等,提高可讀性及減低維護難度。

JavaScript - 除錯, Debug

常見錯誤有:
  1. 語法錯誤(syntax error)
  2. 邏輯錯誤(logic error)
  3. 執行錯誤(runtime error)

除蟲清單:
  • 確定「括號( )」成對出現
  • 確定程式區塊的「大括號{ }」成對出現
  • 避免打錯字,使用有關鍵字提示功能IDE開發工具
  • JavaScript有大小寫之分
  • 字串與變數連接錯誤,例如,多或少+連接符號
  • 單、雙引號,維持一致使用方式
  • 單、雙引號,沒有成對出現也是常見錯誤
  • 確定物件在使用前已經建立
  • 別對區域變數與全域變數取相同的名稱
  • 變數不存在
  • 等號(=)與比較符號(==)使用錯誤
  • 記得要結束";"

bug處理:
  • alert()與document.write()方法
  • 使用window.onerror事件
  • try ... catch
  • Firebug for Firefox

目前主流且最新版本的瀏覽器(IE9, Chrome 16)都內建不錯的除錯功能,也是另一種選擇。

JavaScript - 物件導向(Object-oriented Language, OOP)

Object-oriented Language

Object-oriented Language,物件導向程式語言,特性有:

  1. 封裝Encapsulation
  2. 繼承Inheritance
  3. 多形Polymorphism

Object(物件)

讓正真有需要的原始碼接觸資料,減少資料曝露的程度,讓程式碼再利用。物件結合資料與行為,建立一種新的資料型別,其中可以儲存(store)資料,也可以根據資料而行動(act),所以物件是個容器,其中儲存資料,並聯繫資料與依據資料行動的原始碼。物件(Object)在一個儲存容器內聯繫起變數與函式。

資料(變數)+行為(函式)=物件

物件內的資料稱「property」(屬性、特性),物件內的行為稱「method」(方法),

property + method = Object

.(點)

點號運算子('.' dot operator)用於取用物件property與method,

Object + . + property/method

例如,

1// mail 物件
2// . 運算子
3// from, to, send 方法
4mail.from = "...";
5mail.to = "...";
6...
7mail.send();

物件可以包含其他物件,例如,

1var mail = new Mail(new Date(), "from", ...);
在Mail建構式中傳入一個Date物件。

建構式(constructor) - 屬性(property)

物件具有資料,資料必須在物件建立時「初始化」,每個自訂物件都需要自己的建構式,名稱與「物件相同」。

1function Mail(from,to,body,subject){
2  this.from = from;
3  this.to = to;
4  this.body = body;
5  this.subject = subject;
6}

建構式使用首字母大寫,建立property需使用JavaScript的關鍵字「this」,關鍵字this區分物件property與一般變數。this指定物件property的擁有權,同時設定property的初始值建立屬於「這個(this)」物件的property,例如,

1this.from = from;

將收到的參數指定給新property。沒有this,建構式不會知道你正在建立物件property。以建構式建立物件時,我們使用new運算子,它呼叫物件的建構式,開啟物件建立過程。例如,

1var mail = new Mail("from","to","body","subject");

  1. var mail:新物件儲存在變數裡
  2. new Mail(...):new運算子建立新Mail物件(呼叫建構式)
  3. "from","to","body",...:傳入參數給建構式,以設定property

建構式(constructor) - 方法(method)

1function Mail(from,to,body,subject){
2  // Object method
3  this.send = function(){
4  ...
5  }
6}

該如何知道指令碼(函式)應放入method?

method就是根據物件的property而採取某些行動,換言之,如果指令碼需要取用物件內部資料,就非常合適放入method。

把函式轉為方法

  1. 宣告method
  2. 把現有程式碼移入method裡
  3. 修改使用物件property

宣告method,使用this建立method,與建立property類似。例如,

1this.send = function(){
2  // Do something
3}

關於選用參數

1function Mail(from,to,body,subject,smtp,port){
2  ...
3  // 假設smtp與port為選用功能
4  this.smtp = smtp;
5  this.port = port;
6}

當某個參數未傳入給function、method、constructor時,在任何試圖使用參數值的原始碼裡,它的值都是null,在缺少參數相對應的property將會被設為null。確認選用參數在function參數清單的最後面。例如:當funcion有兩個參數,可能的選擇有:

  • 兩個都傳入
  • 只傳入第一個
  • 兩個都不傳
  • 無法只傳第二個

複本

Mail物件的send()方法,Mail物件的method是在建構式裡,利用關鍵字this建立,但依此建立的Mail物件都會各有一份物件方法的複本,關鍵字"this"用於設置「instance」擁有的property和method。例如,

1var mail1 = new Mail(...);
2var mail2 = new Mail(...);
3var mail3 = new Mail(...);

每個Mail物件(mail1,mail2,mail3),都會有自己的property與method複本,等於會有三份method,這是浪費又沒效率。property為每個物件儲存獨特資料,method應該為物件所共享。

Class與instance

類別Class,是物件的描述,樣版、藍圖。例如,

1function Mail(...)

實例Instance,實際物件,依Class建立。例如,

1var mail = new Mail(...);
mail是依Mail來建立的物件(instance)。

每個instance的property多半都不一樣,所以每個instance才需要有自己的property複本,但method沒有必要複製到每個instance中。

Class擁有method

class-owned instance method,當method為Class所擁有時,所有該Class的instance都可以取用此method,而不需要另外複製一份。

在Class使用prototype

在JavaScript中每個物件都有一個prototype物件(以property存在),prototype用以設定Class level(類別層級)的property與method, 而非屬於instance。也就是說,我們需要把method的「擁有權」指派給Class,而不是指派小單一instance,例如,

1Mail.prototype.send = function(){}

prototype使用需在建構式之外。send()方法直接附加到Mail class本身,而非隸屬於某個instance,這樣無論Mail class建立多少份instance,都只會有一份send()方法。當send()接受呼叫時,將在class內執行,例如,

1mail1.send();
2mail2.send();
3mail3.send();

當其他Mail物件的instance也呼叫了send()方法,仍會執行Class內的同一方法。

class property
類別屬性,此property只需要在類別儲存一次,但能被所有instance存取,例如,

1Mail.prototype.smtp = "smtp.kkbruce.net";
2Mail.prototype.port = "25";

此property只有一個值,讓所有instance共享。想成,它是class的全域變數,但只能讓class對應的instance取用。JavaScript標準物件能也使用prototype,每個物件都有prototype,它允許在Class Level增加property與method,例如,擴充Date物件,

1Date.prototype.shortFormat = function(){
2  return this.getFullYear() +'/'+(this.getMonth()+1)+'/'+ this.getDate();
3}
4 
5var d = new Date();
6d.shortFormat();
這樣即可傳回「年/月/日」格式日期函式。

Class自己的method

類別方法(class method),它屬於Class,只能取用class property,不能取用instance property,建立class method是直接為Class設定method,而不使用prototype,例如,

1Mail.showSMTP = function(){
2  alert('SMTP:'+Mail.prototype.smtp+' ,\n Port:'+Mail.prototype.port);
3}
4...
5Mail.showSMTP();
  • Mail.showSMTP:建立Mail物件的showSMTP方法
  • Mail.prototype.smtp:為了從class method取用class property,你必須下探至prototype,smtp是個Mail class property,所以Mail class method可以取用
  • Mail.showSMTP();:直接透過Class名稱Mail來呼叫方法

再回建構式

讓建構式專注在property的建立與初始化 OOP範例:AJAX OOP的寫法

01function AjaxRequest() {
02  if (window.XMLHttpRequest) {
03    try {
04      this.request = new XMLHttpRequest();
05    } catch(e) {
06      this.request = null;
07    }
08  } else if (window.ActiveXObject) {
09      try {
10        this.request = new ActiveXObject("Microsoft.XMLHTTP");
11      } catch(e) {
12        this.request = null;
13      }
14  }
15 
16if (this.request == null)
17    alert("建立Ajax物件錯誤.\n" + "細節:" + e.message);
18}

01AjaxRequest.prototype.send = function(type, url, handler, postDataType, postData) {
02  //type, url, handler為get必要參數
03  //postDataType, postData為post必要參數
04  if (this.request != null) {
05    this.request.abort();
06 
07    url += "?dummy=" + new Date().getTime();
08 
09    try {
10      this.request.onreadystatechange = handler;
11      this.request.open(type, url, true);
12      if (type.toLowerCase() == "get") {
13        this.request.send(null);
14      } else {
15        this.request.setRequestHeader("Content-Type", postDataType);
16        this.request.send(postData);
17      }
18    } catch(e) {
19      alert("Ajax程式錯誤.\n" + "細節:" + e);
20    }
21  }
22}

1AjaxRequest.prototype.getReadyState = function() {
2  return this.request.readyState;
3}

1AjaxRequest.prototype.getStatus = function() {
2  return this.request.status;
3}

1AjaxRequest.prototype.getResponseText = function() {
2  return this.request.responseText;
3}

1AjaxRequest.prototype.getResponseXML = function() {
2  return this.request.responseXML;
3}

宣告AjaxRequest物件,

1var ajax = new AjaxRequest();

JavaScript - Asynchronous JavaScript And XML, AJAX

同步與非同步

同步HTTP請求:請求 → 顯示 → 互動 → 暫停 → 請求 → 顯示 → 互動 → 暫停 …

需要不斷重新刷新整個頁面,會出現一段時間的空白。

非同步HTTP請求:請求 → 顯示 → 互動 → (請求)互動 → (請求)互動 …

非同步HTTP請求在顯示、執行互動不需要再暫停操作,可以馬上執行所需的互動,只向伺服器要求一小部份資料,然後更新頁面的一小部份, 不需要重新刷新整個頁面,也不會出現一段時間的空白。

非同步好處

  1. 減輕伺服器的負擔,加快瀏覽速度(只給所需)
  2. 帶來更好的用戶體驗(更流暢的畫面)
  3. 標準化技術,主流瀏覽器都支援
  4. 促進頁面呈現與資料分離(提高可維護性)

AJAX組成

AJAX不是單一技術,是集4種技術而成,JavaScript、CSS、DOM、XMLHttpRequest。(或說5種,再加上(X)HTML)

JavaScript AJAX技術組成
名稱說明
JavaScript通用指令碼語言。是撰寫AJAX主要程式語言
CSS為Web頁面元素提供視覺化樣式的定義方法, AJAX透過修改CSS樣式,改變使用者介面
DOMAJAX可以在執行時透過DOM來改變使用者介面,或局部更新某個節點
XMLHttpRequestXMLHttpRequest物件允許Web開發人員向伺服器以非同步方式取資料, 資料格式通常是XML或是文字,目前較流行為JSON

XMLHttpRequest物件

能夠直接在Client使用Javascript來提出HTTP請求。IE內建MSXML剖析器有多個版本,其提供的XMLHttpReqest物件也有多個版本(不建議使用)。

KKBruce提醒,除非您必須處理類似IE等相容性問題,不然是不建議使用以下表格內容。

JavaScript IE內建MSXML剖析器
版本DLL名稱ProgID
2.0(IE5)msxml.dllMicrosoft.XMLHttp
2.6msxml2.dllMSXML2.XMLHttp
3.0(IE6)msxml3.dllMSXML2.XMLHttp.3.0
4.0msxml4.dllMSXML2.XMLHttp.4.0
5.0msxml5.dllMSXML2.XMLHttp.5.0
6.0msxml6.dllMSXML2.XMLHttp.6.0

建立XMLHttpRequest物件

在Mozilla,Chrome和Safaris等主流瀏覽器是內建物件,例如,

1// 1. 透過 new XMLHttpRequest() 產生物件
2// 2. 注意大小寫
3var xmlHttp=new XMLHttpRequest();

在IE6之前是透過ActiveX控制項物件(由MSXML提供),例如,

1var xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");

IE7之後,同時支援原生XMLHttpRequest物件(預設值)和ActiveX控制項物件,例如,

1var xmlHttp;
2function createXMLHttpRequest(){
3  if (window.XMLHttpRequest) //支援原生型
4    xmlHttp = new XMLHttpRequest();
5  else if (window.ActiveXObject) //IE6以下
6    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
7}

[KKBruce補充] 建立XMLHttpRequest物件注意事項

XMLHttpRequest物件屬性

JavaScript XMLHttpRequest物件屬性
名稱說明
readyState唯讀屬性,目前狀態
responseBody唯讀屬性,取得伺服器的回應,傳回非符號位元組的陣列
responseSteam唯讀屬性,取得伺服器的回應,傳回IStream資料流物件
responseText唯讀屬性,取得伺服器的回應,傳回字串
responseXML唯讀屬性,取得伺服器的回應,傳回XML DOM物件,可作DOM處理
status唯讀屬性,取得HTTP狀態碼
statusText唯讀屬性,取得HTTP狀態訊息字串
onreadystatechange存取屬性,執行readyState屬性改變的事件處理,設定處理的程序

readyState會回傳一數值,以表示目前處理的進度。

JavaScript readyState回傳狀態值
名稱說明
0uninitalized,未初始化
1loading,載入中
2loaded,載入完成
3interactive,可互動
4completed,完成

status會回傳狀態碼,以表示目前處理的結果。

流程 -
名稱說明
200OK,請求成功
202請求被接收,但處理未完成
400錯誤的請求
404Not Found,找不到網頁
500Internal Server Error,內部錯誤
...…其他網頁錯誤碼

[KKBruce補充] 這裡有一篇整理很棒的 HTTP 狀態碼,【HTTP 狀態碼,在 IIS 7.0 和 IIS 7.5】非常建議加入我的最愛中,在查詢錯誤的 HTTP 狀態碼時非常有用。例如,我們一般只知道 404 狀態碼是找不到,但 404 下還有整整 20 項細部的定義,這對於開發人員是不可多得的資訊,可以更快速清楚問題所在,而不是用經驗法則在處理。

XMLHttpRequest物件方法

JavaScript XMLHttpRequest物件方法
名稱說明
abort()取消目前HTTP請求
getAllResponseHeaders()取得全部HTTP標頭內容
getResponseHeader("指定Header名稱")取得指定HTTP標頭名稱的內容
open("GET|POST","URL",async,userid,pwd)開啟HTTP請求
send("參數")傳送HTTP請求到伺服器
setRequestHeader("自訂Header名稱",value)自訂HTTP標頭資料

XMLHttpRequest物件open方法參數
名稱說明
GET取得伺服器回應
POST傳送資料到伺服器
URL請求的XML文件或伺服端程式(ASP.NET, PHP, JSP...)
async布林值, 預設true,false表示需要等到伺服器回應後才繼續執行Javascript
userid, pwd伺服器需要id/password,才需要使用

send("參數")說明

參數表示要向伺服器發送的資料,參數格式為查詢字串的形式,例如,

1var param = "name=Bruce&age=18";
在open中指定為GET,則參數作為查詢字串傳送,如果指定為POST,則作為HTTP的POST方法傳送,對於send()方法而言,此參數為必需, 如不發送任何資料,請傳送null即可。

1// GET
2xmlHttp.send(null);
3// POST
4xmlHttp.send(param);

setRequestHeader()說明

如果使用POST方法,在發送之前必須設定HTTP標頭,例如,

1xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
2// 加上UTF-8是最好
3xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");

AJAX下的GET與POST

01function startRequest(){
02    // 建立xmlHttp物件
03 createXMLHttpRequest();
04 // 向Demo.aspx,使用GET開啟請求
05 xmlHttp.open("GET","Demo.aspx");
06 // 狀態有改變時,就執行
07 xmlHttp.onreadystatechange = function(){
08     // 當狀態值為4(完成)與狀態碼為200(請求成功)
09  if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
10      // Do something
11   alert("服務器傳回訊息: " + xmlHttp.responseText);
12 }
13 // 傳送HTTP請求到伺服器
14 // GET記得加上null
15 xmlHttp.send(null);
16}

IE會自動暫存非同步的結果,解決方法是每次非同步請求的URL不同,我們可以加上一個伺服器不需要的參數,讓每次的URL都不同。

1// 加上一個時間戳計當亂數使用
2var url = "Demo.aspx?timestamp=" & new Date().getTime();
3xmlHttp.open("GET",url, true);

GET請求如果有參數,直接放入URL網址中,例如,

1var queryString = "name=Bruce&age=18";
2var url = "Demo.aspx?" + queryString + "&timestamp=" + new Date().getTime();

POST請求有參數,統一放在send()中來傳送,例如,

1var queryString = "name=Bruce&age=18";
2var url = "Demo.aspx?timestamp=" & new Date().getTime();
3// url放在open()
4xmlHttp.open("POST",url,true);
5...
6xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
7// queryString放在send()
8xmlHttp.send(queryString);

POST方法中文會出現亂碼

在IE8與Firefox上測試已無此問題,但為了相容性還是建議加上解決方法。

這是因為XMLHttpRequest物件在處理傳回responseText/XML時是使用UTF-8編碼,建議使用解決方法2,對回傳的資料進行decodeURIComponent()解碼即可。

解決方法一

對要傳送的資料進行兩次encodeURI()編碼,以解決中文亂碼問題,例如,

1...
2xmlHttp.send(encodeURI(encodeURI(queryString)));

對傳回資料responseText/XML再進行一次decodeURI()解碼,例如,

1responseDiv.innerHTML = decodeURI(xmlHttp.responseText);

解決方法二

setRequestHeader直接宣告(charset)使用UTF-8,例如,

1xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
2xmlHttp.send(queryString);

對傳回資料responseText/XML進行decodeURIComponent()解碼,例如,

1responseDiv.innerHTML = decodeURIComponent((xmlHttp.responseXML));

解決方法三

ASP,ASP.NET: 輸出之前Response.Charset = "big5 | gb2312",依取得的頁面charset設定。

onreadystatechange方法

AJAX的重點在狀態改變後的事件處理函式(handler),也可以說,這是唯一我們必須自訂(手動)設計程式碼的地方,換個方向說,我們在請求/回應,而伺服器回應資料後,我們要如何處理及顯示到網頁上(DOM)。

同時觸發非同步問題

如果我們必須同時觸發(呼叫)多個AJAX物件,因為我們通常都是把建立的AJAX物件的xmlHttp宣告為全域變數,所以可能會產生覆蓋的情況。

解決同時觸發非同步問題

就是將xmlHttp宣告為區域變數來處理,並在收到伺服器資料且處理完後,手動刪除。

01function getData(){
02  var xmlHttp="";
03  createXMLHttpRequest();
04  xmlHttp.onreadystatechange = function(){
05    ...
06    // 處理完立即刪除與釋放
07    delete xmlHttp;
08    xmlHttp = null;
09  }
10}

delete關鍵字

刪除物件的property。The delete operator deletes an object, an object's property, or an element at a specified index in an array.

JavaScript - XML DOM簡介

Asynchronous JavaScript And XML, AJAX

  1. HTML/XHTML與CSS:顯示UI與相關資料
  2. XML:伺服端非同步傳遞的資料
  3. XML DOM:當Browser非同步取得XML資料後,可進一步使用Javascript和XML DOM取出所需資訊
  4. XMLHttpRequest:Javascript透過XMLHttpRequest物件來建立非同步HTTP請求

Extensible Markup Language, XML

利用特殊的標示語言(Markup Language),建立XML文件(XML Document)。

XML Document

XML Document是由元素(Elements)組成。

標籤(Tags)

XML能自己定義標籤,如:<book>、<title>…。

元素(Elements)

元素是一個完整項目:<book code="K2010">Javascipt入門</book> 開始標籤、屬性、文字內容、結尾標籤。

屬性

屬性值需要使用引號(單、雙皆可)括起。

實體參考(Entity Reference)

XML本身有一些保留符號,如文件內需要使用這些符號,請使用實體參考。

JavaScript XML實體參考
實體參考代表符號
&lt;<
&gt;>
&amp;&
&apos;'
&quot;"

註解(Comment)

與HTML相同,例如,

1<!-- 註解內容 -->

PCDATA

文字內容稱PCDATA,例如,

1<book code="K2010">Javascipt入門</book>

PCDATA → Javascript入門。

CDATA

Character Data,表示XML在剖析文件時不用處理此區塊的內容,例如,

1<script type="text/javascript">
2<![CDATA[
3    function a(){
4    ...
5    }
6]]>
7</script>
CDATA的註解
在HTML解析器(Browser)是不承認CDATA開始"<![CDATA["與結束"(]]>"標籤,也不認識HTML實體參考(Entity Reference), 可能導致會把問題顯示在Browser,並可能產生"跨網站腳本"問題,所以在HTML會建議註解CDATA。

範例一:JavaScript註解
1<script type="text/javascript">
2// <![CDATA[
3  document.write("<");
4// ]]>
5</script>

範例二:CSS註解

1<style type="text/css">
2/*<![CDATA[*/
3  body { background-image: url(marble.png) }    
4/*]]>*/
5</style>

Processing Instructions, PI

允許XML文件包含傳送給應用程式的指令,例如開頭宣告就是PI,PI如同註解,不屬於XML文件內容。

1<?xml version="1.0" encoding="utf-8" ?>

Document Type Declarations, DTD

是XML文件的驗證機制,可以檢查XML標籤與文件架構是否正確。

1<!DOCTYPE book [
2<!ELEMENT book (code, title, author, price)>
3<!ELEMENT code (#PCDATA)>
4<!ELEMENT title (#PCDATA)>
5<!ELEMENT author (zh-tw_name, zh-en_name)>
6<!ELEMENT zh-tw_name (#PCDATA)>
7<!ELEMENT zh-en (#PCDATA)>
8<!ELEMENT price (#PCDATA)>
9]>

一行一行看,不會很難。

  • <!DOCTYPE book [:book之下包含以下元素
  • <!ELEMENT book (code, title, author, price)>:元素book之下包含其他子元素
  • <!ELEMENT code (#PCDATA)>:code元素含文字內容

XHTML

Well-Format(良好格式)的HTML。什麼是Well-Format?

  1. 標籤、屬性都是小寫
  2. 一定要<html>為根元素
  3. 標籤必須有結尾標籤,空元素需以 />結束標籤
  4. 巢狀標籤不能重疉
  5. 屬性必須有值
  6. 屬性值需使用引號
  7. Script需使用CDATA

第三點,標籤必須有結尾標籤,例如,

1<-- 有頭有尾 -->
2<b>粗體字</b>
3<-- 空元素需以 />結束標籤 -->
4<input id="name" type="text" />

第五點,屬性必須有值,例如,

1<-- HTML -->
2<input type=radio checked>
3 
4<-- XHTML -->
5<input type="radio" checked="checked" />

Document Object Model, DOM

Document Object Model,XML DOM可以將XML文件視為一棵樹狀結構的節點, XML DOM就是W3C DOM針對XML文件所提供應用程式的標準程式介面, 可以透過API來存取各節點物件,將一份結構化文件(XML Document)轉換成一棵節點(Nodes)樹, 提供節點的屬性、方法來存取節點內容,或新增、修改、刪除節點內容。例如,

1<book>
2  <code>K2010</code>
3  <title>Javascript入門</title>
4  <author>
5   <zh-tw_name>金剛</zh-tw_name>
6   <zh-en_name>Bruce</zh-en_name>
7  </author>
8</book>

經過DOM剖析器之後,如圖,

DOM樹
圖一:DOM樹


MSXML

在Javascript程式可使用IE內建的MSXML元件來建立XML DOM物件,建立物件使用ProgID字串,但MSXML物件只能在IE使用,要注意相容性問題。

KKBruce提醒:實務上已經很少人使用MSXML來撰寫程式碼,以下只是簡單介紹,大多都已經使用標準AJAX方式(XMLHttpRequest物件)來處理。

JavaScript MSXML DOM版本
版本DLL名稱ProgID
2.0msxml.dllMicrosoft.XMLDOM或MSXML.DOMDocument
2.6msxml2.dllMSXML2.DOMDocument
3.0msxml3.dllMSXML2.DOMDocument.3.0
4.0msxml4.dllMSXML2.DOMDocument.4.0
5.0msxml5.dllMSXML2.DOMDocument.5.0
6.0msxml6.dllMSXML2.DOMDocument.6.0

範例程式一(IE Only):

01<table border="1">
02<script type="text/javascript" >
03//<![CDATA[
04  // 建立XML DOM物件, 使用ProgID來建立
05  var xmlDom = new ActiveXObject("MSXML2.DOMDocument.6.0");
06  //async=false,可以保證XML文件能完全載入
07  xmlDom.async = "false";
08  // 載入XML文件
09  xmlDom.load("Books.xml");
10  // 建立文件元素子節點樹
11  var objNode = xmlDom.documentElement.childNodes;
12  // 顯示所有XML節點
13  for ( i=0; i < objNode.length; i++ ) {
14      document.write("<tr><td>");
15      document.write(objNode.item(i).nodeName + "</td><td>");
16      document.write(objNode.item(i).text + "</td></tr>");
17  }
18//]]>
19</script>
20</table>

範例程式二(IE Only):

1>// 字串變數
2var strXML = "<book>";
3strXML = strXML + "<code>K2012</code>";
4...
5//載入字串變數
6xmlDom.load(strXML);

先建立XMLDOM物件,然後由Books.xml當成資料來源,由XMLDOM物件讀入轉換成節點樹,再將節點讀取顯示出來。

[補充]使用MSXML2.DOMDocument.6.0與MSXML2.DOMDocument.3.0就好。

JavaScript - W3C DOM簡介

HTML DOM

DOM Core(核心)提供HTML與XML文件瀏覽、處理和維護階層架構的功能。主要有二大功能:

  • 瀏覽(Navigator):走訪各節點
  • 參考(Reference):存取節點

提供一致的走訪方式,只要建立好樹狀結構,所有能走訪到的節點就是標籤物件,文字節點都可以使用相同的nodeValue屬性更改其內容。

DOM HTML

HTML專屬的DOM API,提供現成的物件模型。需使用id/name屬性或forms[]、images[]等物件集合才能取得標籤物件, 而且每種標籤物件都擁有不同的屬性。

DOM Core可使用在HTML與XML,DOM HTML則針對HTML。

每一節點都是一個物件

  • DOM HTML提供各節點物件的屬性和方法
  • DOM Core提供屬性來走訪節點

W3C DOM只能更改文字節點的內容,其它標籤物件的屬性和方法還是來自DOM HTML。

轉換為節點樹

1<table>
2  <tbody>
3    <tr><td>HTML</td><td>CSS</td></tr>
4    <tr><td>Javascript</td><td>jQuery</td></tr>
5  </tbody>
6</table>

瀏覽器會將由伺服器所傳遞過來的HTML轉換為一節點樹,節點樹一定由html元素為根節點,html底下一定有兩個子點節,head元素子節點與body元素子節點。我們可以把這一層一層的關係畫成圖,此圖又稱節點(樹)圖。

節點(樹)圖

以上面table結構為例,

節點(樹)
圖一:節點(樹)

節點(樹狀)結構:


  • 下一層的子節點 → Child Node → tbody是table的Child Node
  • 上一層的父節點 → Parent Node → table是tbody的Parent Node
  • 左右節點(兄弟) → Sibling Node → tr與tr或tr之下td與td,各為Sibling Node
  • 最下層葉節點 → Leaf Node → td為Leaf Node
  • 文字節點(HTML的內容) → Text Node → HTML/CSS/Javascript/jQuery

在轉換一般table時需注意,要先將table轉換成HTML 4.0版的表格,即擁有<tbody>標籤,這樣在訪問時,才不會出錯。

另注意<font>,IE在轉換時,會在<font>後多加一個文字節點#text,目前HTML標準已不建議使用<font>標籤,請改用CSS。

在DOM中有3種節點

  1. 元素節點:element node,各種標籤便是這些元素節點的名稱,元素節點可以包含其他元素,唯一沒有被包含只有根元素<html>
  2. 屬性節點:attribute node,屬性節點總是被包含在元素節點之中,例<a href="http://blog.kkbruce.net">KKBruce Blog</a>,a是元素節點名稱,href是屬性節點名稱
  3. 文字節點:text node,標籤裡具體的文字內容,網頁最終目的是向使用者展示內容

W3C DOM屬性

JavaScript W3C DOM唯讀屬性
名稱說明類型/傳回類型
firstChild傳回第一個子節點childNodes物件集合,包含此節點下所有的子節點Node
lastChild傳回最後一個子節點的childNodes物件集合,包含此節點下所有的子節點Node
parentNode傳回父節點的物件,如已是根節點,傳回nullNode
nextSibling傳回下一個兄弟節點物件,如已是最後一個節點,傳回nullNode
previousSibling傳回上一個兄弟節點物件,如已是第一個節點,傳回nullNode
nodeName傳回節點的HTML標籤(英文大寫)名稱String
nodeType傳回節點種類,1是標籤(element node)、2是屬性(attribute node)、3為文字(text node)Number
specified布林值,傳回在HTML標籤是否有設定指定的屬性值Boolean

W3C DOM讀寫屬性

JavaScript W3C DOM讀寫屬性
名稱說明類型/傳回類型
nodeValue存取文字節點(text node),其他種類的節點傳回nullString

W3C DOM物件集合

W3C DOM物件集合可以取得下一層子節點和節點的屬性。

JavaScript W3C DOM物件集合
名稱說明類型/傳回類型
attributes節點屬性的物件集合,可以直接使用名稱來存取,僅用於元素節點NameNodeMap
childNodes所有子節點的物件集合(Array),方法item(i)可訪問第i+1個節點NodeList

在IE中可以直接使用id/name屬性來取得指定的節點物件,但用此方法實作的程式碼相容性不佳, 建議先使用getElementById("id")來取得指定的節點物件,然後再實作以確保Browser相容性。例如,

1// 相容性不好
2myid.childNodes[0].firstChild.nodeValue = "ASP.NET MVC";
3 
4// 相容性好
5var objValue = document.getElementById("myid");
6objValue.childNodes[0].firstChild.nodeValue = "ASP.NET MVC";

IE與其他Browser中childNodes走訪不同問題

我們在使用childNodes走訪節點時,IE會依順序走訪各元素節點,但其他瀏覽器不光是元素節點,連它們之間的空格也被當成子節點計算。例如,

1<ul id="comicList">
2 <li>航海王</li>
3 <li id="Naruto">火影忍者</li>
4 <li>海棉寶寶</li>
5<ul>

可以使用以下JavaScript在IE與其他瀏覽器測試,

1var eleUL=document.getElementById("comicList");
2var listName="";
3if (ele.hasChildNodes()) {
4 var eleLI = eleUL.childNodes;
5 for (var i=0,len=eleLI.length;i<len;i++){
6  listName += eleLI[i].nodeName + "\n";
7 }
8 alert(listName);
9}

在IE的測試結果:

  1. LI
  2. LI
  3. LI

在Firefox測試結果:

  1. #text
  2. LI
  3. #text
  4. LI
  5. #text
  6. LI

解決瀏覽器走訪不同問題

01function nextSib(node){
02  var tempLast = node.parentNode.lastChild; //取得node的最後一個節點
03  if (node ==tempLast) { //是否為最後一個節點
04    return null;
05  }
06  var tempObj = node.nextSibling; //非最後一個,可找下一個Node
07  while ( tempObj.nodeType!=1 && tempObj.nextSibling!=null) //nodeType不是元素節點且不是最後一個,即找到元素節點為止
08    tempObj = tempObj.nextSibling; //往下找下一個
09  return (tempObj.nodeType==1) ? tempObj:null; //如果是元素節點,傳回節點本身,否則傳回null
10}

01function prevSib(node){
02  var tempFirst = node.parentNode.firstChild; //取得node的第一個節點
03  if (node ==tempFirst) { //是否為第一個節點
04    return null;
05  }
06  var tempObj = node.previousSibling; //非第一個,可往上找上一個Node
07  while ( tempObj.nodeType!=1 && tempObj.previousSibling!=null) //nodeType不是元素節點且不是第一個,即找到元素節點為止
08    tempObj = tempObj.previousSibling; //往上找上一個
09  return (tempObj.nodeType==1) ? tempObj:null; //如果是元素節點,傳回節點本身,否則傳回null
10}

我們可以透過這兩個函式來走訪,而不用擔心相容性問題。

1var eleLI = document.getElementById("Naruto");
2var nextItem = nextSib(eleLI);
3var preItem = prevSib(eleLI);
4if (nextItem != null) //傳回不是null,是元素節點
5...

W3C DOM方法

W3C DOM提供方法能建立、刪除、複製、交換、取代節點。

流程 -
名稱範例說明
appendChildobj(父).appendChild(obj(子))在obj(父)節點新增子節點obj(子),傳回新增的節點物件
cloneNodeobjNew = objDup.cloneNode(deep)複製objDup節點的新節點物件,deep為false僅複製此節點,true連子節點的整個節點樹都複製
createElementobjNew = document.createElement("tagName")建立一個HTML節點物件
createTextNodeobjNew = document.createTextNode(string)建立文字節點
hasChildNodesobjNode.hasChildNodes()檢查節點是否擁有子節點,有為true
insertBeforeobj(父).insertBefore(obj(子),objBrother)在obj(父)節點前插入一個子節點obj(子),位置在objBrother節點前
removeChildobj.parentNode.removeChild(targetNode)先找到要刪除的節點,透過parentNode的removeChild()方法來刪除目標節點
replaceChildobj.parentNode.replaceChild(newNode,oldNode)先找到要替換的節點,透過parentNode的replaceChild()方法來替換節點
getAttributeobj.getAttribute("attr")讀取obj的attr屬性值,例如,obj.getAttribute("title");
setAttributeobj.setAttribute("attr","value")設定obj的attr屬性的值為value,例obj.setAttribute("src","bruce.png");

insertAfter()函式

DOM只有提供insertBefore()在目標元素之前插入新元素,或是appendChild()在父元素的childNodes尾新增新元素, 如果需要在特用元素後插入新元素,需自行撰寫。

01function insertAfter(newElement, targetElement){
02  // 取得目標元素的上層節點
03  var tParent = targetElement.parentNode;
04  // 檢查是否有子元素
05  if (tParent.lastChild == targetElement)
06    // 附加至子節點後
07    tParent.appendChild(newElement);
08  else
09    // 新增至節點之前
10    tParent.insertBefore(newElement, targetElement.nextSibling);
11}

新增HTML Tag步驟

  1. 建立節點
  2. 進行處理

建立節點

1// 新增HTML節點
2var objNew = document.createElement("P");
3// 新增文字節點
4var objText = document.createTextNode("新增說明文字");

進行處理

1// 將objNew節點加入objNode節點最後面
2objNode.appendChild(objNew);
3// 將objText文字節點加入objNew節點之後
4objNew.appendChild(objText);

例如,在一個空的<table>可以一層一層加上<tr>、<td>來自由動態產生你所想要的<table>。

改變節點文字的安全步驟

  1. 刪除所有子節點:removeChild()
  2. 根據新內容,建立新內容節點:createElement(),createTextNode()
  3. 將新內容節點,附加在目標節點之下:appendChild()

1function replaceNodeText(id, newText){
2  var node=document.getElementById(id);
3  while (node.firstChild)
4    node.removeChild(node.firstChild);
5  node.appendChild(document.createTextNode(newText));
6}

DOM與CSS樣式

DOM提供了透過節點取用樣式的途徑。

className屬性:提供對節點樣式類別的存取。

1alert(ele.className);
2ele.className = "highlight";

style屬性:提供對單一樣式的存取。

1ele.style.visibility = "hidden";
2ele.style.display = "none";

JavaScript Anchor Element

Anchor,連結,也就是HTML裡最重點的一個特性,讓我們可以在不同網頁之間瀏覽。

1<a href="protocal://domain/file#bookmark" target="frame_name">context</a>

href屬性

設定超連結的目的地。

  • protocal:通訊協定,例如,http/https/ftp
  • domain:網域名稱或IP
  • file:檔案名稱
  • #bookmark:指定HTML文件中的降落點

讓我們用範例來說明降落點:

1<a id="info">TOP</p>

在網頁設定一個名稱top的降落點,然後,

1<a href="news.htm#info">News</a>

我可以指定要到那一個網頁的那一降落點。如果#info是在網頁的中間,你就能發現,我們一點連結過去時,網頁會自動移至#info的位置,這也就是降落點的意思。

連結其他屬性

JavaScript 連結屬性
名稱說明
name/id名稱
type存取連結資源的Content type
accessKey快速鍵
target設定超連結目的地HTML文件的frame名稱
charset連結資源的編碼方式
hreflang連結資源的語系
tabIndexTab鍵切換的順序值

target屬性設定值

JavaScript 連結target屬性設定值
名稱說明
_blank開啟新視窗來顯示HTML文件
_self在原視窗來顯示HTML文件
_top在原視窗顯示HTML文件
_parent如為frameset,且擁有父frame,就在父frame顯示HTML文件

_top如為frameset,取消frameset以全視窗顯示HTML文件。

在Windows Server 2008 R2 x64上安裝WAMP服務

我在一台全新乾淨的Windows Server 2008 R2 x64 with Service Pace 1的伺服器上,要架設WAMP服務,一直碰壁,以下心得整理。

WAMP現在區分為x32與x64,如上所述,如果是新伺服器,必須先安裝對應版本的 Visual C++ 2008 可轉散發套件。

wamp x32 需安裝 [Microsoft Visual C++ 2008 可轉散發套件 (x86)]
wamp x64 需安裝 [Microsoft Visual C++ 2008 可轉散發套件 (x64)]

不安裝之後,當你要開啟 wampmanager 管理程式時,會一直出現錯誤,而無法啟用。

wampmanager.exe錯誤訊息:

01記錄檔名稱:         Application
02來源:            Application Error
03日期:            2012/2/20 下午 03:07:10
04事件識別碼:         1000
05工作類別:          (100)
06等級:            錯誤
07關鍵字:           傳統
08使用者:           不適用
09電腦:            WIN08R2SP1
10描述:
11失敗的應用程式名稱: wampmanager.exe,版本: 1.6.1.33,時間戳記: 0x2a425e19
12失敗的模組名稱: KERNELBASE.dll,版本: 6.1.7601.17651,時間戳記: 0x4e211319
13例外狀況碼: 0x0eedfade
14錯誤位移: 0x0000b9bc
15失敗的處理程序識別碼: 0xbb0
16失敗的應用程式開始時間: 0x01ccef9e43559d41
17失敗的應用程式路徑: C:\wamp\wampmanager.exe
18失敗的模組路徑: C:\Windows\syswow64\KERNELBASE.dll
19報告識別碼: 811a009f-5b91-11e1-8bd8-08002701cd4a
20事件 Xml:
22  <System>
23    <Provider Name="Application Error" />
24    <EventID Qualifiers="0">1000</EventID>
25    <Level>2</Level>
26    <Task>100</Task>
27    <Keywords>0x80000000000000</Keywords>
28    <TimeCreated SystemTime="2012-02-20T07:07:10.000000000Z" />
29    <EventRecordID>672</EventRecordID>
30    <Channel>Application</Channel>
31    <Computer>WIN08R2SP1</Computer>
32    <Security />
33  </System>
34  <EventData>
35    <Data>wampmanager.exe</Data>
36    <Data>1.6.1.33</Data>
37    <Data>2a425e19</Data>
38    <Data>KERNELBASE.dll</Data>
39    <Data>6.1.7601.17651</Data>
40    <Data>4e211319</Data>
41    <Data>0eedfade</Data>
42    <Data>0000b9bc</Data>
43    <Data>bb0</Data>
44    <Data>01ccef9e43559d41</Data>
45    <Data>C:\wamp\wampmanager.exe</Data>
46    <Data>C:\Windows\syswow64\KERNELBASE.dll</Data>
47    <Data>811a009f-5b91-11e1-8bd8-08002701cd4a</Data>
48  </EventData>
49</Event>

錯誤訊息二:

01記錄檔名稱:         Application
02來源:            SideBySide
03日期:            2012/2/20 下午 03:07:10
04事件識別碼:         33
05工作類別:          無
06等級:            錯誤
07關鍵字:           傳統
08使用者:           不適用
09電腦:            WIN08R2SP1
10描述:
11"c:\wamp\bin\php\php5.3.9\php-win.exe" 的啟用內容產生失敗。 找不到依存組合 Microsoft.VC90.CRT,processorArchitecture="amd64",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"。 請使用 sxstrace.exe 進行詳細的診斷。
12事件 Xml:
14  <System>
15    <Provider Name="SideBySide" />
16    <EventID Qualifiers="49409">33</EventID>
17    <Level>2</Level>
18    <Task>0</Task>
19    <Keywords>0x80000000000000</Keywords>
20    <TimeCreated SystemTime="2012-02-20T07:07:10.000000000Z" />
21    <EventRecordID>671</EventRecordID>
22    <Channel>Application</Channel>
23    <Computer>WIN08R2SP1</Computer>
24    <Security />
25  </System>
26  <EventData>
27    <Data>Microsoft.VC90.CRT,processorArchitecture="amd64",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"</Data>
28 
29    <Data>c:\wamp\bin\php\php5.3.9\php-win.exe</Data>

WampServer管理程式啟動後,你還會發現就算修改 httpd.conf 裡的 Port 設定,還是無法啟用 Apache!因為在Windows Server 2008 R2 x64上我有掛IIS 7 (使用 80 Port),奇怪的事,就算把IIS 7停用,把80 Port給Apache還是無法啟用。

我知道從Vista / Windows Server 2008之後版本開始,對於 C: 有一些權限上的管理與以前不同,我沒有細查文件,我的決解辦法是移除原安裝,重新安裝至非 C: 的路徑,例如,d:\wamp 立即見效。

如果要把PHP掛到IIS上執行,有二種選擇
  1. FastCGI
  2. ISAPI 
我選擇使用後者,在IIS裡設定相當簡單(注意,你在 IIS 的【角色服務』中,必有啟用【ISAPI 擴充功能】與【ISAPI 篩選器】),在【所在網站】或【虛擬目錄】裡有二個地方要設定,一在【處理常式對應】,二在【預設文件】。

處理常式對應 → 新增指令碼對應 →

  1. 要求路徑:*.php
  2. 執行檔:D:\wamp\bin\php\php5.3.9\php5isapi.dll (路徑自行參考,找 *isapi.dll 就對了)
  3. 名稱:PHP (隨便,方便辨識即可)

預設文件 → 新增 → 【 index.php 】 (一般PHP預設首頁文件檔案)

注意x32與x64混合環境

在上面最後一小段,你將PHP使用ISAPI方式掛到IIS上執行,不知道有沒有像我,碰到一堆的Error!後來驗證後證明是我自己搞不清楚狀況。@_@

我們這台x64伺服器上有一個網站是執行x32(ASP)應用程式,當我要把WAMP x64版本php5isapi.dll掛到IIS執行(ASP網站),不管怎麼試就是無法啟動index.php,會一直出現Error,試了好久,結果是:

  • 【WAMP x64 + Windows Server x64 + IIS (應用程式集區 - 啟用32位元應用程式)】(Bad)
  • 【WAMP x32 + Windows Server x64 + IIS (應用程式集區 - 啟用32位元應用程式)】(Bad)
  • 【WAMP x32 + Windows Server x64 + IIS】(Bad)
  • 【WAMP x64 + Windows Server x64 + IIS】(Good)

也就是說,在Windows Server 2008 R2 x64環境下,想要用ISAPI方法使用PHP只有一種方式,完全x64。【WAMP x64 + Windows Server x64 + IIS】就只有這樣的組合才有辦法讓ISAPI可以正常運作PHP。目前在【Windows Server x64 + IIS (應用程式集區 - 啟用32位元應用程式)】是無法透過ISAPI方式讓PHP正常運作。

JavaScript frame - iframe Element

Frame簡介

框架頁(Frameset)目前使用的越來越少,多會建議使用CSS來實作畫面切割排列。不過<iframe>在影音網站還是很常見。
1<frameset cols="value1,value2" rows="value3,value4">
2    <frame name="1" src="1.html" scrolling="yes|no" />
3    <frame name="2" src="2.html" scrolling="yes|no" />
4    <frame name="3" src="3.html" scrolling="yes|no" />
5    <frame name="4" src="4.html" scrolling="yes|no" />
6</frameset>

Frame屬性

  1. cols屬性:定義左右分割frame尺寸
  2. rows屬性:定義上下分割frame尺寸

以前面範例為例,先切左右,畫面從中間左右分割為兩塊(cols兩個value),再切上下,再從中間橫切上下兩塊(rows兩個value),所以畫面會被切成四塊,分別載入不同HTML文件。

frameset運作

name="1"的frame,載入1.html;name="2"的frame,載入2.html,以此類推,由左而右,由上而下。

frame屬性

JavaScript frame屬性
名稱說明
src要顯示的HTML文件
nameframe名稱
scrolling是否有捲動軸,yes有

frames集合架構

Frames集合架構
圖一:Frames集合架構

frames屬性

JavaScript frames集合屬性
名稱說明
self傳回目前的window物件,相當於window屬性
parent傳回目前frame的上一層物件(父物件)
top如果是巢狀frame,top就是最上層的window物件,也因為巢狀frame,top不一定等於prent屬性

1// 由後往前看,找frames[0]的上一層物件
2parent.frames[0];
3// 使用name來取得window物件,然後就可以進一步設定window物件屬性
4parent.1.localtion.href = "1.html";

巢狀frame

  1. 第一層frameset的frame可以擁有第二層的frameset
  2. window和self屬性是指第二層frameset中目前<frame>
  3. parent屬性是指第二層<frameset>,下一層是self屬性的frame
  4. top屬性是最上層第一層<frameset>,下一層是parent屬性的第二層frameset

Frameset屬性

  • cols屬性:定義左右分割frame尺寸
  • rows屬性:定義上下分割frame尺寸

Frame屬性

JavaScript Frame屬性
名稱說明
name/idframe名稱
frameBorder是否顯示frame邊框
src載入的HTML文件
scrolling是否擁有捲動軸
noResize是否可以調整frame的尺寸
marginHeight存取frame邊界的高
marginWidth存取frame邊界的寬

iframe介紹

1<iframe name="" src="" height="" width="" align=""></iframe>

JavaScript iframe屬性
名稱說明
name/id名稱
src顯示圖檔、HTML文件、URL網址
height
width
alignIframe與網頁其他文字對齊方式

1// 將Video.htm載入到id="if1"的iframe
2document.getElementById("if1").src="Video.htm";

JavaScript Image Element

所有圖片<img>依照出現順序都屬於images物件集合 。例如,

1// 設定網頁裡第一張圖片的alt屬性
2document.images[0].alt="wolf";

image元素屬性

JavaScript image元素屬性
名稱說明
name存取圖片名稱
src存取圖片檔案的URL
width存取圖片寬度
height存取圖片的高度
hspace/vspace存取圖片的位置
isMap設定圖片為伺服端的影像地圖
useMap設定圖片為客戶端的影像地圖
alt存取無法顯示圖片時的替代文字
complete檢查圖片是否已經完全載入,true為已載入

image元素事件

JavaScript image元素事件
名稱說明
onload當圖片完全載入時,觸發此事件
onabort當使用者中止載入時,觸發此事件
onerror當找不到圖片檔案或圖檔損壞時,觸發此事件

放大圖片時

如果<img>是含在<div>之內,當我們放大圖片時,能在<div>內使用CSS的兩個參數,讓<div>幫我們出現捲動軸。

1<div id="imgFrame" style="overflow-x:scroll;overflow-y:scroll;height:350px;width:600px;">
2<img src="kkbruce.png" alt="KKBruce" />
3</div>

JavaScript Table Element

table物件

table物件就是<table>,不過並沒有提供集合物件存取指定的<table>,使用使用id或name屬性來存取,例如,

1document.mytable.border = 3;

summary屬性


1<table summary="This is KKBruce created Table">

此table的說明,它對於Browser而言是不會顯示,但對於網路蜘蛛則十分重要,是加分的屬性。

scope屬性

1<th scope="row | col">

th標題是要放在「行(row)」或「列(col)」。scope預設是row,指定th標題出現在表格上方第一行或左邊第一列。

Table元素屬性


JavaScript Table元素屬性
名稱說明
caption存取表格的標題文字(如果存在)
border存取表格框線尺寸
width存取表格的寬度
cellPadding存取儲存格文字內容和框線的距離
cellSpacing存取儲存格框線間的距離
frame存取表格外框線
rules存取表格內框線
rows傳回表格每一最TableRow物件的物件集合(Array)
tBodies傳回<tbody>物件集合
tFoot傳回<tfoot>物件集合
tHead傳回<thead>物件集合

Table元素方法

在table中,每一儲存格都有一組index編號,index編號是由TableRow物件的rowIndex屬性和TableCell物件的cellIndex屬性所組成,(rowIndex, cellIndex) 所以一個二維表格裡每一儲存格Index編號是:
(0,0)(0,1)
(1,0)(1,1)
(2,0)(2,1)


JavaScript Table元素方法
名稱說明
insertRow(index)插入一列<tr>,插入位置是在參數的列號之前
deleteRow(index)刪除index的表格列
createCaption()建立標題文字<caption>
deleteCaption()刪除標題文字
createTHead()建立標題區塊<thead>
deleteTHead()刪除標題區塊
createTFoot()建立註腳區塊<tfoot>
deleteTFoot()刪除標題區塊

1document.mytable.insertRow(0).insertCell(0);
2document.mytable.insertRow(0).insertCell(1);

刪除table某一列

1function deleteColumn(table, number) {
2  //每行刪除對應儲存格
3  for (var i=0, len=table.rows.length; i < len; i++){
4    table.rows[i].deleteCell(number);
5  }
6}

Table元素屬性與方法

另一種分類法:

針對table元素:
JavaScript table元素屬性與方法
名稱說明
caption指向<caption>元素(如果存在)
tBodies指向<tbody>元素的集合
tFoot指向<tfoot>元素(如果存在)
tHead指向<thead>元素(如果存在)
rows表格中所有「行」的集合
deleteRow(position)刪除指定位置上的行
insertRow(position)在rows集合中的指定位置插入一個新行
creatCaption()建立<caption>元素並放入表格中
deleteCaption()刪除<caption>元素

針對tbody元素:
avaScript tbody元素屬性與方法
名稱說明
rows<tbody>中所有行的集合
deleteRows(position)刪除指定位置上的行
insertRows(position)在rows集合中的指定位置插入一個新行

針對tr元素:
JavaScript tr元素屬性與方法
名稱說明
cells<tr>中所有儲存格的集合
deleteCell(position)刪除指定位置上的儲存格
insertCell(position)在cells集合的指定位置上插入一個新的儲存格
1<tr>
2  <td>儲存格1</td>
3  <td>儲存格2</td>
4</tr>

<tr>...</tr>對應TableRow物件。例如,TableRow → rows[i]。<td>...</td>對應TableCell物件,例如,TableCell → cells[i]。

1// rows[i],第幾列
2// cells[i],第幾格
3mytable.rows[i].cells[i];

TableRow(<tr>)

JavaScript TableRow屬性
名稱說明
cells傳回表格列中儲存格TableCell物件集合(Array)
align列中儲存格的水平對齊方式
vAlign列中儲存格的垂直對齊方式
rowIndex傳回TableRow物件的列號(Array)
sectionRowIndex傳回<thead>、<tfoot>、<tbody>區塊中TableRow物件列號

JavaScript TableRow方法
名稱說明
insertCell(index)插入儲存格在傳入index編號前
deleteCell(index)刪除傳入index編號儲存格

TableCell(<td>)

JavaScript TableCell屬性
名稱說明
align儲存格的水平對齊方式
vAlign儲存格的垂直對齊方式
colSpan存取儲存格的左右合併,colspan屬性
rowSpan存取儲存格的上下合併,rowspan屬性
cellIndex傳回儲存格編號

JavaScript - 表單元素 - Regular Expression

Regular Expression


Regular Expression(正規表達式) - 基本字元
名稱說明
\n換行符號
\rEnter
\tTab
\xHex16進位ASCII
\xOct8進位ASCII
\符號轉義,讓符號只是符號,無RE作用

因為符號在RE裡有其他作用,\.代表.、\?代表?,符號有:.、?、/、\、[、]{、}、(、)、+、*、|。

Regular Expression(正規表達式) - 字元集"["與"]"符號"
名稱說明
[abc]代表英文a、b、c
[a-z]代表26個英文小寫
[A-Z]代表26個英文大寫
[0-9]代表數字0到9
[a-zA-Z]代表所有大小寫英文
[^abc]除了a、b、c以外任何字元
-英文或數字的一個範圍
[^]在[]裡的^為排除的意思

[ ]代表一個區段、段落。

Regular Expression(正規表達式) - 常用範圍
名稱說明
\w[0-9a-zA-Z_],任何英數字和底線
\W[^0-9a-zA-Z_],也就是^\w的意思
\d[0-9],任何數字
\D[^0-9],也就是^\w的意思
\s比對空格,空白字元(space)、tab、換行字元、return/enter
..(點)比較任何字元,換行字元(newline)除外

以上都是常用的Escape字串。

Regular Expression語法


1var reName = /pattern/[g|i|gi];

使用變數來儲存pattern,遇/.../字串自動建立RegExp物件。把pattern被在"//"符號之間,就是你所要過濾的規則,例如/[0-9]/。

[g|i|gi]選擇性參數,尋找方式

  • g:比對字串中所有符合pattern字串的子字串, 如果沒有設定,將只找第一個符合pattern的字串
  • i:不區分pattern字串的英文大小寫

尋找方式範例

1// jscript(j小寫)和Jscript(J大寫)都符合
2var reJS1 = /[jJ]script/;
3// 2*2會出現四種符合的組合
4// javascript、javaScript、Javascript、JavaScript
5var reJS2 = /[jJ]ava[sS]cript/;

^開頭$結尾


1// 找出開頭是This的字串
2// 注意,此^不是放在[^],位置不同作用不同
3var reStar = /^This/;
4// 找出結尾是bye.的字串
5var reEnd = /bye.$/

Regular Expression(正規表達式) - ^開頭$結尾
名稱說明
^比對字串開頭
$比較字串結尾

^開頭$結尾範例


1// 需要指定「出現次數」,例如身分證
2// A123456789,第一碼為英文,第二碼為男女,3-9碼為數字
3var reID = /^[a-zA-Z]{1}[1-2]{1}[0-9]{8}/;

量詞


Regular Expression(正規表達式) - 量詞
名稱說明(次數)
?0或1次
*0或多次
+1或多次
{n}出現n次
{n,}至少n次
{n,m}n到m次
( )集合字元或/和中介字元,成為子樣式

最後一個(),我們舉個例子,「/(Hot)? ?Donuts/」過濾條件,可比對出Donuts或Hot Donuts。而「/(red|blue) pill/] 過濾條件,可比對出red pill或blue pill。

定義好樣式(pattern)後,可使用test()方法來測試。

1// 定義過濾條件
2var regex = /^\d{5}/$;
3// 使用test()測試是否符適合條件
4if (!regex.test(inputField.Value))
5  ...

RegExp物件


1var objRE = new RegExp("pattern字串", "g|i|gi");

第一個pattern字串(不需放在//符號之間),第二個為尋找方式的參數。使用RegExp物件的test()方法進行比對,符合回傳true。

1objRE.test(strValue);

如果在JavaScript字串變數需要尋找是否擁有符合Regular Expression的pattern子字串,此時請使用String物件的match()方法,例如,

1String.match(objRE);

字串(String)的match()方法範例,

1var str = "This is book.";
2var objRE = new RegExp("is", "g");
3var result = str.match(objRE);

我們將比對結果儲存起來,然後,

1// 沒有會傳回null,有會傳回Array
2// is, is --> 陣列
3document.write(result);
4// 傳回符合數量
5// 2
6document.write(result.length);

JavaScript - 表單元素 - textarea Element

textarea

testarea物件就是<textarea>,其中accessKey、defaultValue、disabled、form、name、readOnly、tabIndex、type等屬性和input物件相同。

form表單之textarea元素屬性
名稱說明
cols每一行可以有多少字元
rows多少行(列)

限制使用者輸入字元數

由於<textarea>沒有<input>的maxlength,所以我們自訂一個屬性來使用,例如,

1<textarea name="comments" id="comments" cols="40" rows="4" maxlength="100" onkeypress="return lessThan(this);"></textarea>

1function lessThan(objTA){
2  //比較輸入字元數與自訂屬性maxlength的比較結果
3  return objTA.value.length < objTA.getAttribute("maxlength");
4}

JavaScript - 表單元素 - select and option Element

select元素與option元素

select物件就是<select>,其中disabled、form、name、tabIndex、type、value等屬性和input物件相同。

form表單之select元素屬性
名稱說明
length取得共有多少<option>
multiple設定或取得選擇是否複選,true為多選
options取得option物件集合,這是一個Array
selectedIndex傳回選擇的選項index值,這是options的Index值
size設定欄位為下接式或清單,size大於1是清單方塊
text選項名稱
typeselect類型,單選傳回select-one,複選select-multiple

  • options 陣列的index由0開始。例如,SB.options[2]表示<select>中的第3項。
  • selectedIndex,例如,SB.options[selectedIndex].value;

form表單之option元素屬性
名稱說明
text存取選擇文字
defaultSelectedoption預設選項,即selected屬性
indexoption陣列index位置,以0開始
label設定或取得選項說明文字
selected是否被選取,true為選取

取得<select>選取值


01function getSelectValue(selectName){
02  var objForm = document.forms["form1"];
03  //取得對應的select
04  var SB = document.elements[selectName];
05  if (SB.type = "select-one") {
06    //單選
07    var Choice = SB.selectedIndex;
08    alert("Your Choice" + SB.options[Choice].text);
09  }
10  else {
11    //複選
12    var Choice = new Array;
13    for (var i=0,len=SB.options.length; i<len;i++){
14      if (SB.options[i].selected)
15        Choice.push(SB.options[i].text);
16    }
17    alert("Your Choice" + Choice.join());
18  }
19}

新增、替代、刪除<option>

使用Option()建構式直接新增,例如,

1var addOption = new Option(text, value, defaultSelected, selected);

defaultSelected與selected預設為0(false),可不設定。通常會將<select>清單的length直接設定為新選項,即最後一項。例如,

1SB.options[SB.options.length] = addOption;

將以上程式為一支副程式,

1function addOption(selectName, optionIndex) {
2  var objForm = document.forms["form1"];
3  var SB = objForm.elements[selectName];
4  var addOP = new Option("金剛", "King Kong");
5  //處理IE相容性
6  //先新增,再移動到指定Index
7  SB.options[SB.options.length] = addOP;
8  SB.insertBefore(addOP, SB.options[optionIndex]);
9}

替代,取代某一置位(index)的option,例如,

1SB.options[selectIndex] = addOption;

刪除,刪除某一置位(index)的option,例如,

1// 設定某一index為null即刪除
2SB.options[selectIndex] = null;

將以上程式整理成一支副程式,

1function removeOption(selectName, optionIndex){
2  var objForm = document.forms["form1"];
3  var SB = objForm.elements[selectName];
4  SB.options[optionIndex] = null;
5}

JavaScript - 表單元素 - checkbox and radio Element

checkbox與radio


JavaScript form表單checkbox與radio元素屬性
名稱說明
checked設定或取得是否選取或核取,選取或核取為true
defaultCheckedtrue預設選取或核取,checkbox或radio裡的checked屬性

checkbox與radio被選取的值

1if (oRadio[i].checked)
2  alert(oRadio[i].value);

設定選取,例如,

1document.forms["form1"].oRadio[i].checked = true;

全選、全不選、反選

01function changeBoxes(action) {
02  var objForm = document.forms["form1"];
03  var CB = objForm.hobby;
04  //取得checkbox屬性name=hobby的集合
05  for (var i=0,item; item = CB[i];i++){
06    if (action < 0)
07      item.checked = !item.checked;
08      // action傳入-1為反選
09      // 利用!來相反所有選擇
10    else
11      item.checked = action;
12     // action傳入1(true)為全選
13     // action傳入0(false)為全不選
14  }
15}

JavaScript - 表單元素 - Input Element

form表單input元素


JavaScript form表單input元素屬性
名稱說明
form取得input屬於那一個form
namename屬性
type類型
value設定或取得input的值,除下拉式功能表以外
accessKey此input的快捷鍵
accept顯示伺服器支援的ContentType清單
defaultValue設定或取得input的預設值
disabled設定input是否有作用,true為沒作用
tabIndex設定Tab鍵切換順序

JavaScript form表單input元素文字
名稱說明
maxLength設定或取得input最大字元數
readOnly設定或取得input是否是一個唯讀input,true為是
size設定或取得input的尺寸

disabled與readOnly


  • disable會使欄位無效,內容值無法傳送或讀取
  • readOnly會使欄位唯讀,但內容可傳送或讀取

JavaScript form表單input元素方法
名稱說明
blur()設定input失去處理權
focus()設定input擁有處理權
select()選取input,使用反白顯示文字內容,只可以使用在文字欄位
click()觸發onclick事件,button、checkbox、radio、reset、submit

如果使用input方法選擇文字欄位,需同時使用select()與focus(),欄位內容才會反白與取得處理權,例如,

1obj.select();
2obj.focus();

在button中使用submit()


1<input type="button" value="Submit" onclick="document.forms["form1"].submit();" />

如果使用submit()方法來提交表單,不會觸發<form>的onsubmit()事件,這點與<input type="submit />或<input type="image" />提交按鈕不同。

防止使用者重覆按下提交按鈕


1<input type="button" value="Submit" onclick="this.disabled=true;this.form.submit();" />

滑鼠經過時自動選擇文字


  • 在滑鼠經過時onmouseover="this.focus()";
  • 在取得處理權後,選取文字,onfocus="this.select()";

JavaScript - 表單元素 - Form Element

取得<form>裡元素

1<form name="form1">
2  <input type="text" id="username" />
3 
4  <input type="password" id="password" />
5 
6  <input type="button" id="send" />
7</form>

每一對<form>...</form>都解析為一個form物件,可以透過document.forms集合來引用這些物件,例如一個name屬性為"form1":document.forms["form1"]來取得,或使用表單在HTML中的索引來引用:document.forms[1],引用第二個表單物件。可以利用元素在集合中的位置或元素的name屬性來取得元素的引用。

以欄位名稱(name屬性)存取表單欄位

圖一:

1// 取得表單名稱為form1的表單集合
2var oform = document.forms["form1"];

1// 取elements集合中name屬性為username的值
2var getName = oform.elements.username.value;

1// 以元素名稱(username)來取值
2var getName = oform.elements["username"].value;
1// 表單和欄位都沒有指定name或id屬性,
2// 可使用forms與elements的index位置存取欄位
3var getName = oform.elements[0].value;
圖二 …

1document.forms[0].elements[0].value;

  • forms:所有表單物件是都<form>的物件集合
  • elements:表單內所有欄位物件的集合

forms與elements為一個Array Object,依tag在HTML文件出現的順序來編號,index由0開始。此方法,要注意tag順序的變動會影響JavaScript程式。

form

JavaScript form屬性
名稱說明
action存取form處理程式路徑
elementsArray,表單中所有表單欄位的集合
enctype表單向伺服器發送資料時,資料應該使用的編碼方法,預設為「application/x-www-form-urlencoded」,如果要上傳檔案,則「multipart/form-data」
length表單欄位的數量
method存取form資料傳送方法,有post與get
name表單的名稱,即<form>中的name屬性
targetform表單作用的框架

JavaScript form方法
名稱說明
reset()重設form欄位回預設值
submit()送出form欄位到伺服器

Taiwan Taiwan, I Love You

hear me

我不知道各位有沒有發現,我的Blog簡介、個人簡介…裡一定有台灣,I come from Taiwan,來自台灣,以下是個今天且關於台灣的故事。

在2012年1月8日,我從 about.me 這個服務收到一封信,這是一封小怪英文信,一個非常簡單的自我介紹,說他寫了一套軟體,他查詢到我為一些軟體進行過英譯中,想要請我翻譯此軟體為正體中文或簡體中文。(小怪英文信:這位自由軟體開發者( I'm a Freeware developer)是位波蘭人,寫出來的英文有那麼點小怪。)

這讓我考慮很久,原因在於,我翻譯那些軟體是覺得好用,且內容又不會太多太難。copy譯為複製,paste譯為貼上,我相信只要有一點英文底子的人,這誰都會,差異在願不願意出那份工,出那份力。在我有多的時間與體力之下,我就邊玩邊譯,當成複習英文單字。另一個重點,那時的我還沒生小孩,晚上有的是時間與體力。

我考慮了整整一週,突然想到,我自己抱怨過一件事,為什麼現在的外國軟體廠商,只要有出中文版,都一定先出簡體中文版,不然就「只有」簡體中文版。如果是用uni-code來complier,那還好,最少軟體開起來還比較不會有亂碼的問題。我曾經用過一套外國軟體,非常好用,但就是介面只有簡體中文可以選,因為介面上的英文不難,我還自己很不要臉的寫信去說,我可以幫忙翻譯成正體中文,結論是,人家理都不理,連封回信也沒有。那為什麼現在有機會可以幫忙,而你確不幫呢?

很快的我收到了語言檔,我想他是把波蘭文直譯為英文,本想語言檔翻譯好就寄回去了事,結果發現不行,因為有些內容根本與我們在使用的技術英文差異很大,只有打開軟體網頁與軟體本身邊玩邊翻譯。裡面好玩的事,他的英文軟體網頁是由Google線上翻譯的功能,把波蘭文翻譯為英文,老實說,有看沒有懂。

最後花了一個多月時間,終於把正體中文語言檔給寄出去給了他。先說明,我不是英文翻譯高手,也不是專業作家,譯的如何,我是感覺普普,因為很多專業術語,翻譯為中文,自己看了都怪,不譯為中文,又不是每個人都有技術背景,最後我選擇了約90%以上翻譯為中文,例如,Session我採用「工作階段」的中文,等作者把正式版發表,請大家多多指教。

台灣的故事呢?

今天,這位作者寄了beta版本給我測試,突然發現一件事,他軟體裡的語言選擇裡是會帶國旗,也就是英文帶英格蘭國旗,法文帶法國國旗。但讓我傷心的事,是他自己上網找資料(Google),自行把Traditional Chinese譯為中國傳統,而且帶的是五星旗。

這星期的豪小子,加上今天看了最上面的電影「聽說,hear me」,加上我辛辛苦苦翻譯的中文被加上一個錯誤的國旗,讓我有想感慨。

台灣為什麼以前能創造「台灣奇蹟」?為什麼wiki上面的台灣奇蹟是1950 ~ 1990年,那1990年之後,台灣"你"怎麼了?現在苦嗎?聽我爺爺說 823炮戰的故事,什麼感覺?我們根本無法感受到他在炮戰下的任何感受,他說,他怕到會哭,尿褲子算什麼。我們年輕人笑成一團。

現在苦嗎?

我們現在在國際上有個世界第一、第二對手,我們更應該好好加油。媒體只想沾光抄新聞,豪小子很棒,但也不用親戚朋友十八代都請出來上電視,focus在豪小子身上,夠了,豪小子會不會開口說一句:「我是台灣人。」我都很懷疑。不如吵美牛,還算點國際相關。(以上個人意見,請勿批評指教)



這才是我想要的台灣,台灣加油,大家加油。

JavaScript Event(事件) - 事件屬性和方法

事件屬性和方法

主要注意在IE與DOM名稱的差異上。


JavaScript 事件屬性和方法
IE名稱DOM名稱類型讀/寫說明
altKeyaltKeyBooleanR/W按下Alt鍵則為true
butoonbutoonIntegerR/W滑鼠事件,值對應按下的滑鼠鍵(對照下一張表格)
cancelBubblecancelBubbleBooleanIE:R/W、DOM:RIE設置為true可取消氣泡事件
N/AstopPropagation()FunctionN/ADOM使用此方法來取消氣泡事件
clientXclientXIntegerIE:R/W、DOM:R滑鼠指標在「用戶端區域」的X座標
clientYclientYIntegerIE:R/W、DOM:R滑鼠指標在「用戶端區域」的Y座標
ctrlKeyctrlKeyBooleanIE:R/W、DOM:R按下Ctrl鍵則為true
fromElementrelatedTargetElementIE:R/W、DOM:R滑鼠指標所離開的元素
toElementcurrentTargetElementIE:R/W、DOM:R滑鼠指標正在進入的元素
N/AcharCodeIntegerR按下按鍵的Unicode值
keyCodekeyCodeIntegerR/WIE中keypress事件按下按鍵的Unicode值,keydown/keyup事件為按鍵的數位代號。DOM中keypress時為0,其餘為按下按鍵的數位代號。
N/AdetailIntegerR滑鼠按鍵被按一下的次數
returnValueN/ABooleanR/W設置為false時可取消IE事件的預設行為
N/ApreventDefault()FunctionN/ADOM使用該方法來阻止事件的預設行為
screenXscreenXIntegerIE:R/W、DOM:R滑鼠指標相對於「整個電腦螢幕」的X座標值
screenYscreenYIntegerIE:R/W、DOM:R滑鼠指標相對於「整個電腦螢幕」的Y座標值
shiftKeyshiftKeyBooleanIE:R/W、DOM:R按下Shift鍵則為true
srcElementtargetElementIE:R/W、DOM:R引起事件的元素/物件
typetypeStringIE:R/W、DOM:R事件的名稱

我最常看到也最麻煩是程式碼中只寫 returnValue,也就是說單單只針對IE進行處理,只要使用其他Browser即可閃過些段程式碼。正規有進行相容性處理是returnValue與preventDefault都要進行處理。

範例:使用同一個函數處理多個事件

01window.onload=function(){
02  var objImg = document.getElementByTagName("img")[0];
03  objImg=handle;
04}
05 
06funcion handle(evt){
07  // 相容性處理
08  if (window.event) evt = window.event;
09  // 透過type屬性判斷事件名稱,這裡沒有on字首
10  if (evt.type == "click")
11    ......
12  else if (evt.type == "mouseover")
13    ......
14}  

範例:找出觸發事件的物件

01function handle(evt){
02  // 相容性處理
03  if(window.event) evt = window.event;     
04  var getTarget;
05  if(evt.srcElement)  // 處理相容性,獲取IE事件目標
06    getTarget = evt.srcElement;
07  else
08    getTarget = evt.target; // 獲取DOM事件目標
09  ......
10}  

button的值


button 數值表
數值IEDOM
0未按下按鍵左鍵
1左鍵中鍵(滑輪)
2右鍵右鍵
3同時按下左右鍵不支援,undefined
4中鍵(滑輪)不支援,undefined
5同時按下左中鍵不支援,undefined
6同時按下右中鍵不支援,undefined
7同時按下左中右鍵不支援,undefined

鍵盤事件

鍵盤事件重要的是「使用者按了什麼鍵?」IE沒有charCode屬性,而keyCode只有在keydown與keyup事件觸發時才會與標準DOM的keyCode相同,在keypress事件中等於charCode。

1if (window.event) {
2  evt = window.event;
3  evt.charCode=(evt.type == "keypress") ? evt.keyCode : 0;
4  ...
5}  

通常不採用keyCode是因為它表示鍵盤按鍵,而不是輸出字元,例如輸出"a"和"A"時,keyCode的值是相等的,charCode則以字元為區分,另外,在keypress事件中,DOM的keyCode值始終為0。

JavaScript Event(事件) - Bubble Event(氣泡事件)

Bubble Event(氣泡事件)

圖一:DOM樹
圖一:DOM樹

上面的架構圖,每一個tag都擁有onclick事件,如果在最下層的按鈕button觸發了onclick事件,事件不只在此tag觸發,還會向上傳遞,接著form觸發onclick事件,再來是body也一樣會觸發onclick事件。

JavaScript Event(事件) - Event Object(事件物件)

Event Object(事件物件)

在瀏覽器中的事件都是以「物件」的型式存在,但IE與標準DOM瀏覽器之間在取事件物件上有差別。


IE 事件物件

事件物件是window物件的一個屬性event,例如,

1getP.onclick = function(){
2  //取得事件物件
3  var evt = window.event;
4}

DOM瀏覽器事件物件

事件物件須使用唯一參數傳給事件管理函數,例如,

1getP.onclick = function(evt){...}

相容性新增事件監聽

在處理IE與DOM事件相容性時,通常會這樣做,例如,

1function (evt) {
2 // 透過測試window.event來判斷是否是IE來決定事件物件的建立
3 if (window.event)
4   evt = window.event;
5   ...
6 else
7   // DOM事件
8}

取消事件

事件 → 自訂事件處理 → Browser預設事件處理,取消事件處理函數,只需設成null,例如,

1// 取消document的click事件
2document.onclick = null;
3// 取消mybutton物件的click事件
4document.form1.mybutton.onclick = null;

在自訂事件處理函數取消事件,只需傳回false即可。

1return false;

JavaScript Event(事件) - 事件監聽(EventListener)

Event Listener(事件監聽)

頁面中的事件都需要一個函數來回應,這類函數通常稱為「事件處理函數,事件處理函式(event handler)」,另一方面,這些函數都在即時監聽著是否有事件發生,所以也稱「事件監聽函數(event listener)。

將事件當成HTML標籤屬性,例如,

1<input type="button" value="訊息" onclick="showInfo()" />

將事件當成Javascript的屬性,例如,

1// 除了要傳遞參數,否則處理函數不用()符號
2document.form1.mybutton.onclick = "showInfo";

事件是由window或document等上層物件所觸發,只需設定物件的事件屬性,例如,

1document.onclick = "showInfo";

考慮結構與行為分離,例如,匿名函數,

1// 在視窗完成載入後,
2window.onload=function(){
3  // 取得元素id屬性為myP元素的控制權
4  var getP=document.getElementById("myP");
5  // 設定myP元素的onclick事件
6  getP.onclick=function(){
7    alert("click");
8  }
9}

IE事件監聽

在IE中,每個元素都有兩個方法來處理事件的監聽,例如,

1// 新增監聽函數
2[Object].attachEvent("event handler",fnHandler);
3// 刪除監聽函數
4[Object].detachEvent("event handler",fnHandler);
event handler為事件的名稱,如onclick,onload…;fnHandler為監聽函數名稱,這個函數不需加上括弧的執行結果。例如,

1getP.attachEvent("onclick",fnClick1);
2getP.attachEvent("onclick",fnClick2);

在IE7/8中,兩個函數的呼叫順序是fnClick2 → fnClick1,但兩者都會被執行。例如,我們在fnClick2最後加上detachEvent來解除fnClick1,但fnClick1還是會被執行;但如果Click第二次,因為fnClick1已經被detachEvent解除,所以只會執行fnClick2。

IE不會執行標準DOM的addEventListener/removeEventListener方法

標準DOM事件監聽

每個元素都有兩個方法來處理事件的監聽,建議使用標準DOM方法來撰寫監聽事件,例如,

1// 新增監聽函數
2[Object].addEventListener("event name",fnHandler, bCapture);
3// 刪除監聽函數
4[Object].removeEventListener("event name",fnHandler, bCapture);

event name是click、mousemove…沒有on(注意,和IE不一樣),bCapture:false為冒泡。例如,

1getP.addEventListener("click",fnClick1,false);
2getP.addEventListener("click",fnClick2,false);

DOM的執行順序為fnClick1 → fnClick2,而且是fnClick1執行完成後才會從行fnClick2。所以如果我們在fnClick1中最後加上removeEventListener來解除fnClick2,那fnClick2就不會執行。

JavaScript Event(事件) - Mouse, Keyboard, HTML Event

Mouse Event(滑鼠事件)

透過event.type來取得的事件名稱沒有on開頭

JavaScript Mouse Event(滑鼠事件)
名稱說明
onmousedown按下mouse按鍵,不論左右鍵
onmousemove移動mouse
onmouseoutmouse指標離開HTML標籤
onmouseovermouse指標進入HTML標籤
onmouseup放開mouse按鍵
onclick按一下mouse左鍵
ondblclick按二下mouse左鍵

按一下Mouse共會引發三個事件,mousedown → mouseup → click。

隱藏Mouse右鍵選單

Mouse右鍵會觸發一個contextmenu事件,即選單事件,我們只要在contextmenu事件裡取消此事件產生動作,即可隱藏右鍵選單。

1function blockMenu(Evt){
2  // window.event 是IE才有的物件
3  if(window.event){
4    Evt = window.event;
5    Evt.returnValue = false;//取消IE預設事件
6  }else
7    Evt.preventDefault();//取消DOM預設事件
8}
9document.oncontextmenu = blockMenu;

Keyboard Event(鍵盤事件)

透過event.type來取得的事件名稱沒有on開頭。

JavaScript Keyboard Event(鍵盤事件)
名稱說明
onkeydown按下鍵盤按鍵
onkeypress在keydown與keyup之間的事件,或是按著不放時所觸發
onkeyup放開鍵盤按鍵

HTML Event(HTML事件)

透過event.type來取得的事件名稱沒有on開頭。

JavaScript HTML Event(HTML事件)
名稱說明
onload頁面完全載入後在window物件上觸發,圖片載入完成後在其上觸發
onunload頁面完全卸載後在window物件上觸發,圖片卸載完成後在其上觸發
onabort放棄圖片載入
onblur離開擁有處理權的物件
onchange在取得處理權後,更改過文字方塊的內容,離開文字方塊時觸發
onerror腳本出錯時在window物件上觸發,圖片無法載入時在其上觸發
onfocus指定物件擁有處理權
onreset重設表單
onselect選擇網頁內容
onsubmit送出表單

就我們在撰寫網頁相關程式碼中,又以onblur、onchange、onfocus、onreset、onselect、onsubmit這幾個表單事件(form event)最為重要,除了UI的程式碼外,表單是我們很重要與使用者互動的來源,一個良好的表單互動就能簡單讓您的網站有很大的加分的效果,所以這幾個事件的處理份量會比較重一些。

JavaScript-DHTML物件模型-Document物件(四)-CSS

CSS - 存取標籤物件的style屬性


1ele.style.fontSize=12px;

CSS樣式屬性與style屬性差異


CSS樣式屬性,例如,

  • font-size
  • font-family
  • background-color
  • background-image


style屬性中,設定CSS樣式,例如,

  • fontSize
  • fontFamily
  • backgroundColor
  • backgroundImage

style需要把中間的「-」符號刪除,然後將後面的英文字頭改為大寫。

JavaScript-DHTML物件模型-Document物件(三)

取得文件元素

此小節裡的三個方法可以說是JavaScript最重要的三個方法,原因是,當我們想要對頁面上任何元素進行操作前,必須先取得此元素的控制權,有了控制權我們才有辦法對元素本身進行操控。

JavaScript 取得文件元素
名稱說明
getElementById()依HTML tag的id屬性取得指定的元素
getElementByName()依HTML tag的name屬性取得指定的元素
getElementByTagName()傳回一個包含某個相同標籤名稱的元素NodeList(Array)

1<h2 id="header">取得文件元素</h2>

1// 取得元素id屬性為header的元素
2ele = document.getElementById("header");

1// 取得元素name屬性為input的視素
2ele = document.getElementsByName("input");

1// 取得元素標籤名稱為li的元素,回傳Array()
2ele = document.getElementByTagName("li");
3alert( ele.length +', '+ ele[0].tagName +', '+ele[3].childNodes[0].nodeValue);

ele代表元素。

tagName:tag名稱。length:同名tag有多少個。

存取HTML標籤(tags)的內容和屬性 - innerHTML

由getElementById / getElementByName 取得文件元素後,就可以使用innerHTML來存取標籤物件內的子標籤和內容。一般都是用來插入HTML標籤。例如在空的<div>、<span>、<p>插入所需標籤,來顯示動態效果。innerText / outerHTML / outerText 除IE外,其他Browser相容性不佳,不建議使用。

1ele.innerHTML = '<span>動態由JavaScript所插入的span元素</span>';

標籤屬性


1// 取得<p>屬性align的屬性值
2eleAttr = document.getElementById("P").align;
3/* IE可用以下方法,但不建議使用。
4 * eleAttr = document.all.tags("P").item(0).align;
5 */

JavaScript HTML標籤屬性存取
名稱說明範例
getAttribute(attr)取得傳入attr屬性值ele.getAttribute("align");
setAttribute(attr,value)將value值設定給attr屬性ele.setAttribute("align","center");
removeAttribute(attr)刪除傳入的attr屬性ele.removeAttribute("align");

標籤尺寸與位置


JavaScript HTML標籤尺寸與位置
名稱說明
offsetLeft標籤物件距離左方邊界的距離
offsetTop標籤物件距離上方邊界的距離
offsetHeight標籤物件的高
offsetWidth標籤物件的寬
offsetParent取得標籤物件的上一層物件

scrollIntoView方法

scrollIntoView("true|false"):如果Broswer看不到標籤物件,自動捲動視窗顯示標籤物件,例如,

1ele.scrollIntoView(true);

JavaScript-DHTML物件模型-Document物件(二)-Collection集合物件

Collection集合物件


JavaScript Collection集合物件
名稱說明
document.all取得HTML文件中所有Tag Object
document.all(index).tagName取得指定index的Tag Name
document.all(index).SourceIndex取得指定index在HTML中出現的順序(IE only)
document.all.tags("P").length使用tags()方法篩選出指定標籤的物件集合,其中HTML標籤名稱需使用大寫字母

document.all在IE使用沒有問題,但在其他Browser相容性不佳,建議使用getElementById("id")或getElementByName("Name")來取得所需的資訊 (使用getElementById/ByName替代document.all)。

JavaScript-DHTML物件模型-Document物件(一)

Document物件屬性


JavaScript Document物件屬性
名稱說明
domain傳回伺服器的網域名稱
referrer傳回URI字串,指出連結此網頁的位置
title傳回和設定title元素,即<title>
URL傳回網頁的URL字串

開啟與寫入文件


JavaScript 開啟與寫入文件
名稱說明
write();向文件寫入HTML、文字、JavaScript…
writeln();同write()方法,但最後會包含換行符號
open("MIME Type","replace");清除目前的文件內容,然後使用write()或writeln()重新輸出文件的內容
MIMEType:text/html
replace可以取代歷存記錄
最後使用document.close()方法,顯示write()或writeln()輸出的文件內容
close();

Cookies


1document.cookie = "name=value;expires=date;path=pname;domain=dname;secure";

JavaScript Cookies
名稱說明
name(必要)cookie名稱
expirescookie有效期限,為GMT格式。例如:exDate.toGMTString();
domain伺服器網域名稱
path在domain下的路徑名稱
secure如設定,表示cookie需在保密下才能傳送

domain屬性是為了分別cookie屬於那個網站所建立;path屬性可進一步區別同一網站不同網頁所建立的cookie。

1getCookies = document.cookie;

取得cookie屬性的值;kname1=kvalue1;kname2=kvalue2...,為名稱/值的對應。我們必須自行寫Code存取Cookie的資料。

JavaScript-DHTML物件模型-Location物件

Location物件

這裡我們要先了解網址的結構是如何組成的,舉例一:

http://www.microsoft.com:80/default.aspx#user

網址的結構(一)
名稱說明
hrefhttp://www.microsoft.com:80/default.aspx#user
hostnamewww.microsoft.com
port80
hash#user

舉例二:

http://www.microsoft.com:80/default.aspx?user=kkbruce

網址的結構(二)
名稱說明
protocolhttp:
hostwww.microsoft.com:80
pathnamedefault.aspx
search?user=kkbruce

Location物件屬性


JavaScript Location物件屬性
名稱說明
hostname伺服器"網域名稱"或"IP位址"
hrefURL網址
hostURL的hostname:port
hashRUL的#符號後的部份
port通訊埠號,WWW預設80埠號,FTP預設21埠號
pathname網頁檔案的名稱和路徑
searchURL的?符號後的部份
Protocal使用的通訊協定,常用有http://與https://

轉向


1// window.location.href='http://...';
2location.href="http://...";

可使用「上一頁」來回到上一頁。

1location.replace(url);

轉向url的網址,同href屬性,但不能使用「上一頁」來回到上一頁。

重新載入


1location.reload(true);

重新載入現在開啟的HTML文件,如同Browser的"重新整理"鈕。

JavaScript-DHTML物件模型-History物件

History物件


JavaScript History物件
名稱說明
length傳回history物件的歷史記錄數
back();回到上一頁
forward();移到下一頁
go(num);移到上或下幾頁,num大於0為下幾頁,小於0為上幾頁(常用"-1"代表上一頁)

JavaScript-DHTML物件模型-Navigator物件

取得Browser和系統資源資訊


JavaScript Navigator物件
名稱說明
appCodeName傳回Browser的程式碼名稱
appMinorVersion傳回Browser的次版本(IE)
appName傳回Browser的名稱
appVersion傳回Browser版本和作業系統名稱
browserLanguage傳回目前Browser使用的語系(IE)
cookieEnable傳回Browser是否支援cookie
cpuClass傳回CPU的類型(IE)
onLine傳回目前系統是否在線上
platform傳回作業系統的平台
systemLanguage傳回系統預設的語系(IE)
userAgent傳回HTTP通訊協定資料user-agent
userLanguage傳回目前使用者所使用的語系(IE)

JavaScript-DHTML物件模型-Window物件-Screen物件

Screen物件


JavaScript Screen物件
名稱說明
heightMonitor解析度的高度
widthMonitor解析度的寬度
availHeightMonitor視野的高度
availWidthMonitor視野的寬度
colorDepthMonitor的色彩數

取得座標


JavaScript Screen物件之取得座標
名稱說明
screenLeft(IE)/screenX傳回左上方邊界的座標
screenTop(IE)/screenY傳回上方邊界的座標

調整與移動視窗


JavaScript Screen物件之調整與移動視窗
名稱說明
moveTo(x,y);將Browser移到座標x和y位置
moveBy(offsetX,offsetY);將Browser從目前位置,移動x,y的位移量,位移量大於0表示向右和向下移動,小於0表示向左和向上移動
resizeTo(width,height);將Browser視窗調整為width和height的尺寸
resizeBy(offsetX,offsetY);將Browser視窗放大或縮小,x,y大於0為放大,小於0縮小

內容捲動


JavaScript 視窗內容捲動
名稱說明
scroll(x,y);捲動視窗內容到指定的位置
scrollTo(x,y);捲動視窗內容到指定的位置
scrollBy(offsetX,offsetY);從目前視窗內容的位置,捲動參數的位移量

JavaScript-DHTML物件模型-Window物件- open,close,對話方塊

open視窗


1window.open(url,name,features,replace);

features


Open函式 features屬性
名稱說明
left/screenX (*)設定Browser左上角X座標,單位px
top/screenY (*)設定Browser左上角Y座標,單位px
height/innerHeight (*)設定Browser視窗的高,單位px,最小100
width/innerWidth (*)設定Browser視窗的寬,單位px,最小100
directories顯示Browser連結列(無屬性值)
location是否顯示Browser網址欄
menubar是否顯示Browser功能表
resizble是否允許調整視窗的尺寸
scrollbars是否顯示垂直與水平的動軸
status是否顯示Browser下方的狀態列
titlebar是否顯示Browser上方的標題列
toolbar是否顯示Browser的工具列

(*) left,top,height,width為IE使用,screenX/Y,innerHeight/Width為MF使用,建議相對應的屬性(例:left/screenX)都設定。

replace

只適用IE。

windows.open()範例


1window.open("http://blog.kkbruce.net","_blank","height=300,width=400,innerHeight=300,innerWidth=400");

在逗號或等號前後不能有空格。

close視窗


1window.close();

對話方塊

1alert(message);

警告訊息。

1confirm(message);

確認方塊,true按確定鈕,false為按取消鈕。

1prompt(message,value);

輸入文字對話方塊,message為訊息內容,value為預設值。

列印

1window.print();

JavaScript-DHTML物件模型-Window物件-計時器

只會執行一次

  • setTimeout(express,time)
    當time所設定的時間到達時,執行express運算式,time為千分之一秒
  • clearTimeout()
    停止setTimeout方法啟動的計時器

週期執行

  • setInterval(express,time)
    以time時間週期性地執行express運算式
  • clearInterval()
    停止setInterval方法啟動的計時器

JavaScript-DHTML物件模型-Window物件-Browser狀態列

Browser狀態列

  • defaultStatus
    設定和取得Browser程式狀態列的預設訊息文字
  • status
    設定和取得Browser程式狀態列的訊息文字

JavaScript 流程控制 - function函式

function函式組成

1function name(){
2  statement
3}

(arguments),括號內可有一或多個參數。當資料做為參數而傳入函式,它的行動就像函式內已初始化的區域參數;雖然函式參數的行為很像函式內的區域變數,在函式內改變參數,卻不會影響函式外的任何事物。

function函式回傳資料

使用return關鍵字來回傳資料。

1function name(){
2  statement
3  return value;
4}

函式只要碰到return後立刻結束。技巧:在流程控制上,我們也可以使用沒有回傳值的return來結束函式。return不只回傳資料,也負責結束函式。

1function name(){
2  statement
3  return;
4}

所以函式的回傳值會取代了函式的呼叫。例如,

1// 假設有一計算價錢的函式cale(),參數number傳入數量,會得到金額
2totalPrice = cale(number);
3// cale()函式計算後會return price;
4// 最後會以回傳值取代函式的呼叫,可以看成:totalPrice = price; 來得到最終的結果

function is data

函式實字(function literal)

當函式本體單獨出現,沒有名稱。把函式本體看成值,把函式名稱看為變數名稱。

1var showMsg = function(Msg){
2  alert(Msg);
3}

showMsg:函式名稱(函式參考),即變數名稱。

function(){...}:把function(函式實字)當成變數值。

函式實字讓函式能像變數般操縱,例如,

1var myMessage = showMsg;

指派showMsg()函式給變數myMessage。以上程式碼表示函式也能利用變數語法而建立,甚至組成元件也相同。指派函式名稱給另一個變數,就是為了讓變數可以取用函式本體。

1alert(myMessage("Hello World!"));

function reference, 函式參考

呼叫showMsg()與myMessage的結果相同,因為兩個函式最後都參考(reference)了相同的原始碼,因此函式名稱也稱函式參考(function reference)。

函式其實只是「值」參考到函式本體的變數。

函式參考與函式呼叫

函式參考只會單獨出現,例如,

1var myMessage = showMsg;

對myMessage指派函式參考。函式呼叫則必定後隨括號( ),很多時候還附有參數,例如,

1myMessage("Hello World!");

呼叫myMessage()與showMsg()相同。

參考重要性

函式參考不像一般變數,變數的資料儲存成記憶體的某個區段,函式則儲存對原始碼的參考,函式變數的值不是原始碼本身,而是指向儲存原始碼的記憶體位置的指標,函式使用參考,而非實際的值,比起儲存多份函式碼的複本,參考有效率多了。

JavaScript 流程控制 - break與continue關鍵字

break與continue關鍵字

  • break; 終止此迴圈的執行,離開此迴圈
  • continue; 終此這一次的迴圈的執行,執行下一輪的迴圈;或停止continue之後所有迴圈程式,回到迴圈開頭(for/while/do)

JavaScript 流程控制 - 用with建立物件程式碼區塊

with 與 for ~ in差異

for ~ in主要顯示物件的所有屬性,with敘述能夠針對物件(Object)建立一個程式區塊。

1with (ObjectName){
2   ...
3}

例如:

1// 建立一個名片物件
2var Card = new Object();
3with (Card){
4  // 新增property
5  name = "Bruce";
6  age = 33;
7  birthday = new Date("2012/2/15");
8  document.write("姓名:"+name+",年齡:"+age+",生日:"+birthday);
9}

JavaScript 流程控制 - 迴圈控制

for迴圈控制

適合重複動作已知次數。

組成:
  1. 初始化(initialization)
  2. 條件句(test condition)
  3. 動作(action)
  4. 更新(update)

01// 執行順序為[1][2][3][4]-[2][3][4]-[2][3][4]-...
02for ([1]initialization; [2]condition; [4]post loop expression)
03  [3]statement
04 
05/*
06for (1;2;4)
07  3
08   
09
10 
11for (初始化;條件句;更新)
12  動作
13*/

最佳化for迴圈控制

1for (var i = 0; i < a.length; i++) {
2 a[i]=i;
3}

這樣不是很有效率,因為每迴圈一次就會查詢一次 length 屬性。(但所有JavaScript的教科書都這樣教!)比較好的寫法:

1for (var i = 0, len = a.length; i < len; i++) {
2 a[i]=i;
3}

初始化時宣告兩個變數,把length屬性值存放到變數中。更棒的寫法:

1for (var i = 0, item; item = a[i]; i++) {
2 處理item
3}

for 迴圈中間指定變數值的部分會被測試是否為「真的」(truthy):如果成功了,迴圈便會繼續。由於 i 每次都會加一,陣列內的每個項目會被照順序指定到變數 item。當偵測到「假的」(falsy) 項目時(如 undefined)迴圈便會停止。注意:這個小技巧只該用在你確定不會含有「假的」值的陣列(比如說一陣列的物件或 DOM 節點)。假如你在可能含有 0 的數字資料或可能含有空字串的字串資料上做迴圈,最好還是用 i, j 的方式。

while / do ~ while迴圈控制

while迴圈本身沒有更新條件程式,必須自建條件更新條件(update)。
1while (condition)
2  // 需含更新條件
3  statement
組成:
  1. 檢測條件(test condition)
  2. 行動(action)

1do
2  statement
3while (condition)

先執行一次完整程式碼(statement),再進行檢測條件(condition)。

for ~ in迴圈控制

通常用來列舉物件的屬性。
1for (property in expression)
2  statement

for / while 迴圈控制討論

while迴圈能做到任何for迴圈的任務,反之亦然。

1for (init; test; update){
2  action;
3}

1init;
2while (test) {
3  action;
4  update;
5}

JavaScript 流程控制 - 條件控制

if條件控制

if範例

1if (condition)
2  statement

1if (true/false test)
2  Do something;

if/else範例

1if (condition)
2  // true
3  statement
4else
5  // false
6  statement

1if (condition)
2  statement
3else if (condition)
4 statement
5else
6  statement

可產生無限個 if / else if。

?:範例

「條件運算子」可用來指定變數的值,如同 if / else,在變數值需要二選一時非常實用

1$Var = (condition)? "Value1" : "Value2";

()內為條件,true指定?後的內容給變數,false指定:後的內容給變數。

1Hours = (inputHour>=12)? "PM" : "AM";
2 
3//原if/else程式碼
4/*
5if (inputHour >=12)
6  Hours = "PM";
7else
8  Hours = "AM";
9*/

switch條件控制

01switch (expression) {
02  case value:
03    statement
04    break;
05  case value:
06    statement
07    break;
08  ...
09  default:
10    statement
11}

(condition)最終的結果只能為true或false。(expression)相當於資料,case等於「==」邏輯運算子,value等於要比較的值,用說的:(expression)資料 == value嗎?是就執行break前的程式區塊(一段一段case比較),如果都不是請執行default程式碼。

JavaScript Object - 共用屬性與方法

共用屬性與方法

JavaScript 物件共用屬性
名稱說明
constructorjavascript物件的constructor屬性可以取得建立物件副本使用的建構函數名稱(除Global和Math都支援)

範例:檢查物件的建構函數是否為String()


1var test = new String();
2if (test.constructor == String){
3 // Do something ...
4}

JavaScript 物件共用方法
名稱說明
toString()傳回物件的內容,傳回值為字串。例如,object.toString();

依物件型別不同,會回傳不同字串。

JavaScript toString()回傳值
名稱說明
Array將陣列元素轉換成「,」符號分隔的字串
Booleantrue傳回字串"true",false傳回字串"false"
Date傳回日期和時間的字串
Error傳回錯誤息訊的字串
Function傳回字串格式"function name() {...}",其中name為呼叫toString方法的函數名稱
Number傳回數字字串
String傳回String物件的內容

範例:數值轉字串,同時進制轉換


1var a=15; // Number
2a.toString(8); //8代表8進制
3a.toString(16); //16代表16進制

JavaScript 物件共用方法
名稱說明
valueOf()傳回物件值(Math,Error不支援),例如:object.valueOf();


JavaScript valueOf()回傳值
名稱說明
Array將陣列元素轉換成以「,」符號分隔的字串,如同Array.toString()和Array.join()方法
Boolean傳回布林值
Date傳回前晚到現在的秒數,以千分之一秒為單位
Function傳回函數的本身
Number傳回數字
Object傳回物件本身
String傳回字串