若是參數只有一個而且是Number類型,那麼就是指定數組的長度,但不能是NaN,若是是多個會被當作參數列表。javascript
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類型,但又不是一個具體的數字所以報錯)
注意當只傳遞一個參數時,它只是指定該數組的長度,並不會去填充內容java
因爲傳遞一個參數時不會填充數組內容,所以forEach不會循環這些空內容,或者說forEach不是根據數組長度來循環的,如下代碼就不會被輸出任何內容數組
new Array(6).forEach(function(item,index){ console.log(index) });
像咱們本身模擬的forEach基本上都是有問題的,由於我看大部分人都是經過for循環數組的長度來模擬的forEachprototype
function forEach(arr,fun){ for(var i = 0; i < arr.length; i++){ fun(arr[i]); } }
這就說明在某些狀況下數組的長度是不可靠的,而且咱們沒有辦法去真實的模擬forEach,經過判斷是否是undefined也是不許確的。code
因爲傳遞一個參數時只會增長數組長度而不會填充內容,所以咱們能夠利用這個特色來實現自定義索引發始位置。對象
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
固然咱們也能夠這樣玩blog
new Array(10).concat([1,2,3,4,5]).concat(new Array(5)).concat([6,7,8,9,10])
這種方式有個好處就是,空內容不會被循環到。繼承
它還能夠用來實現相同的連續字符索引
new Array(5+1).join("哈") //因爲數組索引是從0開始的因此須要加+1纔是5 // "哈哈哈哈哈"
咱們用它來輸出一個好玩的ip
new Array(3).concat(['l','o','v','e']).concat(new Array(3)).join('--') // "------l--o--v--e------"
若是你但願設置默認填充內容可使用數組的fill方法
new Array(5).fill(999) [999, 999, 999, 999, 999]
咱們也可使用下面這種方式來實現默認填充內容
var arr = new Array(5).join('5,').split(','); arr.splice(-1,1); // ["5", "5", "5", "5"]
以上這種方式的缺點就是都會變成字符串。
經過Array()方法來建立數組和用new方法來建立效果同樣。
數組經過下標訪問
[2,3,4,5][1] // 3
當咱們經過如下方式進行訪問時,會被解析成連續運算返回最後一個值
[2,3,4,5][1,2] // 4
因爲以上[1,2]是去訪問數組的下標於是被解析成了1,2結果返回的是2,因此以上輸出4
數組也是一種特殊的對象,所以咱們也能夠經過鍵值對的形式去訪問
var arr = []; arr.say = 'Hello'; arr.say // "Hello"
數組和任何值相加都會將數組轉換成字符串再進行拼接
[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
[5] - 2 // 3
若是是多個值,確定是NaN
使用for
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
var arr = [2,3,4,5]; arr.forEach((item)=>console.log(item)) // 2 // 3 // 4 // 5
使用map、filter、some等方法均可以達到遍歷數組的目的,不過這些方法都不能直接經過return來跳出循環,但咱們能夠經過如下方式來實現跳出循環
var arr = [2,3]; try{ arr.forEach(function(item){ if(item === 3){ throw Error(); } console.log(item); }); }catch(e){ } // 2
使用for in
var arr = [2,3]; for(let k in arr){ console.log(arr[k]); } // 2 // 3
不過因爲for in會將繼承的屬性和方法也遍歷出來,以下所示
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 (){}
因此咱們還得過濾一下
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來實現一樣的效果,而且沒有以上問題
var arr = [2,3]; for(let item of arr){ console.log(item) } // 2 // 3
有時咱們並不但願一次性遍歷全部的數組項,而是根據需求來執行,此時咱們就須要用到迭代器了,數組中有一個keys方法能夠生成一個迭代器,以下
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中的數組並不是是傳統意義上的數組,而是一個關聯數組,索引數組只是個表面現象,咱們經過下標的方式去訪問數組,它最終仍是會被轉換爲字符串的。
[2,3][1] // 3
其實它是這樣
[2,3]["1"] // 3
若是說javascript中的數組不是索引數組而是關聯數組,那麼咱們在使用for循環時爲何能夠按照順序來輸出呢?
var arr = [2,3]; for(var i = 0, len = arr.length; i < len; i++){ console.log(arr[i]); } // 2 // 3
若是咱們仔細觀察以上代碼,會發現一個啃爹的現象,咱們被欺騙了好久,咱們是用0 1 2這樣的形式去訪問的數組,天然是按照順序輸出了,再看看下面這段代碼,估計你就懂了
var arr = [2,3]; console.log(arr[0]); console.log(arr[1]); // 2 // 3
你但是手動去訪問人家某個具體屬性的,你說能不是按照順序輸出嗎。
這也就是爲何數組可使用for in方法來循環的緣由,由於本質上來說數組具備對象的某些特性,也就說其實咱們也能夠本身用對象來模擬實現數組,不過咱們須要手動去維護length屬性,從另一個角度上來說JavaScript中的數組很大一部分只是維護了length屬性,跟對象沒什麼兩樣。