欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript稀疏數組示例教程

 更新時間:2022年06月27日 09:46:59   作者:錯碼匠  
這篇文章主要為大家介紹了JavaScript稀疏數組的使用示例教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

最近有空在看一本關于 JS 數據結構和算法的書,里面有提到數組,卻對數組的基本概念輕輕帶過,雖然用了 JS 很久但是一直忙于需求業(yè)務的實現從未停下好好回視一下這個 既熟悉又陌生的朋友,于是查閱了一些資料,尤其是密集數組和稀疏數組的區(qū)別,意猶未盡之下,寫了這篇文章,以便更好地幫助理解書中的要點,稍顯淺顯,也有不足望各位提點。

什么是稀疏數組?

通常編程語言中(C、JAVA等)數組都是預先設定好長度的,他們的內存占用是固定的,內存地址是連續(xù)不間斷、緊密相連的,我們稱之為密集數組,好比 JS 中類型化數組(TypedArray)的 ArrayBuffer,但我們這里著重要說的是通過 Array 創(chuàng)建的數組,它其實是個對象,當我們通過 new Array() 創(chuàng)建一個數組時,它只是一個帶有 length 屬性的數組對象,我們可以像對象一樣去操作它的屬性:

let array = new Array(10)
// 下標可以是任何的字符串,就像操作 Object 一樣
array.name = 'This is an Array.'
array['name'] = 'This is an Array.' // 等效 array.name

雖然可以像操作 Object 那樣為數組對象添加屬性,但是真正計入數組元素的只能是以整數類型的字符作為下標去映射值的元素,同時會影響其長度屬性 length,我們接上段代碼繼續(xù):

// 雖然之前賦上了一個新的屬性 name,但是其長度仍然輸出10,而非11
console.log(array.length) // 10
// 用整數類型下標定義一個數組元素才會計入數組長度
array['0'] = 'first' // 下標其實都是字符串
array[11] = 'eleventh' // 看起來這個下標是一個數字,但是 JS 會自動把它轉為字符
console.log(array.length) // 12

長度屬性是可以手動變更的:

array.length = 100
console.log(array.length) // 100

數組對象本身可能不占用太多內存,它只是包含了映射關系和長度,真正占用內存的是元素所映射的目標,也就是“鍵值”中的“值”。在V8引擎里,JS 的數組得到進一步的優(yōu)化,其中有個概念叫 Holey(有孔洞的),也就是那些沒有被指明映射關系的空間,他們不占用內存。如上看到,作為一門動態(tài)語言,我們隨時可以向這個數組對象里添加、修改元素映射,也能隨時改變其長度 length。自然地,其元素所占的內存地址也就無所謂固定連續(xù)了,我們稱這種數組為稀疏數組(Sparse Array)。

創(chuàng)建帶有孔洞的稀疏數組

  • 使用 Array 構造函數:
let sparse = new Array(100)
  • 通過字面量:
let sparse = []
// 用一個超過原始長度的下標為元素賦值,也就為該元素創(chuàng)建了一個映射關系,同時改變了該數組的長度
sparse[99] = 'last'
console.log(sparse.length) // 100
// 用對象字面量書寫數組時,允許元素留空
sparse = [, , ,] // 這就創(chuàng)建了長度為3的空洞的數組
console.log(sparse.length) // 3
  • 手動修改一個大于原數組長度的 length 值:
let sparse = ['red', 'green', 'blue'] // 三個元素的數組
sparse.length = 100 // 此時長度已是100,但有效元素仍然只有3個

刪除元素的映射

從數組中刪除某個元素可以使用 pop、shift、splice 方法,那如何解除元素與某個對象的映射關系呢?我們可以像操作對象一樣用 delete,它不會刪除映射目標,僅僅是將元素和目標對象的關聯(lián)斷開,從而形成一個孔洞,所以也不會改變這個數組的 length。

let one = '壹'
let array = []
array[0] = one // 將數組的第一個元素指到對象 one,長度變?yōu)?1
console.log(array, array.length) // ['壹'], 1
delete array[0] // 刪除數組第一個元素的映射關系
console.log(array) // [空]
console.log(array.length) // 因為只是刪除了元素的映射,長度并沒有改變,仍然輸出 1
console.log(one) // one 的值并不會刪除,仍然保留,輸出 '壹'

現象

我們說到,JS 的數組本質上是對象——由整數字符作為下標與目標值構成映射關系的自帶長度屬性的對象,長度可以大于有效(已創(chuàng)建映射關系的)元素的個數。從映射狀態(tài)來看,完全映射的數組有著和傳統(tǒng)密集數組類似的表現,而不完全映射的數組在生產中會有些特別,但又在情理之中。

  • 訪問沒有映射關系的數組元素時,相當于一個申明了卻沒有定義值的變量,所以會輸出 undefined:
let sparse = new Array(10)
console.log(sparse[0]) // undefined
  • 不完全映射的數組,在用 map()、forEach() 等方法做遍歷時,它們只會遍歷已有映射關系的元素:
// 此時數組元素的映射關系一個都沒有創(chuàng)建,所以 forEach 不會有任何輸出
sparse.forEach((value, i) => {
  console.log(i, value)
}) // nothing
// 根據下標為最后一個元素賦值
sparse[sparse.length - 1] = 'tenth'
// 只會輸出已建立映射的元素 sparse[sparse.length-1] 的值 'tenth'
sparse.forEach((value, i) => {
  console.log(i, value)
}) // 9, tenth
  • 使用 for 語句也只是用數組的 length 值作為循環(huán)依據,它不會主動判斷當前位置是否有映射值,所以當循環(huán)體試圖通過下標訪問沒有映射關系的位置時,會輸出 undefined:
for( let i = 0; i < sparse.length; i += 1){
  console.log(i, sparse[i])
}
  • 映射完全的數組,可以被所有常用數組方法遍歷:
let array = ['1', 'day', 'white', 'Jake', undefined, null, 0] // 一個完全映射的數組
// 輸出每個元素,包括null、undefined、0
array.forEach((value, i) => {
  console.log(i, value)
})
  • 在做 some()、every() 等操作時,不完全映射的數組的表現是特殊的,但也在情理之中,這取決于這些方法的設計,例如 some(),即便長度大于0,但因為其中沒有任何建立映射的元素,所以,相當于給一個空數組([])做操作:
let sparse = new Array(10)
// 由于還沒有建立映射關系,所以 some 的回調也沒有觸發(fā),于是得到的結果依然是 false
console.log(sparse.some(item => !item)) // false
// 在所有元素都被賦值后,用同樣的回調,some 的結果發(fā)生了變化
sparse.fill(false) // 賦值
console.log(sparse.some(item => !item)) // true
  • 當把長度設成小于實際元素個數的值時,會把超出長度的元素從當前數組中剔除:
let array = ['one', 'two', 'three']
array.length = 1
console.log(array) // ['one']

稀疏數組的快速映射(強制創(chuàng)建映射關系)

只是讓數組中的映射元素個數與長度屬性相同,并不能改變其稀疏的特性:

let sparse = new Array(5)
// Array.apply
let array1 = Array.apply(null, sparse)
// Array.from方法
let array2 = Array.from(sparse)
// 解構
let array3 = new Array(...sparse)
let array4 = [...sparse]
// 把所有元素映射為 undefined 了
array1.forEach((item, i) => {
  console.log(i, item) // 輸出 undefined × 5
})
……

總結

以上是對 JS Array 數組的粗淺認知,在 JS 這門動態(tài)語言里,通過 Array 所創(chuàng)建的數組無所謂疏密,因為它們本質上還是對象。在實際生產時,對于數據集合的操作應當盡量保持映射完全,避免不合預期的意外,更多關于JavaScript稀疏數組教程的資料請關注腳本之家其它相關文章!

相關文章

  • JavaScript的面向對象編程基礎

    JavaScript的面向對象編程基礎

    這篇文章主要介紹了JavaScript的面向對象編程基礎,是JavaScript入門學習中的重要知識概念,需要的朋友可以參考下
    2015-08-08
  • 原生javascript 學習之js變量全面了解

    原生javascript 學習之js變量全面了解

    下面小編就為大家?guī)硪黄鷍avascript 學習之js變量全面了解。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • JavaScript中判斷對象類型的幾種方法總結

    JavaScript中判斷對象類型的幾種方法總結

    本篇文章是對JavaScript中判斷對象類型的幾種方法進行了詳細的總結介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-11-11
  • 詳解javascript void(0)

    詳解javascript void(0)

    這篇文章主要介紹了javascript void關鍵字的相關資料,文中講解非常細致,幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-07-07
  • Typescript中的as、問號與感嘆號詳解

    Typescript中的as、問號與感嘆號詳解

    這篇文章主要介紹了Typescript中的as、問號與感嘆號詳解,本文分別講述了這幾個關鍵字的含義作用以及實例,通過文字和代碼的描述,詳細的表達.以下就是詳細內容,需要的朋友可以參考下
    2021-07-07
  • JavaScript基礎重點(必看)

    JavaScript基礎重點(必看)

    下面小編就為大家?guī)硪黄狫avaScript基礎重點(必看)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • 談談關于JavaScript 中的 MVC 模式

    談談關于JavaScript 中的 MVC 模式

    本文介紹了模型-視圖-控制器模式在 JavaScript 中的實現,有需要的朋友可以參考一下
    2013-04-04
  • Javascript基礎教程之數據類型 (字符串 String)

    Javascript基礎教程之數據類型 (字符串 String)

    javascript一共有9種數據類型,分別是字符串 String、數值型 Number、布爾型 Boolean、未定義 Undefine、空值 Null、對象 Object、引用Refernce、列表型 List、完成型 Completion,我們今天首先來看看(字符串 String)
    2015-01-01
  • Javascript this 關鍵字 詳解

    Javascript this 關鍵字 詳解

    Javascript是一種很靈活的語言, 而This關鍵字又是靈活中的靈活, 但是因為它的靈活, 也注定了它的難用.以前我用this的時候, 都會覺得不踏實, 老是擔心它不知道怎么地就會指到另外的什么地方.其實, 這都是因為, 我們對它的不了解.
    2014-10-10
  • 使用 stylelint檢查CSS_StyleLint

    使用 stylelint檢查CSS_StyleLint

    你需要一個防止錯誤產生的機器,可以理解CSS并且理解你:你的意圖、喜好、主意以及弱點。 只要是它可以阻止的錯誤它都會持續(xù)阻止。同時,你和你的同事可以一直改善機器,擴展它的功能并且削弱其局限性。
    2016-04-04

最新評論