1. 程式人生 > >用js來實現那些數據結構(數組篇01)

用js來實現那些數據結構(數組篇01)

指定 賦值 重要 原始類型 delete 號稱 如果 開發 實現原理

   在開始正式的內容之前,不得不說說js中的數據類型和數據結構,以及一些比較容易讓人混淆的概念。那麽為什麽要從數組說起?數組在js中是最常見的內存數據結構,數組數據結構在js中擁有很多的方法,很多初學者記不清數組的大多數用法,只知道push,pop,shift等最基本的幾個。所以,本系列(數組篇)會盡可能的讓大家對數組有一個透徹的了解。也方便後面其他數據結構的學習和使用。

   可能很多web前端開發者都會有一個疑問,那就是,數組和對象究竟是數據類型?還是數據結構?那麽我們就帶著這樣的疑問,開始下面的學習,希望看完這篇文章之後,你模糊的概念會變得清晰一些。

  首先,在js中,數據類型分為兩種,基本類型

(原始類型)和復雜類型,其中,基本類型是:String(字符串),Number(數值),Boolean(布爾值),還有undefinednull。復雜類型是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]

  那麽數組的一些基本用法就先介紹到這裏,後面應該還有兩篇左右的長度來介紹數組。花費如此的篇幅,實在是數組真的極為重要,還請大家不要著急。當真正的學會了數組之後,再去看棧,隊列這種數據結構,其實就很簡單了。

  最後,由於本人水平有限,能力與大神仍相差甚遠,若有錯誤或不明之處,還望大家不吝賜教指正。非常感謝!

用js來實現那些數據結構(數組篇01)