Array構造器
如果引數只有一個並且是Number型別,那麼就是指定陣列的長度,但不能是NaN,如果是多個會被當做引數列表。
1 2 3 4 5 6 7 8 9 10 11 12 |
new Array(12) // (12) [undefined × 12] new Array('') // [""] new Array({}) // [Object] new Array([]) // [Array(0)] new Array(null) // [null] new Array(NaN) // Uncaught RangeError: Invalid array length (無效的陣列長度,因為NaN是Number型別,但又不是一個具體的數字因此報錯) |
注意當只傳遞一個引數時,它只是指定該陣列的長度,並不會去填充內容
由於傳遞一個引數時不會填充陣列內容,因此forEach不會迴圈這些空內容,或者說forEach不是根據陣列長度來迴圈的,以下程式碼就不會被輸出任何內容
1 2 3 |
new Array(6).forEach(function(item,index){ console.log(index) }); |
像我們自己模擬的forEach基本上都是有問題的,因為我看大部分人都是通過for迴圈陣列的長度來模擬的forEach
1 2 3 4 5 |
function forEach(arr,fun){ for(var i = 0; i arr.length; i++){ fun(arr[i]); } } |
這就說明在某些情況下陣列的長度是不可靠的,並且我們沒有辦法去真實的模擬forEach,通過判斷是不是undefined也是不準確的。
由於傳遞一個引數時只會增加陣列長度而不會填充內容,因此我們可以利用這個特點來實現自定義索引起始位置。
1 2 3 4 5 6 7 8 |
new Array(10).concat([1,2,3,4,5]).forEach(function(item,index){ console.log(`item: ${item} index: ${index}`); }); // item: 1 index: 10 // item: 2 index: 11 // item: 3 index: 12 // item: 4 index: 13 // item: 5 index: 14 |
當然我們也可以這樣玩
1 |
new Array(10).concat([1,2,3,4,5]).concat(new Array(5)).concat([6,7,8,9,10]) |
這種方式有個好處就是,空內容不會被迴圈到。
它還可以用來實現相同的連續字元
1 2 |
new Array(5+1).join("哈") //由於陣列索引是從0開始的所以需要加+1才是5 // "哈哈哈哈哈" |
我們用它來輸出一個好玩的
1 2 |
new Array(3).concat(['l','o','v','e']).concat(new Array(3)).join('--') // "------l--o--v--e------" |
如果你希望設定預設填充內容可以使用陣列的fill方法
1 2 |
new Array(5).fill(999) [999, 999, 999, 999, 999] |
我們也可以使用下面這種方式來實現預設填充內容
1 2 3 |
var arr = new Array(5).join('5,').split(','); arr.splice(-1,1); // ["5", "5", "5", "5"] |
以上這種方式的缺點就是都會變成字串。
通過Array()方法來建立陣列和用new方法來建立效果一樣。
陣列的訪問
陣列通過下標訪問
1 2 |
[2,3,4,5][1] // 3 |
當我們通過以下方式進行訪問時,會被解析成連續運算返回最後一個值
1 2 |
[2,3,4,5][1,2] // 4 |
由於以上[1,2]是去訪問陣列的下標因而被解析成了1,2結果返回的是2,所以以上輸出4
陣列也是一種特殊的物件,因此我們也可以通過鍵值對的形式去訪問
1 2 3 4 |
var arr = []; arr.say = 'Hello'; arr.say // "Hello" |
陣列與其他值的運算
陣列和任何值相加都會將陣列轉換成字串再進行拼接
1 2 3 4 5 6 |
[1,2,3] + 6 // "1,2,36" [1,2,3] + {} // "1,2,3[object Object]" [1,2,3] + [1,2,3] // "1,2,31,2,3" |
如果陣列只有一個值,那麼當這個陣列和其他值相減相乘等時會被轉換為數字,如果為空會被轉換為0
1 2 |
[5] - 2 // 3 |
如果是多個值,肯定是NaN
遍歷陣列
使用for
1 2 3 4 5 6 7 8 |
var arr = [2,3,4,5]; for(let i = 0, len = arr.length; i len; i++){ console.log(arr[i]) } // 2 // 3 // 4 // 5 |
使用forEach
1 2 3 4 5 6 |
var arr = [2,3,4,5]; arr.forEach((item)=>console.log(item)) // 2 // 3 // 4 // 5 |
使用map、filter、some等方法都可以達到遍歷陣列的目的,不過這些方法都不能直接通過return來跳出迴圈,但我們可以通過以下方式來實現跳出迴圈
1 2 3 4 5 6 7 8 9 10 11 |
var arr = [2,3]; try{ arr.forEach(function(item){ if(item === 3){ throw Error(); } console.log(item); }); }catch(e){ } // 2 |
使用for in
1 2 3 4 5 6 |
var arr = [2,3]; for(let k in arr){ console.log(arr[k]); } // 2 // 3 |
不過由於for in會將繼承的屬性和方法也遍歷出來,如下所示
1 2 3 4 5 6 7 8 9 10 |
Array.prototype.a = 123; Array.prototype.foo = function(){}; var arr = [2,3]; for(let k in arr){ console.log(arr[k]); } // 2 // 3 // 123 // function (){} |
所以我們還得過濾一下
1 2 3 4 5 6 7 8 9 10 |
Array.prototype.a = 123; Array.prototype.foo = function(){}; var arr = [2,3]; for(let k in arr){ if(arr.hasOwnProperty(k)){ console.log(arr[k]); } } // 2 // 3 |
我們還可以使用for of來實現同樣的效果,並且沒有以上問題
1 2 3 4 5 6 |
var arr = [2,3]; for(let item of arr){ console.log(item) } // 2 // 3 |
有時我們並不希望一次性遍歷所有的陣列項,而是根據需求來執行,此時我們就需要用到迭代器了,陣列中有一個keys方法可以生成一個迭代器,如下
1 2 3 4 5 6 7 8 9 |
var arr = [2,3]; var iterator = arr.keys(); console.log(iterator.next().value); console.log('-----'); console.log(iterator.next().value); // 0 // ----- // 1 |
返回的是索引 Array.prototype.keys
其他
實際上JavaScript中的陣列並非是傳統意義上的陣列,而是一個關聯陣列,索引陣列只是個表面現象,我們通過下標的方式去訪問陣列,它最終還是會被轉換為字串的。
1 2 |
[2,3][1] // 3 |
其實它是這樣
1 2 |
[2,3]["1"] // 3 |
如果說javascript中的陣列不是索引陣列而是關聯陣列,那麼我們在使用for迴圈時為什麼可以按照順序來輸出呢?
1 2 3 4 5 6 |
var arr = [2,3]; for(var i = 0, len = arr.length; i len; i++){ console.log(arr[i]); } // 2 // 3 |
如果我們仔細觀察以上程式碼,會發現一個啃爹的現象,我們被欺騙了很久,我們是用0 1 2這樣的形式去訪問的陣列,自然是按照順序輸出了,再看看下面這段程式碼,估計你就懂了
1 2 3 4 5 |
var arr = [2,3]; console.log(arr[0]); console.log(arr[1]); // 2 // 3 |
你可是手動去訪問人家某個具體屬性的,你說能不是按照順序輸出嗎。
這也就是為什麼陣列可以使用for in方法來迴圈的原因,因為本質上來講陣列具有物件的某些特性,也就說其實我們也可以自己用物件來模擬實現陣列,不過我們需要手動去維護length屬性,從另外一個角度上來講JavaScript中的陣列很大一部分只是維護了length屬性,跟物件沒什麼兩樣。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式