用js來實現那些數據結構 第一章


 在開始正式的內容之前,不得不說說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]

  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)]
復制代碼

  希望大家仔細看一下這個例子,當然,我還是一句話說明一下吧。

  其實主旨就是,你所傳的參數無論正負,參數所限定的范圍必須是包含數組元素的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM