摘要:沒有循環(huán)循環(huán)次四屬性屬性屬性表示數(shù)組元素的數(shù)量,的數(shù)組元素并不是連續(xù)的,有些索引的位置可能沒有元素,所以屬性并不能真正表示元素的數(shù)量,其值等于數(shù)組最大索引。
一、JS沒有“真正的數(shù)組”
像C++,Java這些編程語言中數(shù)組元素分配的內(nèi)存都是連續(xù),這有利于性能提升,但是JS的數(shù)組不是這樣的。它使用對象模擬數(shù)組,即對象屬性為數(shù)字,并含有l(wèi)ength屬性。所以JS數(shù)組對象的內(nèi)存不是連續(xù)的,同一般對象內(nèi)存分配。
二、創(chuàng)建數(shù)組 2.1 字面量方式var a = [], // 定義空數(shù)組 b = [1,true], // 數(shù)組元素用逗號隔開 c = [1,,3], // 忽略中間的元素 d = [1,2,]; // 末尾是逗號
注意:
數(shù)組元素類型可以各不相同,因為JS數(shù)組本質(zhì)是個對象;
b[1]元素是未定義的,不是取值是undefined的元素;
數(shù)組d的長度是2,不是3,因為字面量準(zhǔn)許末尾是逗號。
2.2 使用構(gòu)造函數(shù)Arrayvar a = new Array(), // 等價 [] b = new Array(2), // 等價 [,,], 注意這里是兩個逗號哦 c = new Array(1,2), // 等價 [1, 2] d = Array(1,2); // 等價于new Array(1,2)
注意:
使用構(gòu)造函數(shù)Array比較坑的就是不同數(shù)量的參數(shù),Array函數(shù)的行為不一致。
Array即是構(gòu)造函數(shù)也是工廠函數(shù)。即new Array() 等價于直接調(diào)用Array();
三、索引和屬性名稱訪問對象的屬性是通過屬性名稱,而訪問數(shù)組的元素則是通過索引。索引即為數(shù)組元素的下標(biāo)。索引是32位的正整數(shù),有效取值范圍是[0, 2^32 - 2](因為數(shù)組的length屬性也是32位整數(shù),所有下標(biāo)最大為2^32-2),不在這個范圍的值都不是索引。雖然JS沒有整數(shù)類型,但索引的操作都是按照32位正整數(shù)方式處理的。數(shù)組本質(zhì)也是對象,也是可以通過屬性名稱的方式訪問數(shù)組的屬性。
var a = [1,2], b = { 0: 1, 1: 2 }; console.log(a[1]); // 索引訪問方式 console.log(a["1"]); // 索引訪問方式,會把"1"轉(zhuǎn)成正整數(shù)1 console.log(b[1]); // 屬性名稱訪問方式,會把1轉(zhuǎn)成字符串“1”
注意:
索引是一種特殊的屬性名稱;
屬性名稱方式會把中括號里的表達(dá)式轉(zhuǎn)成字符串,索引方式會把中括號里的表達(dá)式轉(zhuǎn)成32整數(shù),如果不是合法的索引,則視為屬性名稱,所以JS數(shù)組不存在下標(biāo)越界的問題。
3.2 稀疏數(shù)組JS數(shù)組元素不一定是連續(xù)的,索引位置上沒有元素(沒有元素跟取值是undefined的元素是不同的)的數(shù)組叫稀疏數(shù)組。
var a = [,], // 定義即為稀疏數(shù)組 b = Array(3), // 定義即為稀疏數(shù)組 c = [1,2,3]; delete c[1]; // delete操作造成稀疏
注意:
再強(qiáng)調(diào)索引位置上沒有元素跟取值是undefined的元素不一樣的(有些數(shù)組的方法, 運(yùn)算符的行為不一樣)。
for(var a in [,]) {console.log(1)} // 沒有循環(huán) for(var a in [1,2]) {console.log(1)} // 循環(huán)2次四、length屬性 4.1 length屬性
length屬性表示“數(shù)組元素的數(shù)量”,JS的數(shù)組元素并不是連續(xù)的,有些索引的位置可能沒有元素,所以length屬性并不能真正表示元素的數(shù)量,其值等于數(shù)組最大索引+1。并且length屬性是可寫的
var arr = [1]; arr.length; // 1 arr.length = 3; // 增大length屬性值 arr.length;// 3, 索引1,2位置是未定義的元素。 arr.length = 0; // 減小length屬性值 arr[0]; //undefined4.2 偽數(shù)組
行為有點(diǎn)像數(shù)組的對象叫偽數(shù)組。廣義上只要含有l(wèi)ength屬性且length值是在索引有效取值范圍內(nèi)(或可以通過類型轉(zhuǎn)換成有效索引)的對象都可以視為偽數(shù)組。偽數(shù)組可以應(yīng)用數(shù)組的一些方法,也可以反過來定義:可以應(yīng)用數(shù)組方法的對象叫偽數(shù)組對象。
var a = {length: 2}; // a是偽數(shù)組 Array.prototype.slice.call({length: 2}); // 可以應(yīng)用slice方法,其結(jié)果等價于Array(2)的結(jié)果五、方法 5.1 ES3
主要是操作元素相關(guān)的方法
1. push/pop 2. unshift/shift之前一直混淆unshift和shift的功能。一般都記得push是向數(shù)組尾部插入數(shù)據(jù),pop是從數(shù)組尾部彈出元素,可以借助push/pop記憶unshift/shift。push名字比pop長,而unshift名字也比shift長。即push和unshift功能相似,并且名字都比對應(yīng)功能的方法pop/shift名字長。長對長,短對短,估計再也不會混淆unshift和shift方法的功能了。
3. join最近看到某個框架源碼有這么個片段:
var indent = ""; for (i = 0; i < space; i += 1) { indent += " "; }
大概意思就是根據(jù)參數(shù)space生成指定長度的空格字符串??梢酝ㄟ^join方法改進(jìn)下哈:
var indent = Array(space + 1).join(" "); // 記得+1,否則字符串長度少1
join方法會把值為undefined/null的數(shù)組元素轉(zhuǎn)成空字符串。
4. reverse 5. sort 6. concat一直以為該方法用于多個數(shù)組合并,其實除了的功能外還可以把非數(shù)組類型的參數(shù)插入返回值數(shù)組里。
var a = [1, 2]; a.concat([3, 4]) // [1, 2, 3, 4] a.concat(3, 4) // [1, 2, 3, 4]7. slice 8. splice
splice方法可以實現(xiàn)對數(shù)組任意位置,任意數(shù)量的元素進(jìn)行增加,替換,刪除操作。
var a = [1, 2, 3, 4, 5]; // 替換:將元素2,3替換成10,11 a.splice(1, 2, 10, 11) console.log(a) // [1, 10, 11, 4, 5] // 刪除:刪除10,11 a.splice(1, 2) // [1, 4, 5] // 插入:在元素4后面插入元素22,23,24 a.splice(2, 0, 22, 23, 24) console.log(a) // [1, 4, 22, 23, 24, 5]
splice的返回值是被刪除或者替換的元素的集合
大部分情況我們經(jīng)常對數(shù)組的首尾進(jìn)行添加刪除操作,所以一般使用push/pop, unshift/shift方法多些。
5.2 ES5主要是遍歷和基于遍歷的搜索、診斷相關(guān)的方法
1. forEach 2. map 3. filter 4. every/some 5. reduce/reduceRight是否指定初始值循環(huán)的次數(shù)不一樣的
reduce應(yīng)用場景很多,認(rèn)真看下MDN Demos,還有這個面試題
改成純Promise版:
function genTask(action, delay, context) { return function() { return new Promise(resolve => { action && action.call(context); setTimeout(resolve, delay == null ? 0 : (delay * 1000)) }) } } function machine(name) { var tasks = []; tasks.push(genTask(function() { console.log(`start ${name}`) })) function execute() { var self = this; tasks.reduce((promise, task) => { return promise.then(task) }, Promise.resolve()) } function _do(task) { tasks.push(genTask(function() { console.log(`${name} ${task}`) })) return this } function wait(delay) { tasks.push(genTask(() => { console.log(`wait ${delay}s`); }, delay, null)) return this } function waitFirst(delay) { tasks.unshift(genTask(() => { console.log(`wait ${delay}s`); }, delay, null)) return this } return { name: name, execute: execute, do: _do, wait: wait, waitFirst: waitFirst } } machine("ygy") .waitFirst(3) .do("eat") .execute();
Demo 重學(xué) JS:為啥 await 在 forEach 中不生效這里也有個題目可以用reduce實現(xiàn):
function fetch(x) { return new Promise((resolve, reject) => { console.log(x) setTimeout(() => { resolve(x) }, 500 * x) }) } async function test() { let arr = [3, 2, 1] await arr.reduce(async (promise, item) => { await promise; console.log(item) return await fetch(item); }, Promise.resolve()) console.log("end") } test();6. indexOf/lastIndexOf
采用絕對相等(===)的判斷邏輯。
7. Array.isArray 注意:forEach, map, filter, every/some, reduce/reduceRights, indexOf/lastIndexOf都會有遍歷數(shù)組的行為,可以根據(jù)不同的需求選用不用的遍歷方法,并且都不會遍歷數(shù)組中被刪除或從未被賦值的元素,見稀疏數(shù)組;
有人嘗試把a(bǔ)sync函數(shù)作為上述數(shù)組具有遍歷功能的回調(diào)函數(shù),但可能得到意想不到的結(jié)果,比如這個重學(xué) JS:為啥 await 在 forEach 中不生效。不僅僅是forEach,其他的遍歷方法也都只處理同步代碼。
異步函數(shù)的返回值是個Promise對象,相當(dāng)于這些遍歷方法實際在操作Promise對象。
5.3 ES6主要是添加了新的功能,讓數(shù)組使用的更加方便
1. copyWithin 2. entries 3. fill 3. find 4. findIndex功能類似ES5點(diǎn)indexOf,參數(shù)不同,是indexOf的加強(qiáng)版:更靈活,使用回調(diào)函數(shù)可以更靈活的控制相等判斷邏輯。
5. includes判斷數(shù)組是否包含指定的元素,在此之前我們一般借助indexOf方法的返回只是否為-1判斷元素是否存在():
var a = [1, 2, 4]; a.indexOf(1) !== -1 // true, 存在 a.indexOf(6) !== -1 // false, 不存在
ES6引入includes方法專門用來判斷元素是否存在,并且采用的是0值相等的等值判斷算法,indexOf方法采用的絕對相等算法。
var a = [1, NaN]; a.includes(NaN) // true, 存在 a.indexOf(NaN) !== -1 // false, 不存在6. keys 7. values 8. [Symbol.iterator] 9. [Symbol.species] 10. Array.of
我們都知道Array的構(gòu)造函數(shù)根據(jù)的參數(shù)數(shù)量的不同具有不同的行為:
Array(7); // 一個參數(shù)表示數(shù)組的長度:構(gòu)建長度為7的數(shù)組 Array(1, 2, 3); // 多個參數(shù)表示數(shù)組的元素:構(gòu)建數(shù)組為[1, 2, 3]
而Array.of方法統(tǒng)一了這種行為,都是用來根據(jù)元素構(gòu)建數(shù)組:
Array.of(7); // [7] Array.of(1, 2, 3); // [1, 2, 3]11. Array.from 參考
MDN Array
MDN Array.prototype
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92569.html
摘要:新建數(shù)組新建數(shù)組的方法有三種方法一方法二方法三新增是中新增的將一組值轉(zhuǎn)換為數(shù)組的方法,該方法的出現(xiàn)時為了彌補(bǔ)構(gòu)造函數(shù)因為參數(shù)不同導(dǎo)致的不同行為。 原文鏈接:http://mrzhang123.github.io/2016/08/03/js-Array 在ECMAScript中最常用的類型之一就是Array類型,Array類型的方法也有很多,所以在這篇文章中,梳理一下Array類型的方法...
閱讀 2458·2019-08-29 13:53
閱讀 2530·2019-08-29 11:32
閱讀 3082·2019-08-28 17:51
閱讀 3840·2019-08-26 10:45
閱讀 3547·2019-08-23 17:51
閱讀 3015·2019-08-23 16:56
閱讀 3359·2019-08-23 16:25
閱讀 3118·2019-08-23 14:15