首頁 > web前端 > js教程 > JavaScript之引用型別介紹_基礎知識

JavaScript之引用型別介紹_基礎知識

WBOY
發布: 2016-05-16 17:50:59
原創
985 人瀏覽過

Object型別
  Object型別是JavaScript中使用最多的一種型別。雖然Object的實例不具備多少功能,但對於在應用程式中儲存和傳輸資料而言,它確實是非常理想的選擇。

  建立Object實例的方式有兩種,第一種是使用new操作子後面接著Object建構子。

複製程式碼 程式碼如下:

var person = new Object(); .name = "tt";
person.age = 12;

  另一種方式是使用物件字面量表示法。

複製程式碼 程式碼如下:
var person = {
name : 'tt' ,
age : 12
}

  另外,使用物件字面量語法時,如果留空其花括號,則可以定義值包含預設屬性和方法的物件。

var person = {}; //與new Object()相同
person.name = "tt";
person.age = 12;

  雖然可以使用前面介紹的任何一種方法來定義對象,但開發人員更青睞第二種方法(對象字面量語法),因為這種語法要求的程式碼量少,而且能給人封裝資料的感覺。實際上,物件字面量也是向函數傳遞大量可選參數的首選方式,例如:

複製程式碼 程式碼如下:
function showInfo(args)
{
if(args.name != undefined)
{
alert(args.name); if(args.age != undefined)
{
alert(args.age);
}
}

showInfo({
name:'name',
showInfo({
name:'name',
age:12
});

showInfo({name:'name'});

 一般來說,存取物件屬性時所使用的都是點表示法,這也是許多物件導向語言中通用的語法。不過,在JavaScript也可以使用方括號表示法來存取物件的屬性。例如:

複製程式碼 程式碼如下:
alert(person.name);


alert(person.name);
alert(person['name']);

  從功能上看,這兩種存取物件屬性的方法沒有任何區別。但方括號語法的主要優點是可以透過變數來存取屬性。 複製程式碼
程式碼如下:


var propertyName = 'name';
alert( person[propertyName]);


  通常,除非必須使用變數來存取屬性,否則我們建議使用點表示法。
Array型

  JavaScript中的陣列與其他多數語言中的陣列有著相當大的差異。雖然JavaScript數組與其他語言中的數組都是資料的有序列表,但與其他語言不同的是,JavaScript數組的每一項可以保持任何類型的資料。也就是說,可以用陣列的第一個位置來保存字串,用第二個位置來保存數值,用第三個位置來保存物件。而且,JavaScript數組的大小是可以動態調整的,即可以隨著資料的添加自動增長以容納新增資料。
  建立陣列的基本方式有兩種。第一種是使用Array建構函式。 複製程式碼
程式碼如下:


var colors1 = new Array(>
var colors1 = new Array(>

var colors1 = new Array(>
var colors1 = new Array(>); colors2 = new Array(20); var colors3 = new Array('red','blue','yellow');   建立陣列的第二種基本方式是使用陣列字面量表示法。


複製程式碼

程式碼如下:
var colors1 = [] var colors1 = [] ['red','blue','yellow'];
  在讀取和設定數組的值時,要使用方括號並提供相應值的基於0的數字索引。 複製程式碼 程式碼如下:

var colors = ['red','blue','yellow']; //定義一個字串陣列
alert(colors[0]); //顯示第一項
colors[2] = 'green'; //修改第三項
colors[3] = 'black'; //新增第四項

  數組的長度保存在其length屬性中,這個屬性總是會回傳0或更大的值。
複製程式碼 程式碼如下:

var colors = ['red','blue', 'yellow'];
var names = [];
alert(colors.length); //3
alert(names.length); //0

  數組數組的length屬性很有特色——它不是唯讀的。因此,透過設定這個屬性,可以從陣列的末端移除項目或想數組中新增項目。
複製程式碼 程式碼如下:

var colors = ['red','blue', 'yellow'];
colors.length = 2;
alert(colors[2]); //undefined

  這個例子中的陣列colors一開始有3個值。將其length屬性設為2會移除最後一項,結果再訪問colors[2]就會顯示undefined了。

  利用length屬性也可以方便地在陣列末尾新增項目。
複製程式碼 程式碼如下:

var colors = ['red','blue', 'yellow'];
colors[colors.length] = 'green'; //在位置3加上一種顏色
colors[colors.length] = 'black'; //再在位置4加一種顏色

  由於陣列最後一項的索引總是length-1,因此下一個新項目的位置就是length。

轉換方法

所有物件都具有toLocaleString()、toString()和valueOf()方法。其中,呼叫陣列的toString()和valueOf()方法會傳回相同的值,也就是由陣列中每個值的字串形成拼接而成的一個以逗號分隔的字串。實際上,為了建立這個字串會呼叫數組每一項的toString()方法。
複製程式碼 程式碼如下:

var colors = ['red','blue', 'yellow'];
alert(colors.toString()); //red,blue,yellow
alert(colors.valueOf()); //red,blue,yellow
alert(colors) ; //red,blue,yellow

  我們首先明確地呼叫了toString()和valueOf()方法,以便傳回陣列的字串表示,每個值的字串表示拼接成了一個字串,中間以逗號分隔。最後一行程式碼直接將陣列傳遞給了alert()。由於alert()要接收字串參數,所有它會在後台呼叫toString()方法,由此會得到與直接呼叫toString()方法相同的結果。

  另外,toLocaleString()方法經常也會傳回與toString()和valueOf()方法相同的值,但也不總是如此。當呼叫陣列的toLocaleString()方法時,它也會建立一個陣列值的以逗號分隔的字串。而與前兩個方法唯一的不同之處在於,這次為了取得每一項的值,呼叫的是每一項的toLocaleString()方法,而不是toString()方法。例如:
複製程式碼 程式碼如下:

var person1 = {
(){
return "person1 : toLocaleString";
},
toString : function(){
return "person1 : toString";
}
}
var
var person2 = {
toLocaleString : function(){
return "person2 : toLocaleString";
},
toString : function(){
return "person2 : toString";
};
var people = [person1,person2];
alert(people); //person1 : toString,person2 : toString
alert(people.toString()); //person1 : toString,person2 : toString
alert(people.toLocaleString()); //person1 : toLocaleString,person2 : toLocaleString

  數組繼承的toLocaleString()、OLocaleString()、Ovalue ,在預設情況下都會以逗號分隔的字串的形式傳回數組項。而如果使用join()方法,則可以使用不同的分隔符號來建構這個字串。
複製程式碼 程式碼如下:

var colors = ['red','blue','yellow'];
alert(colors.join(',')); //red,blue,yellow
alert( colors.join('||')); //red||blue||yellow

  注意:如果數組中的某一項的值是null或undefined,那麼該值在join ()、toString()、toLocaleString()和valueOf()方法傳回的結果以空字串表示。

  棧方法


JavScript數組也提供了一種讓數組的行為類似於其他資料結構的方法。具體來說,數組可以表現得就像堆疊一樣,後者是一種可以限制插入和刪除項目的資料結構。棧是一種後進先出後進先出的資料結構。而棧中項的插入(叫做推入)和移除(叫做彈出),只發生在一個位置-棧的頂端。 JavaScript提供了push()和pop()方法,以便實作類似的堆疊行為。

  push()方法可以接收任意數量的參數,把它們逐個加到數組末尾,並返回修改後數組的長度。而pop()方法則從陣列結尾移除最後一項,減少陣列的length值,然後傳回移除的項。
複製程式碼 程式碼如下:

var colors = new Array(>

var colors = new Array(); //建立一個); //陣列
var count = colors.push('red','blue'); //推入兩個項目
alert(count); //2
count = colors.push('yellow') ; //再推入一項
alert(count); //3
var item = colors.pop(); //取得最後一項
alert(item); //yellow
alert(colors.length); //2

  
佇列方法


  隊列資料結構的存取規則是先出。佇列在清單的末端新增項,從清單的前端移除項目。由於push()是向陣列末端新增項目的方法,因此要模擬佇列只需一個從陣列前端取得項目的方法。實現這一操作的數組方法就是shift(),它能夠移除數組中的第一個項並返回該項,同時將數組長度減1。結合使用shift()和push()方法,可以像使用隊列一樣使用陣列:
複製程式碼
程式碼如下:


var colors = new Array(); //建立一個陣列
var count = colors.push('red','blue'); //推入兩項
alert(count); //2
count = colors.push('yellow'); //再推入一項
alert(count); //3
var item = colors.shift (); //取得第一項
alert(item); //red
alert(colors.length); //2


  JavaScript也為陣列提供了一個unshift ()方法。顧名思義,unshift()與shift()的用途相反:它能在數組前端添加任意個項並返回新數組的長度。因此,同時使用unshift()和pop()方法,可以從反方向來模擬隊列,即在數組的前端添加項,從數組的末端移除項,例如:
複製程式碼
程式碼如下:


var colors = new Array(); //建立一個陣列
var count = colors .unshift('red','blue'); //推入兩個項目
alert(count); //2
count = colors.unshift('yellow'); //再推入一項
alert(count); //3
var item = colors.pop(); //取得第一項
alert(item); //blue
alert(colors.length); //2


  注意:IE對JavaScript的實作中存在一個偏差,其unshift()方法總是傳回undefined而不是陣列的新長度。   
重排序方法

  數組中已經存在兩個可以直接用來重新排序的方法:reverse()和sort(),reverse()方法會反轉數組項的順序。 複製程式碼
程式碼如下:


var values = [1,2,33,4,4, 5];
values.reverse();
alert(values); //5,4,3,2,1

  在預設情況下,sort()方法按升序排列數組項-即最小的值位於最前面,最大的值排在最後面。為了實現排序,sort()方法會呼叫每個陣列項目的toString()轉型方法,然後比較得到的字串,以確定如何排序。即使陣列中的每一項都是數值,sort()方法比較的也是字串,如下圖: 複製程式碼
程式碼如下:


var values = [0,1,5,10,15];
values.sort();
alert(values); //0,1 ,10,15,5
  可見,即使例子中值的順序沒有問題,但sort()方法也會根據測試字串的結果改變原來的順序。因為數值5雖然小於10,但在進行字串比較時,「10」則位於「5」的前面。因此sort()方法可以接收一個比較函數作為參數,以便我們指定哪個值位於哪個值的前面。

複製程式碼 程式碼如下:

function compare(value1,value. 🎜>if(value1 return 1;
} else if(value1 > value2){
return -1;
} else{
return 0;
}
var values = [0,1,5,10,15];
values.sort(compare);
alert(values); //15,10,5,1, 0


  對於數值類型或其valueOf()方法會傳回數值類型的物件類型,可以使用一個更簡單的比較函數。這個函數主要用第二個值來減第一個值即可。


複製程式碼 程式碼如下:
function compare(value1,>

function compare(value1,value2). value2 - value1;
}


  
操作方法
 JavaScriptScriptScript為操作數組提供了許多方法。其中,concat()方法可以基於目前數組中的所有項目建立一個新數組,如果傳遞給concat()方法的是一或多個數組,則該方法會將這些數組中的每一項都添加到結果數組中。如果傳遞的值不是數組,這些值就會被簡單地加到結果數組的末尾。

複製程式碼 程式碼如下:
var colors = ['red','green' 'blue'];
var colors2 = colors.concat('yellow',['black' , 'brown']);
alert(colors); //red,green,blue
alert( colors2); //red,green,blue,yellow,black,brown

  slice()方法能夠基於目前陣列中的一個或多個項目建立一個新陣列。 slice()方法可以接受一或兩個參數,也就是要傳回項目的起始和結束位置。在只有一個參數的情況下,slice()方法會傳回從該參數指定位置開始到目前陣列末端的所有項目。如果有兩個參數,則方法傳回起始和結束位置之前的項目-但不包括結束位置的項。


複製程式碼 程式碼如下:
var colors = ['red',' green','blue','yellow','black','brown'];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
alert(colors2); //green,blue,yellow,black,brown
alert(colors3); //green,blue,yellow


  下我們來介紹splice( )方法,這個方法恐怕要算是最強大的數組方法了,splice()主要用途是向數組的中部插入項,但使用這種方法的方式則有如下3種。

  刪除-可以刪除任意數量的項,只需指定2個參數:要刪除的第一項的位置和要刪除的項數。例如,splice(0,2)會刪除陣列中的前兩項。

  插入-可以向指定位置插入任意數量的項,只需提供3個參數:起始位置、0(要刪除的項數)、要插入的項。如果要插入多個項,可以再傳入第四、第五,以致任意多個項。例如,splice(2,0,'red','green')會從目前陣列的位置2開始插入字串'red'和'green'。

  替換-可以向指定位置插入任意數量的項,且同時刪除任意數量的項,只需指定3個參數:起始位置、要刪除的項數和要插入的任意數量的項。插入的項數不必與刪除的項數相等。例如,splice(2,1,'red','green')會刪除目前陣列位置2的項,然後再從位置2開始插入字串'red'和'green'。

複製程式碼 程式碼如下:
var colors = ['red','green' 'blue'];
var removed = colors.splice(0,1); //刪除第一項
alert(colors); //green,blue
alert(removed); //red
removed = colors.splice(1,0,'yellow','black'); //從位置1開始插入兩個項目
alert(colors); //green,yellow,black,blue
alert(removed); //傳回一個空數組
removed = colors.splice(1,1,'red','brown'); //插入兩項,刪除一項
alert(colors) ; //green,red,brown,black,blue
alert(removed); //yellow



Date類型

  JavaScript中的Date類型是在早期Java中的java.util.Date類別基礎上建構的。為此,Date類型使用自UTC 1970年1月1日零時開始經過的毫秒數來保存日期。在使用這種資料儲存格式的條件下,Date類型保存的日期能夠精確到1970年1月1日之前或之後的285 616年。

  要建立一個日期對象,使用new運算元和Date建構函式即可。

var now = new Date();
  在呼叫Date建構函式而不傳遞參數的情況下,新建立的物件會自動取得目前日期和時間。如果想要根據特定的日期和時間建立日期對象,必須傳入表示該日期的毫秒數。為了簡化這個計算過程,JavaScript提供了兩個方法:Date.parse()和Date.UTC()。

  其中,Date.parse()方法接收一個表示日期的字串參數,然後嘗試根據這個字串傳回對應日期的毫秒數。 JavaScript並沒有定義Date.parse()應該支援哪種格式,因此這個方法的行為因實作而異,而且通常是因地區而異。將地區設定為美國的瀏覽器通常都接受下列日期格式:

  ● "月/日/年",如:6/13/2204

  ● "英文月名日,年",如:January 12,2004

  ● "英文星期幾英文月名日年時:分:秒時區",如:Tue May 25 2004 00:00:00 GMT-0700

  例如,要為2004年5月25日建立一個日期對象,可以使用下面的程式碼:

  var someDate = new Date(Date.parse("May 25 , 2004"))
  如果傳入Date.parse()方法的字串不能表示日期,那麼它會回傳NaN。實際上,如果直接將表示日期的字串傳遞給Date建構函數,也會在後台呼叫Date.parse()。換句話說,下面的程式碼與前面的例子是等價的:

  var someDate = new Date('May 25 , 2004');
  Date.UTC()方法同樣也回傳表示日期的毫秒數,但它與Date.parse()在建構值時使用不同的資訊。 Date.UTC()的參數分別是年份、基於0的月份(一月是0,二月是1,以此類推)。月中的哪一天(1到31)、小時數(0到23)、分鐘、秒、毫秒數。在這些參數中,只有前兩個參數(年和月)是必要的。如果沒有提供月中的天數,則假設天數為1;如果省略其他參數,則統統假設為0。
複製程式碼 代碼如下:

  //GMT時間2000年111日時
  var y2k = new Date(Date.UTC(2000, 0));
  //GMT時間2005年5月5日下午5:55:55
  var allFives = new Date。 (2005,4,5,17,55,55));
  如同模仿Date.parse()一樣,Date建構子也會模仿Date.UTC(),但有一點明顯不同:日期和時間都基於本地時區而非GMT來創建的。可以將前面的範例改寫如下:

  //本地時間2000年1月1日零時
  var y2k = new Date(2000,0);    5月5日下午5:55:55
  var allFives = new Date(2005,4,5,17,55,55);


  Date類型還有一些專門用於將日期格式化為字串的方法,這些方法如下:

  ● toDateString()——以特定於實現的格式顯示星期幾、月、日和年

  ● toTimeString()——以特定於實現的格式顯示時、分、秒和時區

  ● toLocaleDateString()——以特定於地區的格式顯示星期幾、月、日和年

  ● toLocaleTimeString()——以特定於實現的格式顯示時、分、秒

  ● toUTCString()——以特定於實現的格式完整的UTC日期

  以上這些字串格式方法的輸出也是因瀏覽器而異的,因此沒有哪一個方法能夠用來在使用者介面中顯示一致的日期資訊。

  以下是所有Date型別的方法:
方法 描述
Date() 回傳當日的日期和時間。
getDate() 從 Date 物件傳回一個月中的某一天 (1 ~ 31)。
getDay() 從 Date 物件傳回一週中的某一天 (0 ~ 6)。
getMonth() 從 Date 物件傳回月份 (0 ~ 11)。
getFullYear() 從 Date 物件以四位數字傳回年份。
getYear() 請使用 getFullYear() 方法代替。
getHours() 傳回 Date 物件的小時 (0 ~ 23)。
getMinutes() 傳回 Date 物件的分鐘 (0 ~ 59)。
getSeconds() 傳回 Date 物件的秒數 (0 ~ 59)。
getMilliseconds() 傳回 Date 物件的毫秒(0 ~ 999)。
getTime() 返回 1970 年 1 月 1 日至今的毫秒數。
getTimezoneOffset() 返回本地時間與格林威治標準時間 (GMT) 的分鐘差。
getUTCDate() 根據世界時從 Date 物件返回月中的一天 (1 ~ 31)。
getUTCDay() 根據世界時從 Date 物件返回週中的一天 (0 ~ 6)。
getUTCMonth() 根據世界時從 Date 物件返回月份 (0 ~ 11)。
getUTCFullYear() 根據世界時從 Date 物件傳回四位數的年份。
getUTCHours() 根據世界時返回 Date 物件的小時 (0 ~ 23)。
getUTCMinutes() 根據世界時返回 Date 物件的分鐘 (0 ~ 59)。
getUTCSeconds() 根據世界時傳回 Date 物件的秒鐘 (0 ~ 59)。
getUTCMilliseconds() 根據世界時傳回 Date 物件的毫秒(0 ~ 999)。
parse() 傳回1970年1月1日午夜到指定日期(字串)的毫秒數。
setDate() 設定 Date 物件中月的某一天 (1 ~ 31)。
setMonth() 設定 Date 物件中月份 (0 ~ 11)。
setFullYear() 設定 Date 物件中的年份(四位數字)。
setYear() 請使用 setFullYear() 方法代替。
setHours() 設定 Date 物件中的小時 (0 ~ 23)。
setMinutes() 設定 Date 物件中的分鐘 (0 ~ 59)。
setSeconds() 設定 Date 物件中的秒鐘 (0 ~ 59)。
setMilliseconds() 設定 Date 物件中的毫秒 (0 ~ 999)。
setTime() 以毫秒設定 Date 物件。
setUTCDate() 依照世界時設定 Date 物件中月份的一天 (1 ~ 31)。
setUTCMonth() 根据世界时设置 Date 对象中的月份 (0 ~ 11)。
setUTCFullYear() 根据世界时设置 Date 对象中的年份(四位数字)。
setUTCHours() 根据世界时设置 Date 对象中的小时 (0 ~ 23)。
setUTCMinutes() 根据世界时设置 Date 对象中的分钟 (0 ~ 59)。
setUTCSeconds() 根据世界时设置 Date 对象中的秒钟 (0 ~ 59)。
setUTCMilliseconds() 根据世界时设置 Date 对象中的毫秒 (0 ~ 999)。
toSource() 返回该对象的源代码。
toString() 把 Date 对象转换为字符串。
toTimeString() 把 Date 对象的时间部分转换为字符串。
toDateString() 把 Date 对象的日期部分转换为字符串。
toGMTString() 请使用 toUTCString() 方法代替。
toUTCString() 根据世界时,把 Date 对象转换为字符串。
toLocaleString() 根据本地时间格式,把 Date 对象转换为字符串。
toLocaleTimeString() 根据本地时间格式,把 Date 对象的时间部分转换为字符串。
toLocaleDateString() 根据本地时间格式,把 Date 对象的日期部分转换为字符串。
UTC() 根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数。
valueOf() 返回 Date 对象的原始值。

Function類型

  JavaScript中什麼最有意思,我想那莫過於函數了-而有意思的根源,則在於函數實際上時物件。每個函數都是Function類型的實例,而且都與其他引用類型一樣具有屬性和方法。由於函數是對象,因此函數名稱實際上也是一個指向函數對象的指針,不會與某個函數綁定。

  函數通常是使用函數聲明語法定義的,如下面例子所示:
複製代碼 代碼如下:

function sum(num1,num2)
{
return num1 num2;
}
這與函數使用函數使用函數使用函數定義式的方式幾乎相差無幾:

複製程式碼 程式碼如下:
var sun = function(1 sun = function(11 ,num2){
return num1 num2;
};

  以上程式碼定義了變數sum並將其初始化為一個函數。 function關鍵字後面沒有函數名,這是因為使用函數表達式定義函數時,沒有必要使用函數名-透過變數sum即可引用函數。另外,也要注意函數末尾有一個分號,就像在宣告其他變數時一樣。

  最後一種定義函數的方式是使用Function建構子。 Function建構函數可以接收任意數量的參數,但最後一個參數總是會被看成是函數體,而前面的參數則枚舉出了新函數的參數。

  var sum = Function('num1','num2','return num1 num2'); //不建議使用此種方式
  由於函數名稱僅是指向函數的指針,因此函數名稱與包含物件指標的其他變數沒有什麼不同。換句話說,一個函數可能會有多個名字,例如:


複製程式碼 程式碼如下:
function sum(num1,num2)
{
return num1 num2;
}
alert(sum(10,10)); //20
var anotherSum =var anotherSum =var another. sum;
alert(anotherSum(10,10)); //20
sum = null;
alert(anotherSum(10,10)); //20

注意:使用不帶括號的函數名稱是存取函數指針,而非呼叫函數。

  函數宣告與函數表達式
  目前為止,我們一直沒有對函數宣告和函數表達式加以區別。而實際上, 解析器在向執行環境中載入資料時,對函數宣告和函數表達式並非一視同仁。解析器會率先讀取函數聲明,並使其在執行任何程式碼之前可用(可以存取);至於函數表達式,則必須等到解析器執行到它所在的程式碼行,才會真正被解釋執行。

複製程式碼 程式碼如下:
alert(sum(10,10)); >function sum(num1,num2)
{
return num1 num2;
}


  以上程式碼完全可以正常運作。因為在程式碼開始執行之前,解析器就已經讀取函數宣告並將其加入到執行環境中了。如果像下面例子所示,把上面的函數宣告改為變數初始化方式,就會在執行期間導致錯誤。


複製程式碼 程式碼如下:
alert(sum(10,10)); >var sum = function(num1,num2)
{
return num1 num2;
}


  作為值的函數
   因,所以函數也可以當作值來使用。也就是說,不僅可以像傳遞參數一樣把一個函數傳遞給另一個函數,而且可以將一個函數作為另一個函數的結果傳回。



複製程式碼 程式碼如下: function callSomeFunction(>
function {someFunction(someFunction(someFunction" 🎜>return someFunction(someArgument);
}


  這個函數接受兩個參數,第一個參數應該是一個函數,第二個參數應該是要傳遞給該函數的一個值。然後,就可以像下面的例子一樣傳遞函數了:

複製代碼 代碼如下:

function add(num)
{
return num 10;
}
var result = callSomeFunction(add,10);
alert(result); //20

  當然,可以從一個函數中返回另一個函數,而且這也是極為有用的一種技術。

複製程式碼 程式碼如下:

function createSumunction(createSumunction( 🎜>return function(num1,num2){
return num1 num2;
};
}
var sumFunction = createSumFunction();
alert(sumFunction(10,10)); /20


  函數內部屬性
  在函數內部,有兩個特殊的物件:arguments和this。其中,arguments是一個類別數組對象,包含傳入函數中的所有參數,而且可以使用length屬性來決定要傳遞進來多少個參數。



複製代碼 代碼如下:
function sayHi()
{
alert(arguments.length); //2
alert(arguments[0] ',' arguments[1]); //hello,world
}
sayHi('hello','world ');


  雖然arguments的主要用途是保存函數參數,但這個物件還有一個名叫callee的屬性,該屬性是一個指針,指向擁有這個arguments物件的函數。看下面這個很經典的階乘函數:



複製程式碼 程式碼如下:
程式碼如下:


{
if(num return 1;
} else {
return num * factorial(num-1);
}
}


  定義階乘函數一般都要用到遞歸演算法;如上面的程式碼,在函數有名字,而且名字以後也不會變的情況下,這樣定義沒有問題。但問題是這個函數的執行與函數名稱factorial緊密耦合在一起。為了消除這種緊密耦合的現象,可以像下面這樣使用arguments.callee
複製程式碼
程式碼如下:


function factorial(num)
{
if(num return 1;
} else {
return num * arguments.callee( num-1);
}
}


  在這個重寫後的factorial()函數的函數體內,沒有再引用函數名factorial。這樣,無論引用函數時使用是什麼名字,都可以保證正常完成遞歸呼叫。例如:
複製程式碼
程式碼如下:


var trueFactor = faial; >factorial = function(){
return 0;
};
alert(trueFactorial(5)); //120
alert(factorial(5)); //0


  函數內部的另一個特殊物件是this,this引用的是函資料以執行操作的物件-或者也可以說,this是函數在執行時所處的作用域(當在網頁的全局作用域中呼叫函數時,this物件引用的就是window)。看下面的例子:
程式碼如下:


windowcolor =window. 'red';
var o = {color:'blue'};

function sayColor()
{
alert(this.color);
}

sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //blue

  上面這個函數sayColor()是在全域作用域中定義的,它引用了this物件。由於在呼叫函數之前,this的值並不確定,因此this可能會在程式碼執行過程中引用不同的物件。當在全域作用域中呼叫sayColor()時,this引用的是全域物件 window;換句話說,對this.color求值會轉換成對window.color求值,於是結果就是'red'。而當把這個函數賦給物件o並呼叫o.sayColor()時,this引用的是物件o,因此對this.color求值會轉換成對o.color求值,結果就是'blue'。

  函數屬性與方法
  因為JavScript中的函數是對象,因此函數也有屬性和方法。每個函數都包含兩個屬性:length和prototype。其中,length屬性表示函數希望接收的命名參數的個數。

複製程式碼 程式碼如下:

function sayName(name)


function sayName(name)

alert(name);
}
function sayHi()
{
alert('hi');
}
alert(sayName.length); //1
alert(sayHi.length); //0


  在JavaScript中最耐人尋味的就要數prototype屬性了。對於引用類型而言,prototype是保存它們所有實例方法的真正所在。諸如toString()和valueOf()等方法其實都是保存在prototype名下,只不過是透過各自物件的實例來存取罷了。在建立自訂引用類型以及實作繼承時,prototype屬性的作用是極為重要的(這裡就不對prototype屬性做詳細介紹了)。
  每個函數包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途是在特定的作用域中呼叫函數,實際上等於設定函數體內this物件的值。首先,apply()方法接受兩個參數:一個是在其中運行函數的作用域,另一個是參數數組。其中,第二個參數可以是Array的實例,也可以是arguments物件。例如: 複製程式碼

程式碼如下:


function sum(num1,22)
{
return num1 num2;
}
function callSum1(num1,num2)
{
return sum.apply(this,arguments);
{
return sum.apply(this,arguments);
}
callSum2(num1,num2)
{
return sum.apply(this,[num1,num2]);
}
alert(callSum1(10,10)); //20
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20

複製程式碼


程式碼如下:

function callSum2(num1,num2) 🎜>return sum.call(this,num1,num2);
}
alert(callSum2(10,10)); //20
  一事實上,傳遞參數並非app ()和call()真正的用武之地;它們真正強大的地方是能夠擴充函數賴以運作的作用域。看下面的例子:
複製程式碼


程式碼如下:


windowcolor =window. 'red';
var o = {color:'blue'};

function sayColor()
{
alert(this.color);
}

sayColor(); //red
sayColor.call(this); //red sayColor.call(window); //red sayColor.call(o); //blue
  在上面的例子中,當運行sayColor.call(o)時,函數的執行環境就不一樣了,因為此時函數體內的this對象指向了o,於是結果顯示"blue"。

  注意:每個函數都有一個非標準的caller屬性,該屬性指向呼叫目前函數的函數。一般是在一個函數的內部,透過arguments.callee.caller來實現對呼叫棧的追溯。目前,IE、FireFox、Chrome都支援該屬性,但建議將該屬性用於調試目的。

內建物件
  JavaScript中有兩個內建物件:Global和Math。

 Global物件
  Global(全域)物件可以說是JavaScript中最特別的物件了,因為不管你從什麼角度來看,這個物件都是不存在的。 JavaScript中的Global物件在某種意義上是作為一個終極的「兜底兒物件」來定義的。換句話說,不屬於任何其他物件的屬性和方法,最終都是它的屬性和方法。事實上,沒有全域變數或全域函數;所有在全域作用域定義的屬性和函數,都是Global物件的屬性。諸如isNaN()、parseInt()以及parseFloat(),實際上全都是Global物件的方法,Global物件還包含其他一些方法。

  URI編碼方法
  Global物件的encodeURI()和encodeURIComponent()方法可以對URI進行編碼,以便傳送給瀏覽器。有效的URI中不能包含某些字符,例如空格。而這兩個URI編碼方法就可以對URI進行編碼,它們用特殊的UTF-8編碼替換所有無效的字符,從而讓瀏覽器能夠接受和理解。

  其中,encodeURI()主要用於整個URI(例如:http://www.test.com/test value.html),而encodeURIComponent()主要用於對URI中的某一段(例如前面URI中的test value.html)進行編碼。它們主要區別在於,encodeURI()不會對本身屬於URI的特殊字元進行編碼,例如冒號、正斜線、問好和井號;而encodeURIComponent()則會對它發現的任何非標準字元進行編碼。

複製程式碼 程式碼如下:

var uri = "http://www .test.com/test value.html#start";
//"http://www.test.com/test value.html#start"
alert(encodeURI(uri));
//"http://www.test.com/test value.html#start"
alert(encodeURIComponent(uri));

  一般来说,使用encodeURIComponent()方法的时候要比使用encodeURI()更多,因为在实践中更常见的是对查询字符串参数而不是对基础URI进行编码。

  与encodeURI()和encodeURIComponent()方法对应的两个方法分别是decodeURI()和decodeURIComponent()。其中,decodeURI()只能对encodeURI()替换的字符进行解码,同样,decodeURIComponent()只能对encodeURIComponent()替换的字符进行解码。

  eval()方法
  eval()方法大概是JavaScript中最强大的一个方法了,eval()方法就像是一个完整的JavaScript解析器,它只接受一个参数,即要执行的字符串。看下面的例子:

  eval("alert('hi')");
  这行代码的作用等价于下面这行代码:

  alert('hi');
  当解析器发现代码中调用eval()方法时,它会将传入的参数当做实际的JavaScript语句来解析,然后把执行结果插入到原位置。通过eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过eval()执行的代码可以引用在包含环境中定义的变量,例如:

var msg = 'hello world';
eval('alert(msg)'); //hello world
  可见,变量msg是在eval()调用的环境之外定义的,但其中调用的alert()仍然能够显示“hello world”。这是因为上面第二行代码最终被替换成了一行真正的代码。同样地,我们也可以在eval()调用中定义一个函数,然后再在该调用的外部代码中引用这个函数:

eval("function sayHi(){alert('hi')}");
sayHi();
  注意:能够解释代码字符串的能力非常强大,但也非常危险。因此在使用eval()时必须极为谨慎,特别是在用它执行用户输入数据的情况下。否则,可能会有恶意用户输入威胁你的站点或应用程序安全的代码(即所谓的代码注入)。

 Math对象
  与我们在JavaScript直接编写的计算功能相比,Math对象提供的计算功能执行起来要快得多。Math对象还提供了辅助完成这些计算的属性。

属性 描述
E 返回算术常量 e,即自然对数的底数(约等于2.718)。
LN2 返回 2 的自然对数(约等于0.693)。
LN10 返回 10 的自然对数(约等于2.302)。
LOG2E 返回以 2 为底的 e 的对数(约等于 1.414)。
LOG10E 返回以 10 为底的 e 的对数(约等于0.434)。
PI 返回圆周率(约等于3.14159)。
SQRT1_2 返回返回 2 的平方根的倒数(约等于 0.707)。
SQRT2 返回 2 的平方根(约等于 1.414)。

Math物件包含的方法如下:

方法 描述
abs(x) 返回数的绝对值。
acos(x) 返回数的反余弦值。
asin(x) 返回数的反正弦值。
atan(x) 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x) 返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。
ceil(x) 对数进行上舍入。
cos(x) 返回数的余弦。
exp(x) 返回 e 的指数。
floor(x) 对数进行下舍入。
log(x) 返回数的自然对数(底为e)。
max(x,y) 返回 x 和 y 中的最高值。
min(x,y) 返回 x 和 y 中的最低值。
pow(x,y) 返回 x 的 y 次幂。
random() 返回 0 ~ 1 之间的随机数。
round(x) 把数四舍五入为最接近的整数。
sin(x) 返回数的正弦。
sqrt(x) 返回数的平方根。
tan(x) 返回角的正切。
toSource() 返回该对象的源代码。
valueOf() 返回 Math 对象的原始值。
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板