數組 Array數組
本質上,數組屬於一種特殊的對象。typeof
運算符會返回數組的類型是 object
函數
// Object.keys方法返回數組的全部鍵名。 var arr = ['a', 'b', 'c']; Object.keys(arr); // ["0", "1", "2"] // 能夠看到數組的鍵名就是整數0、一、2。
length
屬性的最大值就是 4294967295與普通對象的區別是 "數組使用數字做爲索引 [index] 來操做屬性"。index 從 0 開始。性能
數組的存儲性能相對較好。this
var arr = ['唐僧','孫悟空','豬八戒','沙和尚','白龍馬'];spa
1. 建立數組對象prototype
var arr = new Array(); // typeof arr 返回 object
2. 給數組添加對象code
arr[0] = 1; // console.log(arr) 打印 "1" arr[1] = 11; // console.log(arr) 打印 "1,11" arr[2] = 22; // console.log(arr) 打印 "1,11,22"
3. 讀取數組對象對象
console.log(arr[0]); // 1 console.log(arr[1]); // 11 console.log(arr[2]); // 22 console.log(arr[3]); // undefined 不會報錯
4. 獲取數組長度blog
var arr = [1,2,3]; console.log(arr.length); // 返回 3 ,由於有 3 個元素 arr[0],arr[1],arr[2] arr.[100] = 100; // 此時數組有4個元素 arr[0],arr[1],arr[2],arr[100] console.log(arr.length); // 可是會返回 101 , 實際只有 4 個元素, 這四個元素之外的其餘 97 個元素值都爲 undefined, 且用 in 判斷時返回 false
var arr = [ 'a', 'b', 'c' ]; arr.length = 0; arr // []
5. 在數組最後添加元素排序
// 根據上一個特性,能夠在數組最後追加一個元素 arr[arr.length] = 666;
1. 使用字面量來建立數組
var arr = []; // 和 new Array() 效果相同
2. 在建立時指定元素
var arr = [0,1,2,3,4]; // 等同於 var arr = new Array(0,1,2,3,4);
3. 建立一個只有一個元素的數組
var arr = [10]; // 此時數組只有1個元素,arr[0] = 10; var arr = new Array(10); // 此時建立了一個長度爲10的數組!!! // 每一個元素的值都爲 undefined
4. 數組中元素能夠聽任意數據類型的數據
var arr = ["Hello","How",1,2,3,null,undefined,true,false]; // 數組元素是對象 var sun = {name:"孫悟空"}; arr[arr.length] = sun; console.log(arr[arr.length-1].name); // 將會打印 "孫悟空" // 數組元素是函數 var arr = [ function(){console.log("Hello!"}, function(){console.log("Hi!")} ]; // 數組 裏面放 數組 var newArr = [["01","02","03"],[0,1,2],["11","22","33"]]; // 混合着放 var arr = [ {a: 1}, // 對象 [1, 2, 3], // 數組 function() {return true;} // 函數 ]; arr[0] // Object {a: 1} arr[1] // [1, 2, 3] arr[2] // function (){return true;}
5. 遍歷數組
for...in
循環不只能夠遍歷對象,也能夠遍歷數組,畢竟數組只是一種特殊對象
var a = [1, 2, 3]; for (var i in a) { console.log(a[i]); // 1 2 3 }
for...in
不只會遍歷數組全部的數字鍵,還會遍歷非數字鍵。因此,不推薦使用 for...in
遍歷數組。
var a = [1, 2, 3]; a.foo = true; for (var key in a) { console.log(key); // 0 1 2 foo console.log(key); // 1 2 3 true }
for
循環 或 while
循環
var a = [1, 2, 3]; // for循環 for(var i = 0; i < a.length; i++) { console.log(a[i]); } // while循環 var i = 0; while (i < a.length) { console.log(a[i]); i++; } // 逆向遍歷 var l = a.length; while (l--) { console.log(a[l]); }
var colors = ['red', 'green', 'blue']; colors.forEach(function (color) { console.log(color); // red green blue });
length
屬性
var a = ['a' , , 'c']; a.length // 3
// 數組的空位是能夠讀取的,返回a[1] // undefined
a[2] // 'c'
undefined
a[0] // 'a'
a.length // 3var a = [1, 2, 3,];
length
屬性
var a = [1, 2, 3]; delete a[1]; a[1] // undefined a.length // 3
undefined
,是不同的。
forEach
方法、for...in
結構、以及Object.keys
方法進行遍歷,空位都會被跳過。
var a = [, , ,]; a.forEach(function (x, i) { console.log(i + '. ' + x); // 不產生任何輸出 }) for (var i in a) { console.log(i); // 不產生任何輸出 } Object.keys(a) // []
var a = [undefined, undefined, undefined]; a.forEach(function (x, i) { console.log(i + '. ' + x); }); // 0. undefined // 1. undefined // 2. undefined for (var i in a) { console.log(i); // 0 1 2 } Object.keys(a) // ['0', '1', '2']
6. 相似數組對象
length
屬性,那麼這個對象就很像數組,語法上稱爲「相似數組的對象」(array-like object)。
var obj = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; obj[0] // 'a' obj[1] // 'b' obj.length // 3 obj.push('d') // TypeError: obj.push is not a function // 由於它們不具有數組特有的方法。 // 對象obj沒有數組的push方法,使用該方法就會報錯。
length
屬性不是動態值,不會隨着成員的變化而變化arguments
對象,以及大多數 DOM 元素集,還有字符串。slice
方法能夠將 「相似數組的對象」 變成真正的數組
var arr = Array.prototype.slice.call(arrayLike);
call()
,能夠把 forEach()
嫁接到 arrayLike
上面調用
arguments
對象上面調用forEach
方法。
// forEach 方法 function logArgs() { Array.prototype.forEach.call(arguments, function (elem, i) { console.log(i + '. ' + elem); }); } // 等同於 for 循環 function logArgs() { for (var i = 0; i < arguments.length; i++) { console.log(i + '. ' + arguments[i]); } }
forEach
要慢,forEach
方法。
var arr = Array.prototype.slice.call('abc'); arr.forEach(function (chr) { console.log(chr); // a b c });
7. 數組的靜態方法
var arr = [1, 2, 3]; typeof arr // "object" Array.isArray(arr) // true
8. 數組的實例方法
valueOf
方法 返回數組自己。。。不一樣對象的valueOf
方法不盡一致toString
方法 返回數組的字符串形式var arr = []; arr.push(1); // 1 arr.push('a'); // 2 arr.push(true, {}); // 4 // arr = [1, 'a', true, {}]
var arr = ['a', 'b', 'c']; arr.pop() // 'c' // arr = ['a', 'b']
對空數組使用pop
方法,不會報錯,而是返回undefined
push
和pop
結合使用,就構成了「後進先出」的棧結構(stack)
shift
方法能夠遍歷並清空一個數組。
var list = [1, 2, 3, 4, 5, 6]; var item; while (item = list.shift()) { console.log(item); } list // []
push
和shift
結合使用,就構成了「先進先出」的隊列結構(queue)
unshift
方法能夠接受多個參數,這些參數都會添加到目標數組頭部
var a = [1, 2, 3, 4]; a.join(' '); // '1 2 3 4' a.join(' | '); // "1 | 2 | 3 | 4" a.join(); // "1,2,3,4"
[undefined, null].join('#') // '#' ['a',, 'b'].join('-') // 'a--b'
若是數組成員是undefined
或null
或空位,會被轉成空字符串
call
方法,這個方法也能夠用於字符串或相似數組的對象
Array.prototype.join.call('hello', '-') // "h-e-l-l-o" var obj = { 0: 'a', 1: 'b', length: 2 }; Array.prototype.join.call(obj, '-') // 'a-b'
['hello'].concat(['world']); // ["hello", "world"] ['hello'].concat(['world'], ['!']); // ["hello", "world", "!"] [].concat({a: 1}, {b: 2}); // [{ a: 1 }, { b: 2 }] [2].concat({a: 1}); // [2, {a: 1}]
concat
方法返回當前數組的一個淺拷貝。所謂「淺拷貝」,指的是新數組拷貝的是對象的引用
slice
方法的參數是負數,則表示倒數計算的位置var a = ['a', 'b', 'c']; a.slice(-2); // ["b", "c"] a.slice(-2, -1); // ["b"] var a = ['a', 'b', 'c']; a.slice(4); // [] a.slice(2, 1); // []
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }) // ['a', 'b'] Array.prototype.slice.call(document.querySelectorAll("div")); Array.prototype.slice.call(arguments);
數值會被先轉成字符串,再按照字典順序進行比較因此101
排在11
的前面
sort
方法按照自定義方式排序,能夠傳入一個函數做爲參數
0
,表示第一個成員排在第二個成員後面;其餘狀況下,都是第一個元素排在第二個元素前面。
[10111, 1101, 111].sort(function (a, b) { return a - b; }); // [111, 1101, 10111]
[ { name: "張三", age: 30 }, { name: "李四", age: 24 }, { name: "王五", age: 28 } ].sort(function (o1, o2) { return o1.age - o2.age; }); // [ // { name: "李四", age: 24 }, // { name: "王五", age: 28 }, // { name: "張三", age: 30 } // ]
var numbers = [1, 2, 3]; numbers.map(function (n) { return n + 1; }); // [2, 3, 4] numbers // [1, 2, 3]
map
方法向它傳入三個參數:當前成員 elem、當前位置 index、數組自己 arr
[1, 2, 3].map(function(elem, index, arr) { return elem * index; }); // [0, 2, 6]
map
方法還能夠接受第二個參數,用來綁定回調函數內部的this
變量
var arr = ['a', 'b', 'c']; [1, 2].map(function (e) { return this[e]; }, arr) // ['b', 'c']
map
方法的回調函數在這個位置不會執行,會跳過數組的空位 (不會跳過不會跳過undefined
和null
)
var f = function (n) { return 'a' }; [1, undefined, 2].map(f); // ["a", "a", "a"] [1, null, 2].map(f); // ["a", "a", "a"] [1, , 2].map(f); // ["a", , "a"]
map
方法很類似,也是對數組的全部成員依次執行參數函數forEach
方法不返回值,只用來操做數據。map
方法,不然使用forEach
方法forEach
方法也能夠接受第二個參數,綁定參數函數的 this 變量
forEach
方法也會跳過數組的空位 , 不會跳過undefined
和null
var out = []; [1, 2, 3].forEach(function(elem) { this.push(elem * elem); }, out); out // [1, 4, 9]
forEach
方法沒法中斷執行,老是會將全部成員遍歷完。for
循環
true
的成員組成一個新數組返回。該方法不會改變原數組。
[1, 2, 3, 4, 5].filter(function (elem) { return (elem > 3); }); // [4, 5] 將大於3的數組成員,做爲一個新數組返回 var arr = [0, 1, 'a', false]; arr.filter(Boolean); // [1, "a"] 獲取全部布爾值爲true的成員
[1, 2, 3, 4, 5].filter(function (elem, index, arr) { return index % 2 === 0; }); // [1, 3, 5]
filter
方法還能夠接受第二個參數,用來綁定參數函數內部的this
變量
var obj = { MAX: 3 }; var myFilter = function (item) { if (item > this.MAX) return true; }; var arr = [2, 8, 3, 4, 1, 3, 2, 9]; arr.filter(myFilter, obj); // [8, 4, 9]
some
方法是隻要一個成員的返回值是true
,則整個some
方法的返回值就是true
,不然返回false
var arr = [1, 2, 3, 4, 5]; arr.some(function (elem, index, arr) { return elem >= 3; }); // true
every
方法是全部成員的返回值都是true
,整個every
方法才返回true
,不然返回false
var arr = [1, 2, 3, 4, 5]; arr.every(function (elem, index, arr) { return elem >= 3; }); // false
some
方法返回false
,every
方法返回true
,回調函數都不會執行
reduce
是從左到右處理(從第一個成員到最後一個成員)reduceRight
則是從右到左(從最後一個成員到第一個成員),其餘徹底同樣// 求出數組全部成員的和
[1, 2, 3, 4, 5].reduce(function (a, b) { console.log(a, b); return a + b; }); // 1 2 第一次執行, 是數組的第一個成員,是數組的第二個成員 // 3 3 第二次執行, 爲上一輪的返回值,爲第三個成員 // 6 4 第三次執行, 爲上一輪的返回值,爲第四個成員 // 10 5 第四次執行, 爲上一輪返回值,爲第五個成員 // 最後結果:15a1b2a3b3a6b4a10b5
reduce()
和 reduceRight()
的第一個參數都是一個函數。該函數接受如下四個參數
reduce
方法和reduceRight
方法的第二個參數
[1, 2, 3, 4, 5].reduce(function (a, b) { return a + b; }, 10); // 25 // 指定參數a的初值爲10,因此數組從10開始累加,最終結果爲25。 // 注意,這時b是從數組的第一個成員開始遍歷
reduce
方法會報錯。這時,加上第二個參數,就能保證老是會返回一個值function substract(prev, cur) { return prev - cur; } // 比較 reduce() reduceRight() [3, 2, 1].reduce(substract) // 0 [3, 2, 1].reduceRight(substract) // -4
function findLongest(entries) { return entries.reduce(function (longest, entry) { return entry.length > longest.length ? entry : longest; }, ''); } findLongest(['aaa', 'bb', 'c']); // "aaa"
-1
var a = ['a', 'b', 'c']; a.indexOf('b'); // 1 a.indexOf('y'); // -1 ['a', 'b', 'c'].indexOf('a', 1); // -1 結果爲-1,表示沒有搜索到
-1
var a = [2, 5, 9, 2];
a.lastIndexOf(2); // 3
a.lastIndexOf(7); // -1
[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1
NaN
的位置,即它們沒法肯定數組成員是否包含NaN
var users = [ {name: 'tom', email: 'tom@example.com'}, {name: 'peter', email: 'peter@example.com'} ]; users .map(function (user) { return user.email; }) .filter(function (email) { return /^t/.test(email); }) .forEach(function (email) { console.log(email); }); // 先產生一個全部 Email 地址組成的數組,而後再過濾出以t開頭的 Email 地址,最後將它打印出來