javascript快速初始化數組

来源:https://www.cnblogs.com/ctxb/archive/2022/06/29/16424899.html
-Advertisement-
Play Games

編寫代碼中通常會有快速初始化數組的需求,例如我們需要一個類似matlab里的zeros函數,假如這裡我們需要生成一個0-23的數組用於表示一天24小時。 最基本的做法如下: function(){ let hours = []; for(let k = 0; k < 24; k++ )hours.p ...


編寫代碼中通常會有快速初始化數組的需求,例如我們需要一個類似matlab里的zeros函數,假如這裡我們需要生成一個0-23的數組用於表示一天24小時。
最基本的做法如下:

function(){
    let hours = [];
    for(let k = 0; k < 24; k++ )hours.push(k);
    return hours;
}

下麵我們來思考如何用更優雅的方式實現。
考慮使用new Array(24)+ map的方法來實現。
代碼如下:

Array(24).map((_, h) => h);

註意,這裡map的第二個參數是索引,平時用的少,這裡把索引作為數值。
結果與預期並不符合,為啥呢?
簡單搜索了一下,發現時因為js里的稀疏數組的邏輯導致的。
我們先看一下下麵的代碼:

let a = [];
a[1000] = 2;
console.log(a.length);
// 1000
a.forEach(x => console.log("hello"));
// only one "hello"

js的處理邏輯是,對於沒有主動賦值的位置進行“空置”處理,對於這些“空置”未知,迭代器是不會理會的,這麼做最主要的目的就是避免不合理的賦值操作導致的bug。
假設沒有這種邏輯,我們寫下了new Array(Date.now()),這將導致系統新建一個非常大的數組,而實際上啥也沒存。
我們可以吧new Array(len)乾的事情簡單理解為下麵的過程:

function(len){
    let r = [];
    r.length = len;
    return r;

這就是為什麼對new Array(len)調用map或者forEach的時候跟預期不一致了。
如何解決這一問題呢,除了使用new Array(len)的形式,我們還可以使用new Array(1,2,3)這種寫法來初始化數組,但是這麼寫就沒法實現我們編寫初始化數組的目的了。
這個時候我們想到了apply,這個函數的第二個參數正好就是一個數組,於是我們寫下了下麵的代碼。

// 借用apply
Array.apply(null, Array(24)).map((_, h) => h);
// [0, 1, ..., 24]

得到了我們希望的結果。這就說明,Array(24)apply中作為參數的時候是被當做24個值對待的,因為這一點就保證了最後得到的數組長度是24。
既然如此,我們當然同樣可以使用apply的姊妹函數call

// 借用call
Array.call(null, ...Array(24)).map((_, h) => h);
// [0, 1... 23]

這也更確認了一件事,Array(len)解構會得到len個參數而非一個參數,當然call的使用必須在支持解構操作符的環境中。

在熟悉了callapply的原理後,我們可以進一步寫出下麵的代碼:

// Array本身
Array(...Array(24)).map((_, h) => h);
// [0, 1, ..., 24]

這種形式已經足夠優雅了。
另外,在ES6中,Array提供了新方法fill,借用該方法填充那些“空置”位,進而保證後續的操作能順利進行。
具體代碼如下:

// 推薦
Array(24).fill(null).map((_, h) => h);

現在也比較推薦最後一種寫法,這種方法也最為直觀。
不過需要註意fill方法的使用,應該儘量避免盲目地填充,因為這樣會上面提到了js設計“空置”邏輯為了避免的bug。
有興趣的可以嘗試一下下麵的代碼:

// no-fill
console.time("no-fill");
let t = Array(5e7);
console.timeEnd("no-fill");
// fill
console.time("fill");
let q = Array(5e7).fill(null);
console.timeEnd("fill");
// => no-fill: 0.240ms
// => fill: 3247.921ms

在瀏覽器中嘗試瀏覽器基本會不響應,沒有設置更大的數值為了避免得不到結果。假設一個int占用4個位元組的記憶體,這個fill會占用200M的記憶體,且需要迴圈5千萬次,這必然會占用大量的CPU和記憶體,在單線程的js中是絕對不允許的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 2022年6月28日,HDD·HMS Core.Sparkle影音娛樂沙龍線上上與開發者們見面。HMS Core音頻編輯服務(Audio Editor Kit)專家為大家詳細分享了基於分離的3D音樂創作技術,引起了行業及音樂愛好者的關註。 音頻3D化是音頻發展的重要方向,但當前從源頭製作3D音頻成本 ...
  • 華為帳號是打開華為生態服務的一把鑰匙,只需一個華為帳號,即可在華為全場景設備上使用華為應用市場、華為音樂、華為雲空間、華為錢包等眾多優質的華為應用服務。同時,華為帳號綁定的所有會員權益、購買記錄、收藏/喜歡等數據,也會在不同設備間一鍵同步,輕鬆實現自由切換。 登錄華為帳號後,您可以在多台設備上,快捷 ...
  • Javascript趣味程式從需求到實現-體重測量器 Version 0.0.1 一、需求梳理 二、分析結果: 1、需要提供輸入身高、體重、以及選擇性別的HTML組件,如input、select 2、需要對信息進行驗證,專門的工具類完成這個職責如 “BmiUtils” 3、無效的信息需要提示 4、與 ...
  • 一、效果圖 二、實現邏輯 將需要動態添加的表單項項的綁定值存為一個數組 以迴圈的方式展示form表單 點擊`+`按鈕觸發事件,向數組中新加一個item 點擊`-`按鈕觸發事件,根據迴圈的得到的index來刪除數組中相對應位置的item 三、代碼實現 <template> <div> <el-butt ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 JS是一門單線程語言,單線程就意味著,所有的任務需要排隊,前一個任務結束,才會執行下一個任務。這樣所導致的問題是:如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染載入阻塞的覺。為瞭解決這個問題,JS中出現了同步和異 ...
  • 一、效果圖 二、代碼實現 註:需要安裝依賴 pnpm i sortablejs -S <template> <div style="padding: 15px"> <h3 style="text-align: left; padding: 10px; background: #ccc"> vue+e ...
  • 1. Text 的絕對居中 Android中顯示時會有預設的padding保留,導致垂直居中會有誤差 //不寫下麵兩個,Android系統上文字會偏下* includeFontPadding: false, textAlignVertical: "center", Text省略號顯示 <Text n ...
  • 2.兩數相加 給你兩個 非空 的鏈表,表示兩個非負的整數。它們每位數字都是按照 逆序 的方式存儲的,並且每個節點只能存儲 一位 數字。 請你將兩個數相加,並以相同形式返回一個表示和的鏈表。 你可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。 示例 1: 輸入:l1 = [2,4,3], l2 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...