此乃犀牛書(第七章 數組)讀書筆記,又結合了ES6中數組的擴展部分作的知識梳理。
精華部分就是手工繪製的兩張數組總結圖了。
靈活運用數組的各類方法是基本功,是基本功,是基本功,重要的事情說三遍。
好了,正文從下面開始~數組
對象是屬性的無序集合,而數組是值的有序集合;
每一個值叫作一個元素,每一個元素在數組中的位置稱爲索引;函數
JS數組是無類型的:數組元素能夠是任意類型,同一個數組中的元素也可能有不一樣類型;優化
JS數組是動態的:可根據須要增加或縮減;spa
JS數組多是稀疏的:數組元素的索引不必定是連續的。prototype
稀疏數組length屬性值大於元素的個數code
建立稀疏數組的兩種方法:對象
var a= []; a[1000] =1 //直接量
var a = [1,2,3,4,5,6]; delete a[0]; //刪除從而使得不連續
數組是特殊的對象,使用[]訪問數組元素就像使用[]訪問對象屬性同樣(索引就是屬性名)blog
數組的特別之處在於,當使用小於2的32次方的非負整數做爲屬性名時數組會自動維持其length屬性值,length屬性使得數組區別於常規JS對象。索引
當爲數組元素賦值時,索引i大於或等於length,length屬性變爲i+1;
當設置數組length屬性小於當前數組長度時,大於的部分將被刪除;
也能夠設置數組的length屬性大於當前數組長度,這時後面會建立空區域;
可使用Object.defineProperty()將數組length屬性設置爲只讀的。rem
如何判斷一個對象是數組對象?
ES5提供了一個方法:
Array.isArray(a) // true or false
還能夠經過檢查對象的類屬性(class)
Object.prototype.toString.call(a) == '[object array]' //這裏須要使用Object的toString方法,由於Array的toString方法被重寫了。
注意:使用instanceof判斷數組對象是不靠譜的。這是由於當跨越多個窗體時,檢測會失敗。
類數組對象:擁有length屬性,屬性是非負整數的對象
數組方法在類數組對象上也能work, 類數組對象不能直接調用數組的方法,但能夠間接調用
常見的類數組對象:arguments對象、一些DOM方法的返回
下面用一張圖來總結一下數組的方法:
這張圖是按照ES標準發展的順序總結了標準中數組提供的方法,畫完圖的我表示嚇了一跳。ES6居然提供了這麼多新的方法。看來使用的是至關不充分。之後要考慮少用underscore了。。。
上圖中每一個方法可能能夠實現不止一種功能(例如splice既能實現爲數組增長元素,又能刪除數組元素),那麼按照數組操做劃分,這張圖又能夠變成下面這個樣子:
下面對上述兩張圖裏面的部分知識進行詳細說明和demo演示。
數組直接量
var a = [1, true,'hi']; var b = [,,] //undefined*2
new + Array
var a = new Array() var b = new Array(10) var c = new Array(1,2)
Array.of()
Array.of(1,2,3) //[1,2,3]
這是ES6中提供的方法,爲了彌補new+Array在傳入不一樣個數的參數時輸出不一致的問題。
使用'[]'訪問數組元素時,js將索引轉換爲字符串,而後將其做爲屬性名同樣使用。
//注意使用負整數和浮點數做爲索引時: a[-123] //同a['-123'] a[1.000] //同a[1]
var a = []; a[1] = 1; a.push(1) a.unshift(1) //以上都使得a變成了[1]
delete刪除數組元素是不改變數組的length的,也不會讓其餘數組元素索引起生改變,會讓數組變爲稀疏數組。
最簡單的方案就是使用for循環,那麼,使用for循環遍歷數組時能夠有哪些優化點?
首先,若是數組不是稠密的,應該加判斷排除null, undefined和不存在的元素,以免多餘循環;
其次,數組長度應該先求出來,而非每次循環都去查詢長度,可是這種適用於在遍歷過程當中不修改數組長度的狀況(試一下一邊遍歷,一邊刪除數組元素的狀況);
使用for循環和使用forEach,map這些方法有什麼區別?
使用for循環,能夠從後向前遍歷數組,而使用方法則作不到。
sort() 直接使用時是按照字母順序排列的。若是想要根據數值大小順序排列,能夠在回調函數裏指定。
var a= [33,4,1111,222] a.sort() //[1111,222,33,4] a.sort((a,b)=>{ return a-b //<0 第一個參數應該在前 }) //[4,33,222,1111]
var a = [1,2,3] var b = a.concat(4,5) //a不變,返回[1,2,3,4,5]
注意,concat只拼接第一層結構。
另外,使用擴展運算符一樣能實現數組拼接:
var a = [1,2,3] var b = [...a,4,5]
splice既能刪除元素,也能插入元素,取決於有咩有第三個參數
splice是修改數組自己的,可是slice方法是不修改數組自己的。
var a = [1,2,3,4,5,6] a.splice(4) //a: [1,2,3,4] a.splice(2,1) //[1,2,4] a.splice(2,1,3) //[1,2,3]
ES5數組方法的特色:
第一個參數是函數,對數組的每一個元素調用一次該函數
若是是稀疏數組,對不存在的元素不調用傳遞的函數(wow)
不修改原始數組
forEach 不能break , 想break 須要try catch
forEach不修改原始數組,想修改,能夠藉助第三個參數
var data = [1,2,3,4,5,6] data.forEach((ele, index, dd)=>{ dd[index] = ele + 1 }) //data: [2,3,4,5,6,7]
map方法也不修改原始數組
var b = a.map(function(ele){return ele+1})
indexOf方法有兩個缺點:
不夠語義化,它的含義是找到參數值出現的第一個位置,因此要去比較是否不等於-1
內部使用嚴格運算符'===',因此會致使對NaN的誤判
[NaN].indexOf(NaN) //-1
而includes方法沒有這個問題。
[NaN].includes(NaN) //true
關於數組的方法衆多,在使用時多嘗試不一樣的方法,方能熟記各種方法的特色。
未完待續~