引用類型的值(對象)是引用類型的一個實例。在ECMAScript中,引用類型是一種數據結構,它描述的是一類對象具有的屬性和方法。
對象是某個特定引用類型的實例,新對象是使用new操作符后跟一個構造函數來創建的。
Object類型
大多數引用類型值都是Object類型的實例,Object是ECMAScript中使用最多的一個類型。Object的實例不具備多少功能,但對於在應用程序中存儲和傳輸數據而言,是非常理想的選擇。
創建Object實例的方式有兩種:
- 第一種是使用new操作符后跟Object構造函數
var person = new Object(); person.name = "Nicholas"; person.age = 29;
- 另一種是使用對象字面量表示法,如
var person = { name : "Nicholas", //使用逗號“,”來分隔不同的屬性 age : 29 //最后一個屬性后面不能加逗號,會出錯 }; //屬性名也可使用字符串,如下 var person = { “name” : "Nicholas", “age” : 29 };
開發人員更青睞對象字面量表示法,因為這種語法的代碼量少,而且給人封裝數據的感覺。實際上,對象字面量也是向函數傳遞大量可選參數的首選方法。
一般來說,訪問對象屬性時使用的都是點表示法,JavaScript中也可以使用方括號表示法來訪問對象的屬性。如
alert(person["name"]); //"Nicholas" alert(person.name); //"Nicholas"
兩種訪問對象屬性的方法比較:
- 本質沒有任何區別。
- 方括號的有點事可以通過變量來訪問屬性,如下
var propertyName = "name"; alert(person[propertyName]); //"Nicholas"
- 如果屬性名中包含會導致語法錯誤的字符,或屬性名使用的是關鍵字或保留字,也可以使用方括號表示法。如下:
person["first name"]="Nicholas";
因為“first name”中包含一個空格,所以不能使用點表示法來訪問。屬性名中包含非字母非數字的時候可以使用方括號表示法來訪問它們。
- 通常,除非必須使用變量來訪問屬性,否則建議使用點表示法。
Array類型
ECMAScript中的數組與其他多數語言中的數組有着很大的區別。雖然ECMAScript數組與其他語言中的數組都是數據的有序列表,但與其他語言不同的是,ECMAScript數組的每一項可以保存任何類型的數據。可以用第一個位置保存字符串,第二個位置保存數值,第三個位置保存對象,以此類推。而且,數組的大小是可以動態調整的,即可以隨着數據的添加自動增長以容納新增數據。
表示方法
創建數組的基本方式有兩種:
- 第一種是使用Array構造函數,如果預先知道數組要保存的項目數量,也可以給構造函數傳遞該數量,而該數量會自動變成length屬性的值;給構造函數傳遞值也可以創建數組。如下:
var colors = new Array();//空數組 var colors = new Array(20);//創建一個length為20的數組 var colors = new Array("red", "blue", "green");//創建一個包含三個字符串值的數組 //使用Array構造函數時也可以省略new操作符 var names = Array("Greg");//創建一個包含一個字符串值的數組
-
第二種是使用數組字面量表示法。數組字面量由一對包含數組項的方括號表示,多個數組項之間以逗號隔開,如下:
var colors = ["red", "blue", "green"]; //創建一個包含3個字符串的數組 var names = []; //創建一個空數組 var values = [1,2,]; //禁忌,會創建一個包含2或3項的數組 var options = [, , , , ,]; //禁忌,會創建一個包含5或6項的數組
讀取設置數組的值:使用方括號和基於0的數字索引。如下:
var colors = new Array("red", "blue", "green"); alert(colors[0]); //輸出第一項red color[2]="black"; //修改第三項 color[3]="brown"; //新增第四項
訪問:方括號中的索引號表示要訪問的值,如果索引小於數組中的項數,則返回對應項的值。
設置:設置數組的值使用的語法和訪問的語法一樣,但會替換指定位置的值。
新增:如果索引操作過了現有項數,就會自動增加到該索引值加1的長度。
length屬性
數組length的屬性不是只讀的,通過設置這個屬性,可以從數組的末尾移除項或向數組中添加新項。
var colors = ["red", "blue", "green"]; //創建一個包含3個字符串的數組 colors.length = 2; //將它的長度修改為2,那么最后一項就會被移除 alert(colors[2]); //訪問位置為2的那一項的結果就為undefined var colors = ["red", "blue", "green"]; //創建一個包含3個字符串的數組 colors.length = 4; //將它的長度修改為4, alert(colors[3]); //這個數組不存在位置3,所以訪問這個位置的值就得到了特殊值undefined
利用length屬性也可以方便的在數組末尾添加新項:
var colors = ["red", "blue", "green"]; //creates an array with three strings colors[colors.length] = "black"; //add a color colors[colors.length] = "brown"; //add another color alert(colors.length); //5 alert(colors[3]); //black alert(colors[4]); //brown
var colors = ["red", "blue", "green"]; //creates an array with three strings colors[99] = "black"; //add a color (position 99) alert(colors.length); //100 //在該數組中,位置3到位置98實際上是不存在的,所以訪問它們都將返回undefined
1、檢測數組
自從ECMAScript3作出規定后,就出現了確定某個對象是不是數組的經典問題。對於一個網頁,或者一個全局作用域而言,使用instanceof操作符就能得到滿意結果。
if (value instanceof Array) { //value是一個變量名 //對數組執行某些操作 }
如果網頁中包含多個框架,那實際上就存在兩個以上不同的全局執行環境,從而存在兩個以上不同版本的Array構造函數。如果從一個框架向另一個框架傳入一個數組,那么傳入的數組與第二個框架中原生創建的數組分別具有各自不同的構造函數。為了解決這個問題,ECMAScript5新增了Array.isArray()方法:這個方法的目的是最終確定某個值是不是數組,而不管它是來自哪個全局執行環境中創建的。
if (Array.isArray(value)) { //對數組執行某些操作 }
2、轉換方法
- toString():返回由數組中每個值的字符串形式拼接而成的一個以逗號分隔的字符串。---------返回值是String類型
- toLocaleString():返回由數組中每個值的字符串形式拼接而成的一個以逗號分隔的字符串。但是toLocaleString 只是用來顯示結果給用戶;最好不要在腳本中用來做基本計算,因為返回的結果是隨機器不同而不同的。 ---------返回值是String類型
- valueOf() :返回的還是數組。---------返回值是Array類型
- join():使用不同的分隔符,返回包含所有數組項的字符串。---------返回值是String類型
var colors = ["red", "green", "blue"]; alert(colors.toString()); //red,green,blue。默認是以逗號隔開 alert(colors.join(",")); //red,green,blue alert(colors.join("||")); //red||green||blue
3、棧方法(LIFO)---push、pop
push()方法接受任意數量的參數,把它們逐個添加到數組末尾,並返回修改后的數組長度。
pop()方法從數組末尾移除最后一項,減少數組的length值,然后返回移除的項。
var colors = new Array(); //create an array var count = colors.push("red", "green"); //push two items alert(count); //2 count = colors.push("black"); //push another item on alert(count); //3 console.log(colors.push("black")) var item = colors.pop(); //get the last item alert(item); //"black" alert(colors.length); //2
4、隊列方法(FIFO)---push和shift、unshift和pop
shift()方法:移除數組中的第一個項並返回該項,同時將數組長度減1.
push和shift方法結合使用,可以像隊列一樣使用數組。
var colors = new Array(); //create an array var count = colors.push("red", "green"); //push two items alert(count); //2 count = colors.push("black"); //push another item on alert(count); //3 var item = colors.shift(); //get the first item alert(item); //"red" alert(colors.length); //2
unshift()方法:在數組前端添加任意個項並返回新數組的長度。
unshift和pop結合使用,可以從相反的方向來模擬隊列:在數組的前端添加項,從數組末端移除項。
var colors = new Array(); //create an array var count = colors.unshift("red", "green"); //push two items,此時colors=["red","green"] alert(count); //2 count = colors.unshift("black"); //push another item on,此時colors=["black","red","green"] alert(count); //3 var item = colors.pop(); //get the first item alert(item); //"green" alert(colors.length); //2
5、重排序方法---reverse、sort
數組中已經存在兩個可以直接用來重排序的方法:reverse()
和sort()
方法。
reverse()
方法會反轉數組項的順序。-----會改變原數組
var values = [1, 2, 3, 4, 5]; values.reverse(); alert(values); //5,4,3,2,1
默認情況下,sort()
方法按升序排列數組項。為了實現排序,sort()
方法會調用每個數組項的toString()
轉型方法,然后比較得到的字符串,以確定如何排序。 如下: -----會改變原數組
var values = [0, 1, 5, 10, 15]; values.sort(); alert(values); //0,1,10,15,5
上述例子中,數值5比10 小,但在進行字符串比較時,“10”位於“5”前面,所以這種不是理想的方案。
所以,sort()
方法可以接收一個比較函數作為參數。比較函數接受兩個參數,如果第一個參數應該位於第二個之前則返回一個負數,如果兩個參數相等則返回0,如果第一個參數應該位於第二個之后則返回一個正數。實際操作可以根據需要自行定義。如下是升序的一個例子:只需將compare函數作為參數傳遞給sort()
方法即可。
function compare(value1, value2) { if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } } var values=[0,1,5,10,15]; values.sort(compare); console.log(values) //0,1,5,10,15
降序排序:
function compare(value1, value2) { if (value1 < value2) { return 1; } else if (value1 > value2) { return -1; } else { return 0; } } var values=[0,1,5,10,15]; values.sort(compare); console.log(values) //15,10,5,1,0
另外,對於數值類型或者其valueOf()
方法會返回數值類型的對象類型,可以使用一個更簡單的比較函數。
function compare(value1, value2) { return value2 - value1; }
6、操作方法
- 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
如果沒有給concat()方法傳遞參數,則它只是復制當前數組並返回副本;如果傳遞給concat()方法的是一個或多個數組,則會把數組中的每一項添加到結果數組中去;如果傳遞給concat()方法的不是數組,那么這些值就會被簡單的添加到結果數組中。
- slice()方法:從已有的數組中返回選定的元素。接受一個或兩個參數,即要返回項的起始和結束位置,只有一個參數時,返回的是指定位置到末尾的所有項;有兩個參數時,返回起始位置到結束位置之間的項(包括起始位置的項,不包括結束位置的項)。----------不會改變現有的數組
var colors = ["red", "green", "blue", "yellow", "purple"]; var colors2 = colors.slice(1); var colors3 = colors.slice(1,4); alert(colors); //red,green,blue,yellow,purple alert(colors2); //green,blue,yellow,purple alert(colors3); //green,blue,yellow
如果參數中有負數,則用數組長度加上該負數來確定相應的位置。例如:在一個包含5項的數組上調用slice(-2,-1)與調用slice(3,4)得到的結果相同。如果結束位置小於開始位置,返回空數組。
- splice()方法:有很多用法,最主要的用途是向數組的中部插入項。這個方法的使用有3種:
- 刪除:可以刪除任意數量的項, 只需指定兩個參數:要刪除的第一項的位置和要刪除的項數。例如,
splice(0, 2)
會刪除數組中的前兩項。 - 插入:可以向指定位置插入任意數量的項,只需提供三個參數:起始位置、0(要刪除的項數)和要插入的項。如果要插入多個項,可以再傳入第四、第五,甚至任意多個項。例如
splice(2, 0, "red", "green")
會從當前數組的位置2開始插入字符串”red”和”green”。 - 替換:可以向指定位置插入任意數量的項,且同時刪除任意數量的項,只需提供三個參數:起始位置、要刪除的項數和要插入的項。如果要插入多個項,可以再傳入第四、第五,甚至任意多個項。例如
splice(2, 1, "red", "green")
會刪除當前數組位置2的項,然后再從當前數組的位置2開始插入字符串”red”和”green”。var colors = ["red", "green", "blue"]; var removed = colors.splice(0,1); //remove the first item alert(colors); //green,blue alert(removed); //red - one item array removed = colors.splice(1, 0, "yellow", "orange"); //insert two items at position 1 alert(colors); //green,yellow,orange,blue alert(removed); //空數組 removed = colors.splice(1, 1, "red", "purple"); //insert two values, remove one alert(colors); //green,red,purple,orange,blue alert(removed); //yellow - one item array
- 刪除:可以刪除任意數量的項, 只需指定兩個參數:要刪除的第一項的位置和要刪除的項數。例如,
splice()方法始終會返回一個數組,該數組中包含從原始數組中刪除的項,如果沒有刪除任何項,則返回一個空數組。
7、位置方法
ECMAScript5為數組實例添加了兩個位置方法:
- indexOf():接受兩個參數:要查找的項和(可選的)表示查找起點位置的索引。
indexOf()
方法從數組的開頭向后查找。 - lastIndexOf():接受兩個參數:要查找的項和(可選的)表示查找起點位置的索引。
laseIndexOf()
方法則從數組的末尾開始向前查找。
這兩個方法都返回要查找的項在數組中的位置,沒找到返回-1.在比較第一個參數與數組中的每一項時,會使用全等操作符;也就是說,要查找的項必須嚴格相等。
var numbers = [1,2,3,4,5,4,3,2,1]; alert(numbers.indexOf(4)); //3 alert(numbers.lastIndexOf(4)); //5 alert(numbers.indexOf(4, 4)); //5 alert(numbers.lastIndexOf(4, 4)); //3 var person = { name: "Nicholas" }; var people = [{ name: "Nicholas" }]; var morePeople = [person]; alert(people.indexOf(person)); //-1 alert(morePeople.indexOf(person)); //0
8、迭代方法
ECMAScript5為數組定義了5個迭代方法。每個方法都接受兩個參數:要在每一項上運行的函數和(可選的)運行該函數的作用域——影響this的值。傳入這些方法中的函數(即方法的第一個參數)會接收三個參數:數組項的值、該想在數組中的位置和數組對象本身。根據使用的方法不同,這個函數執行后的返回值可能會也可能不會影響方法的返回值。以下是這5個迭代方法的作用。
- every():對數組中的每一項運行給定函數,如果該函數對每一項都返回true,則返回true。
- some():對數組中的每一項運行給定函數,如果該函數對任一項返回true,則返回true。
- filter():對數組中的每一項運行給定函數,返回該函數會返回true的項組成的數組。
- forEach():對數組中的每一項運行給定函數。這個方法沒有返回值。
- map():對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組。
every和same的比較:
var numbers = [1,2,3,4,5,4,3,2,1]; var everyResult = numbers.every(function(item, index, array){ return (item > 2); }); alert(everyResult); //false,沒有全部都返回true,所以最終返回false var someResult = numbers.some(function(item, index, array){ return (item > 2); }); alert(someResult); //true,有一項返回true,所以最終返回true
filter函數:利用指定的函數確定是否在返回的數組中包含某一項。簡稱為濾波器,可以用來過濾出符合條件項。
var numbers = [1,2,3,4,5,4,3,2,1]; var filterResult = numbers.filter(function(item, index, array){ return (item > 2); }); alert(filterResult); //[3,4,5,4,3]返回的是數組
map():返回一個數組。這個數組的每一項都是在原始數組中的對應項上運行傳入函數的結果。可以用來創建包含的項與另一個數組一一對應的項。
var numbers = [1,2,3,4,5,4,3,2,1]; var mapResult = numbers.map(function(item, index, array){ return item * 2; }); alert(mapResult); //[2,4,6,8,10,8,6,4,2]
forEach():沒有返回值,只是對數組中的每一項運行傳入的函數。本質上和使用for循環迭代數組一樣。
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1]; numbers.forEach(function(item, index, array) { //執行某些操作 });
8、歸並方法
ECMAScript5還新增了兩個歸並數組的方法:reduce()和reduceRight()。這兩個方法都會迭代數組的所有項,然后構建一個最終返回的值。reduce()從前到后,reduceRight()從后到前。 這兩個方法都接收兩個參數:一個在每一項上調用的函數和(可選的)作為歸並基礎的初始值。傳給reduce()和reduceRight()的函數接收4個參數:前一個值、當前值、項的索引和數組對象。這個函數返回的任何值都會作為第一個數自動傳給下一項。第一次迭代發生在數組的第二項上,因此第一個參數是數組的第一項,第二個參數就是數組的第二項。
使用reduce()方法可以執行數組中所有值求和操作。如下:
var values = [1,2,3,4,5]; var sum = values.reduce(function(prev, cur, index, array){ return prev + cur; }); alert(sum);//15
(pre,cru)的值依次為(1,2),(3,3),(6,4),(10,5),(15).
reduceRight()的作用類似,只是方向相反,如下:
var values = [1,2,3,4,5]; var sum = values.reduceRight(function(prev, cur, index, array){ return prev + cur; }); alert(sum);//15
(pre,cru)的值依次為(5,4),(9,3),(12,2),(14,1),(15).
使用reduce()還是reduceRight(),主要取決於要從哪頭開始遍歷數組,除此之外,它們完全相同。