在開始正式的內容之前,不得不說說js中的數據類型和數據結構,以及一些比較容易讓人混淆的概念。那么為什么要從數組說起?數組在js中是最常見的內存數據結構,數組數據結構在js中擁有很多的方法,很多初學者記不清數組的大多數用法,只知道push,pop,shift等最基本的幾個。所以,本系列(數組篇)會盡可能的讓大家對數組有一個透徹的了解。也方便后面其他數據結構的學習和使用。
可能很多web前端開發者都會有一個疑問,那就是,數組和對象究竟是數據類型?還是數據結構?那么我們就帶着這樣的疑問,開始下面的學習,希望看完這篇文章之后,你模糊的概念會變得清晰一些。
首先,在js中,數據類型分為兩種,基本類型(原始類型)和復雜類型,其中,基本類型是:String(字符串),Number(數值),Boolean(布爾值),還有undefined和null。復雜類型是Objecct(對象)。
說到這里大家可能會有些疑問,只有這六種類型?那數組(Array),正則(RegExp),日期(Date)算是什么?其實他們都是Object(對象)的一個分支,換句話說它們都屬於Object類型,這也正是js與眾不同的地方——萬物皆對象。而后面要聊的包括隊列,棧,鏈表,集合,樹,圖等數據結構在js中的展現方式,也都是通過對象和原型來實現的。本文無意去詳細的描述數據類型和數據結構的種類以及在js中的體現形式。所以點到為止。
故事已經開始,請大家系好安全帶,跟着我馳騁在在這篇廣闊的土地上——數組。
先解釋一下什么是數組吧,所謂數組,是有序的元素序列。 若將有限個類型相同的變量的集合命名,那么這個“名”稱為數組名。組成數組的各個變量稱為數組的分量,也稱為數組的元素,有時也稱為下標變量。用於區分數組的各個元素的數字編號稱為下標。數組是在程序設計中,為了處理方便, 把具有相同類型的若干元素按無序的形式組織起來的一種形式。這些無序排列的同類數據元素的集合稱為數組。簡單來說數組就是用於儲存多個相同類型數據的集合。(當然,js中的數組也可以存儲不同類型數據,但是!不建議這樣做!)
一、數組的創建和初始化
相信很多小伙伴都知道創建一個數組十分容易:
var arr = [];
這樣我們就創建了一個數組,我們還可以用new關鍵字來創建並初始化一個數組:
//創建一個空數組 var newArr = new Array(); //創建一個指定長度的數組 var newLenArr = new Array(4); //創建一個具有指定參數的數組 var numArr = new Array(1,2,3,4);
當然,通過new關鍵字創建並初始化數組的方式並不推薦,這里只是給大家介紹一下。其實我們通過上面第一種方式來創建數組的本質就是通過new來實例化一個Array對象。OK,這里不多說它的實現原理,還是回到數組本身來吧。
那么我們如何讀取數組中的數據呢?很簡單,我就一句話帶過了,也就是通過中括號([ ])arr[2],來傳遞數值的位置,獲取到對應位置的值,也可以通過這種方式來重新賦值。
二、數組的增刪
接下來說說如何使用js數組自帶的方法來實現數組頭尾的增刪:push(數組尾部插入元素),unshift(數組頭部插入元素),pop(數組尾部刪除元素)和shift(數組頭部刪除元素)
1、push方法
如果我不想使用push方法,有沒有什么方式可以在數組的尾部插入一個元素呢?其實很簡單,我們只需要把值賦給數組中最后一個空位上的元素就可以了。
var nums = [0,1,2,3,4]; nums[nums.length] = 5;
我們通過length屬性,獲取該數組的長度是5,但是我們數組對應的下標是從0開始的,通過這樣的方式,也就給數組的尾部插入了一個新的元素。當然,其實我們可以更方便的使用push來給數組的尾部插入一個元素:
var nums = [0,1,2,3,4]; nums.push(5);
也可以得到同樣的結果。當然,push也可以傳入多個參數,依次的從尾部插入數組:
var nums = [0,1,2,3,4]; nums.push(5,6,6); //[0,1,2,3,4,5,6,6]
2、unshift方法
那么同樣的,如何在不使用原生方法的前提下給數組的頭部添加一個元素呢?
var nums = [0,1,2,3,4,5,6]; for(var i = nums.length;i >= 0;i--){ nums[i] = nums[i - 1]; } //[undefined, 0, 1, 2, 3, 4, 5, 6] nums[0] = -1; //[-1, 0, 1, 2, 3, 4, 5, 6]
實際上,我們通過循環遍歷,把nums數組中的每一位所對應的下標增加一個,也就是向后移動一位,那么這就導致了頭部的位置空出(它的位置是存在的),但是此時我們並沒有給空出的位置所對應的下標賦值,所以它的長度增加了值確實undefined,賦值之后,才會得到我們想要的結果。
下面我們還是用unshift方法來給數組的頭部插入新值:
var nums = [0,1,2,3,4,5]; nums.unshift(-1); //[-1, 0, 1, 2, 3, 4, 5] nums.unshift(-2,-3); //[-2, -3, -1, 0, 1, 2, 3, 4, 5]
那么要注意一點,在使用unshift傳入多個參數的時候,他會把第一個參數放在數組的頭部(以此類推),也就是說unshift方法會把所有的參數依照順序插入數組,並不是我們想當然的那樣從第一個參數依次添加進數組。
3、pop方法
如果我想要刪除數組尾部的元素,我們可以使用pop方法,其實我們還是可以用js來模擬一下pop:
var nums = [0,1,2,3,4,5]; nums.length = nums.length - 1; //[0, 1, 2, 3, 4]
我們可以通過手動讓數組的長度減少一位,就可以實現刪除數組尾部的元素,當然也可以減少兩位三位等。
實際上,在日常開發中通常都會使用pop方法來刪除數組尾部的元素(pop()方法沒有參數,只是刪除數組尾部的元素。):
var nums = [0,1,2,3,4,5]; nums.pop() // [0, 1, 2, 3, 4]
4、shift方法
那么接下來我們看看如何從數組的首位刪除元素:
var nums = [0,1,2,3,4,5]; for(var i = 0; i < nums.length; i++) { nums[i] = nums[i + 1] } // [1, 2, 3, 4, 5, undefined]
可以看到,我們最后一位是undefined,也就是說在最后一次的循環里,i + 1引用了一個數組里還未初始化的位置(開辟了空間但是未賦值),所以,這樣的方式只是依次覆蓋了上一位的值,並沒有真正的刪除元素。如果想要刪除首位的元素,這就需要用到shift方法了。
var nums = [0,1,2,3,4,5]; nums.shift(); // [1, 2, 3, 4, 5]
5、splice方法
最后,我們看看如何使用splice()方法,在數組的任意位置添加和刪除元素:
var nums = [0,1,2,3,4,5,6,7]; nums.splice(2); //[0, 1] //如果只加一個參數,說明刪除從下標2開始的所有的后面的元素
var nums = [0,1,2,3,4,5,6,7]; nums.splice(2,1); //[0, 1, 3, 4, 5, 6, 7] //如果加入兩個參數,則為刪除從下標2開始的后面的幾個元素。
var nums = [0,1,2,3,4,5,6,7]; nums.splice(2,1,"a","b","c"); //[0, 1, "a", "b", "c", 3, 4, 5, 6, 7] //三個或多個參數,意味着刪除從下標2(第一個參數)開始的后面的1個(第二個參數)元素,並在下標2的后面加入從第三個參數開始的后面的所有參數,把第二個參數設置為0就可以不刪除元素從而實現從任意位置添加元素
再多說一點,我們還可以使用delete操作符來刪除數組中的元素,但是實際上,delete只是刪除了對應下標上所存儲的值,並沒有同時把存儲值得空間也刪除掉,會導致對應位置上的值為undefined:
var nums = [0,1,2,3,4,5,6,7]; delete nums[2]; //[0, 1, undefined, 3, 4, 5, 6, 7]
splice()方法是修改了原數組的。
6、slice()
slice()方法,會返回參數選定的范圍的數組。該方法有兩個參數,start(必選)和end(可選)。這兩個值可以為負數,如果為負數則默認從尾部的第一個參數算起,也就是說-1就是數組的最后一個元素,-2就是數組的倒數第二個元素,以此類推。如果不傳end,則默認從start開始直到數組最后一個元素都會被截取。
var nums = [0,1,2,3,4,5,6,6,7,"a",9,10,{name:"zaking"},["b","c"]]; var a = nums.slice(1,5); console.log(a);//[1, 2, 3, 4] var b = nums.slice(-1,5); console.log(b);//[] var c = nums.slice(-1,-5); console.log(c);//[] var d = nums.slice(-5,-1); console.log(d);// ["a", 9, 10, {…}] var f = nums.slice(5,1); console.log(f);//[] var x = nums.slice(5); console.log(x);// [5, 6, 6, 7, "a", 9, 10, {…}, Array(2)] var y = nums.slice(-5); console.log(y)//["a", 9, 10, {…}, Array(2)]
希望大家仔細看一下這個例子,當然,我還是一句話說明一下吧。
其實主旨就是,你所傳的參數無論正負,參數所限定的范圍必須是包含數組元素的。