數組的基本特點
- 數組元素是任意類型的
- 可能的最大索引是2^32-2,默認起始索引是 0
- Javascript的數組是動態的,無需手動開辟內存
- 數組可能不連續
- 每個數組都與一個length屬性,length之比數組中所有元素的索引值都大
1.創建數組
- 四種方式
1. var arr = []; //空數組,不含任何元素
2. var arr = new Array(); //空數組,不含任何元素 效果與1一樣
3. var arr = [1,2,3]; //初始化數組的同時,添加新元素
4. var arr = new Array(1,'',3); //效果與3一樣,數組用元素可以是任意類型
5. var arr = new Array(10); //指定長度創建一個數組,此時數組長度length=10
- 注意點
數組直接量的末尾可以有可選逗號,因此創建數組的時候末尾的逗號一般可以省略
1. var arr = [1,,3]; //此時數組中有三個元素,中間那個元素是undefined
2. var arr = [,,]; //此時數組中只有兩個元素,都是undefined
2.元素讀寫與刪除
- 使用 [ ] 來操作數組元素
- 數組是對象的特殊形式,用方括號訪問數組元素就像用其訪問對象屬性一樣
- javascript中對于小于2^32-2的非負整數索引,會自動維護length的值
- 使用負數或者非整數作為數組的索引的時候,會自動轉化為字符串做索引,因此不存在數組“越界”的概念
- 字符串做索引的時候能轉化為非負整數的時候,會默認轉化為非負整數的索引
- 試圖查詢數組中不存在的索引的時候,會返回undefined
var a = [1,2,3];
var a1 =a[0]; //讀數組中的第一個元素,默認索引從0開始
a[0] = 'A'; //給數組中0索引的寫入新值 'A'
a[10] = 'B'; //數組中沒有索引為10的元素,則直接生產索引為10的元素,此時length=11
a[-1.1] =1.1; //創建“-1.1”的屬性,值為1.1
a['1000']=1000; //此時該元素是數組的第1001個元素
a[1.000] = 1; //等價于a[1] = 1
a.push(0); //等價于a[a.length] = 0;
a.push(1,3,5); //在數組末尾連續添加三個元素
a.pop(); //刪除數組末尾的元素,length = length-1;
delete a[1]; //刪除索引1處的元素,此操作不會改變length值
3.稀疏數組
數組中的索引不是連續的,則稱這個數組是稀疏數組,此時數組length值大于數組元素的個數
- 例子
var a = new Array(10);//數組沒有元素,length=10
a = [] ;//空數組(也就是沒有元素),length=0;
a[1000] = 1; //添加新元素1,此時length =10001
- 注意點
在數組中直接量中省略值時不會創建稀疏數組,省略的元素是存在于數組中的,其值為undefined,和數組中根本不存在元素是有差別的
var a1 = [,];//無元素的空數組,length=1;
var a2 = [undefined];//含元素undefined元素的數組,length = 1;
0 in a1 ; //false ,a1在索引0處沒有元素
0 in a2 ; //true ,a2在索引0出有一個undefined元素
var a1 = [,,,]; // length = 3;
var a2 = new Array(3); // length =3;
0 in a1 ; //true ,a1在索引0處有元素undefined
0 in a2 ; //false ,a2在索引0處沒有元素
//a與b效果一樣
var a = [1,,3];
var b = [1,undefined,3];
4.數組長度
- 數組長度length 在非稀疏數組中,為數組元素賦值的時候,當前索index引大于等于length,那么length = index +1,這是數組自動維護的。
- 將length設置為一個小于當前length值并且是非負整數 L 的時候,數組中大于等于索引L的元素會被刪除,刪除方式是逐個刪除
- 當設置數組長度length大于當前數組的長度值時,不會創建新的元素,只是在數組的末尾創建一個空的區域
var a = [1,2,3,4,5]; // length=5;
a.length = 3; //此時數組為[1,2,3]
a.length = 0; //此時數組為[ ]
a.length = 5; //length =5,數組為[ ]
在ECMAScript 5中可以通過Object.defineProperty()讓數組的長度變為只讀,但是數組內部還是能維護數組的長度length的
var a =[1,2,3];
Object.defineProperty(a,"length",{writable:false});
a.length = 0; //此時數組的長度將不會被設置成0
5.數組遍歷
使用for in 遍歷數組的時候需要注意 for in 遍歷能枚舉集成的屬性名,例如添加到Array.Prototype中的方法,因此遍歷的時候因該過濾掉這些不必要的屬性
var a =[1,2,3,4,5];
for(var i =0,l = a.length;i<l;i++){
//跳過null undefined 和 不存在的元素
if(!a[i])
continue;
//跳過undefined 和 不存在的元素
if(a[i]===undefined)
continue;
//跳過不存在的元素
if(!(i in a))
continue;
}
//用for in 處理稀疏數組
// i 是得到數組中含有元素的索引
for(var i in a){
//獲取索引i的值
var value = a[i];
//過濾繼承過來的屬性名
if(!a.hasOwnProperty(i)) continue;
//跳過非負整數的元素
if(String(Math.floor(Math.abs(Number(i))))!==i) continue;
}
6.多維數組
在表面上javascript不支持多維數組,但是數組可以存放任意的類型的這個特點可以變向的實現多維數組,實際中也很常用。
基本思想就是數組中在存放另一個數組,可以多層嵌套,但是層數太多,管理和操作都會越來越復雜
- 一個簡單的多維數組
var table = new Array(5);
for(var i = 0,l = table.length;i<l)
table[i] = new Array(10);
for(var i = 0,l = table.length;i<l;i++)
{
for(var j = 0,l = table.length;j<l;j++){
table[i][j] = i*j;
}
}
7.數組方法
ECMAScript 3 :
數組方法是定義在Array.prototype中的,對所有數組都可以使用
- join()
將數組中所有元素都轉化為字符串并連接在一起,默認分隔符是',',可以指定分隔符
var a = [1,2,3];
a.join(); // "1,2,3"
a,join("");// "123"
- reverse()
數組元素順序反轉,返回反轉后的數組,此過程在原數組進行,不創建新數組
var a = [1,2,3];
a.reverse().join(); //結果是"3,2,1"
- sort()
將數組元素進行排序,不帶參數將默認按字典序排序。設比較的兩數為(未排序時,a在b前面) a,b 返回值 >0 則使a排在b之后,返回值 < 0 則使a排在b之前,返回值 ==0 則使a,b順序無關緊要
var a = [3,1,5,6,2];
a.sort().join();
a.sort(function(a,b){
//自定義的排序規則(此處是遞減排序)
if(a>b)
return -1;
if(a<b)
return 1;
return 0;
}).join();
- concat()
創建并返回一個數組,他的元素是原數組和concat()中的每個參數,參數是數組的時候,連接的是數組的元素,而非數組本身。當參數是多層嵌套的數組的時候不會遞歸的把多層嵌套的數組元素取出來拼接到原數組。
var a = [1,2,3];
a.concat(4,[5,6,[7,8]]);// 新數組[1,2,3,4,5,6,[7,8]]
- slice()
返回指定數組的一個片段(子數組),一個參數的時候截取的是 參數i - length,連個參數(a,b)的時候是截取 a包括a到b之間的元素,當參數為負整數時是從末尾元素開始數的第|x|個
var a = [1,2,3,4,5];
a.slice(3); //[4,5]
a.slice(1,2); //[2]
a.slice(-4,-2); //[2,3]
- splice()
在數組中刪除或者插入數據,一個參數是刪除指定索引到結尾的全部元素,兩個參數的時候是刪除指定區間元素,大于兩個參數的時候是刪除指定元素后插入指定位置。第一個參數是要刪除元素的索引,第二個參數是由起始索引到結束索引的長度,第二個之后的參數是插入到起始刪除索引位置的元素。
var a = [1,2,3,4];
a.splice(2,1); //[1,2,4]
a.splice(1); //[1]
a.splice(1,0,2,3,4,[5,6]); // [1,2,3,4,[5,6]]
- push() 和 pop()
和棧結構中的圧棧出棧概念一樣。push()帶多個參數的時候是按順序壓入
var s = [];
s.push(1,2);
s.push([3,4]);
s.pop();
- shift() 和 unshift()
shift():從數組首部刪除一個元素并返回該元素
unshift():在數組首部添加一個或者多個元素,添加的順序從參數尾部向前添加
var s = [1,2];
a.unshift(3,4,[6,7]); // s = [3,4,[6,7],1,2]
a.shift(); // s = [4,[6,7],1,2]
- toString() toLocalString()
toString():將數組中的每個元素轉化成字符串并輸出用逗號做分隔符的字符串序列,數組有多層數組嵌套的時候會遞歸的進行轉化字符串
toLocalString()是toString()的本地化方法,將toString()轉化的字符串本地化
var s = [1,2,[3,'a']];
s.toString(); // "1,2,3,a"
ECMAScript 5 :
- 關于ECMAScript 5數組方法的一些說明:
大多數方法的第一個參數都傳遞一個函數,并且對每個元素都調用一次這個函數,稀疏數組中對不存在的元素則不調用。
- forEach()
從頭到尾遍歷數組,為每個元素調用指定的函數。forEach無法用break中途停止遍歷。
var a = [1,2,3];
var sum = 0;
s.forEach(function(v){sum+=v});
//sum = 6;
// v:當前索引的元素,i:當前索引 ,a:調用該方法的數組
a.forEach(function(v,i,a){
a[i] = v + i;
});
// 結果是:a =[2,3,4];
- map()
將調用數組中的每個元素傳遞給指定的函數。map不改變調用它的數組本身,會返回一個新的數組,如果是稀疏數組,那么返回的數組和調用map的稀疏數組有一樣的length 和 缺失元素
var a = [1,2,3];
var b = a.map(function(x){ return x++;});
// b = [2,3,4];
- filter()
返回一個新數組,新數組是調用該函數數組的一個子集,filter中傳遞的函數返回true 或者 false ,true:新數組添加該元素。filter() 會跳過稀疏數組總缺少的元素,所以返回的新數組總是稠密數組
var a = [1,2,3,4,5];
var b = a.filter(function(x){
if(x>3) return true; //篩選大于3的元素
return false;
});
// b = [4,5];
//壓縮稀疏數組
var v = a.filter(function(){ return true;});
//壓縮并刪除undefined 和 null 元素
var v = a.filter(function(x){ return x!==undefined && x!= null;});
- every() 和 some()
邏輯判斷函數,返回值都是true 或者false,every:所有元素調用判定函數返回true 最后結果才是true,遇到判定返回false則停止遍歷,結果是false。some :至少有一個元素調用判定函數返回true ,結果返回true,判定返回遇到true,則停止遍歷,結果返回true。
var a = [1,2,3,4,5];
a.every(function(x){ return x>0}); //true
a.some(function(x){ return x > 5}); //false
- reduce() 和 reduceRight()
- 兩個方法都是使用指定的函數將元素進行組合。區別在于兩者的遍歷數組順序剛好相反。reduce是索引從低到高,reduceright是索引從高到低。
- 函數中需要兩個參數,參數1:化簡操作的函數,參數2(可選):函數初始值(沒有初始值的時候,會默認使用遍歷的第一個元素的值作為初始值)
3.空數組的時候,不傳遞初始值會導致類型錯誤異常
var a = [1,2,3];
//簡單的數組求和,初始值為0
//第一次調用時是 return 的是 0(初始值)+a;然后才是a+b
var res = a.reduce(function(a,b){ return a+b;},0); //res = 6
//簡單的數組求積,初始值為1
//第一次調用時是 return 的是 1(初始值)* a;然后才是a*b
var res = a.reduce(function(a,b){ return a+b;},1); //res = 6
//對象求并集
var a = [{x:1,a:1},{y:2,a:2},{z:3,a:3}];
//不帶初始值的時候默認使用第一個遍歷到的元素值
a.reduce(function(union)); //結果是:{x:1,y:2,z:3,a:1}
a.reduceRight(function(union)); //結果是:{x:1,y:2,z:3,a:3}
- indexOf() 和 lastIndexOf()
- 搜索整個數組中具有給定值的元素,返回第一個找到的元素的索引,沒找到則返回-1
- indexOf :從頭到尾搜索,lastIndexOf:從尾到頭搜索
- 第一個參數:給定搜索的值,參數二(可選):指定開始搜索的索引
var a = [1,3,5,7];
var i = a.indexOf(7,2); // i = 3
//參數2可以為負數,表示相對末尾的偏移量
var i = a.lastIndexOf(3,-2);// i = 1
8.數組類型
- ECMAScript 5中使用Array.isArray()判定是否是數組
Array.isArray([]); // true
- ECMAScript 3中使用isArray()的方法是判斷一個對象的屬性是否是“Array”
var isArray = Function.isArray() || function(o){
return typeof o === "object" && Object.protitype.toString.call(o)
=== "[Object Array]";
}
- instanceof 在瀏覽器中開啟多窗口多窗口時,只能正對該窗口做檢測,不能全局(整個瀏覽器)檢測,因為每個窗口都有自己的全局環境
9.數組相關
9.1 作為數組的字符串
常見的是用[] 代替字符串的chatAt()方法
var s = "String";
s.chatAt(1) == s[1]; //
因為字符串是不可變值的所以不能用 s[0] = 3 的方式復制,也不能使用數組中的push(),pop(),sort(),reverse(),splice()等方法
Array.prototype.join.call(s,","); //結果是:"S,t,r,i,n,g"
Array.prototype.filter.call(s,function(x){ return x >'a';}).join("");
//結果是:"tring"
9.2 類數組對象
-
類數組對象與數組有明顯的區別。體現在數組用類數組對象沒有的特點:
- 數組中有新元素添加,會自動更新length屬性
- 通過設置length的值為一個較小的非負整數截斷數組
- 數組從Array.protitype中繼承了有用的方法
- 數組的類屬性是"Array"
- 通過[ ]將對象偽裝成對象
var o ={};
var i = 0;
while(i<10){
o[i] = i;
i++;
}
a.lenght = i;
ECMAScript 5 中 數組方法都是通用的,所以能在類數組對象上使用,ECMAScript 3中除了toString() ,toLocalString()外的方法也是通用。
但是類數組對象沒有繼承Array.prototype,所以不能直接在類數組對象上調用數組方法,可以使用Function.call()方法調用
var a={"0":"a","1":"b","2":"c",length:3};//類數組對象
Array.prototype.join.call(a,"_"); // 結果是:"a_b_c"
Array.prototype.map.call(a,function(x){
return x.toUpperCase();
}); // 結果是:"["A","B","C"]"