摘要:總結使用訪問數組元素,使用訪問數組屬性,如。數組的長度保證大于每個元素的索引值,數組沒有元素,最大索引為,為為數組元素賦值,如果其索引大于等于現有數組長度,的屬性值將設置為如果設置的值小于數組長度時,會將索引大于的元素全部刪除。
數組
數組是值的有序集合,數組中每個值稱為元素,元素在數組中的位置稱為索引。JavaScript中的數組是一種特殊的對象:
類屬性class attribute為Array
新元素添加到數組后,自動更新自身的length屬性
從Array.prototype對象中繼承方法
設置length屬性值小于元素個數時,會截斷數組
數組的特點JavaScript中,數組的元素可以是任意JavaScript值,并且同一個數組中不同元素值的類型可以不同
數組的索引是基于0的32位數值,最大的索引為(2^32 - 1) - 1
數組是動態的,可以根據需要增長或縮短
數組的操作方法大部分定義在Array.prototype原型對象上,使所有的數組對象都可以使用
數組的實現經過了優化,用索引訪問元素的效率高于直接訪問常規對象的屬性
數組可能是稀疏或者稠密的。
1 數組的創建與訪問 1.1 創建數組有兩種方法可以創建數組:數組字面量[1, 2, 3]和new Array(1, 2, 3)。推薦使用數組字面量創建數組,簡潔易懂。
對象字面量創建的數組,其元素可以是表達式、對象或其他數組。如果省略數組中字面量的值,數組會變為稀疏數組。
var empty = []; // <==> var empty = new Array();數組字面量的寫法更簡潔 var primes = [2, 3, 5, 7, 11]; var misc = [1.1, true, "a"]; //數組中元素可以是任意類型值 var base = 1024; var table = [base, base + 1, base + 2, base + 3]; // ==> [ 1024, 1025, 1026, 1027 ] var b = [[1, {a: "1", b: 2}], [true, {x: 2, y:3}]];
通過Array()構造函數也可以創建數組,但是使用比較繁瑣,根據傳入參數個數的不同,分為三種情況:
不傳入參數:var a = new Array();a數組與[]相同
傳入一個非負整數:var a = new Array(10);創建一個存放10個數組元素的空間,但是此時沒有定義索引屬性和存儲值,此時的數組是稀疏的
傳入2個或多個數組元素或者一個非數值元素:var c = new Array("1", 2, true, "text");,創建的數組["1", 2, true, "text"]
稀疏數組與稠密數組根據數組是否有不連續的數組,將其分為稀疏數組和稠密數組
稀疏數組的length屬性大于元素的個數,在實現上比稠密數組更慢,消耗內存空間更大,查找元素的效率與常規對象相似。
要避免使用稀疏數組,其查找效率很低。稀疏數組空缺的部分沒有值和索引,因為不能用for-in循環遍歷出空缺的部分,for-in循環可以遍歷對象的可枚舉屬性(自身和繼承)
var undefs = [, , ]; //數組字面量允許逗號結尾,是稀疏數組,沒有元素,使用for-in循環不會輸出任何內容 var count = [1, , 3]; //稀疏數組,使用for-in循環只輸出[1, 3] var arr = new Array(10); //稀疏數組,沒有賦值和索引 a = new Array(5); //數組沒有元素,a.length為5,稀疏 a[1000] = 0; //a.length為1001,索引大于元素個數,稀疏 a = [, , , ]; //是稀疏數組,0 in a; => false a = [1, , 3]; //稀疏數組,長度為3 a = [,]; //數組沒有元素,長度是1
總結:數組創建盡量使用字面量方法,如果數組的索引不連續,則數組是稀疏數組,查詢效率低,內存消耗高
1.2 數組的訪問數組是特殊的對象,可以利用對象屬性的訪問方式.和[],因為數組元素的索引是非負數的字符串,所以需要使用[]訪問,而數組的屬性(如length則可以用.訪問)。
利用[]可以讀寫數組的元素:
var a = ["Hello"]; var value = a[0]; //讀取第一個元素 a[1] = 3.14; //寫入第二個元素
數組是特殊的對象:
所有的數組都是對象,但對象不一定是數組;
數組對象的屬性名在0~2^32-2之間的是索引,可以為數組創建任意屬性,只有當屬性是索引時,才更新其length屬性
使用負整數、與整數等的浮點數作為屬性時,會將其轉化為索引
a[-1.23] = true; //創建一個名為"-1.23"的屬性 a[-3] = false; //創建一個名為"-3"的屬性 a["1000"] = 0; //數組的第1001個元素為值為0 a[2.000]; //與a[2]相同
注:JS中沒有越界的概念,因為是將數組作為對象來處理,對于不存在的下標,將其當做普通屬性添加到數組對象上。
總結:使用[]訪問數組元素,使用.訪問數組屬性,如.length。
1.3 數組的長度對于稠密數組,其length屬性代表元素的個數,索引從0開始,最大值是length - 1。如果是稀疏數組,其length屬性大于元素的個數。數組的長度保證大于每個元素的索引值
[].length; //==>0,數組沒有元素 [1, 2, 3].length; //==>3,最大索引為2,length為3
為數組元素賦值,如果其索引i大于等于現有數組長度,length的屬性值將設置為i+1
如果設置的length值n小于數組長度時,會將索引大于n的元素全部刪除。
在ES5中,可以通過Object.defineProperty()設置數組的length屬性的描述符descripter為{writable: false},使其變為只讀屬性,設置之后不能添加或者刪除數組元素
a = [1, 2, 3, 4, 5]; a.length = 3; //數組變為[1, 2, 3] a.length = 0; //刪除所有數組元素 a = [1, 2, 3]; //注意設置為只讀后,不能在為數組添加元素,除非修改writable為true Object.defineProperty(a, "length", {writable: false}); a.length = 2; //a.length不會改變 a.length; //==>32 數組的操作
在Array.prototype對象中定義許多關于數組操作的方法。
2.1 數組元素的添加與刪除 push()和unshift()方法push()方法:在數組末尾插入一個或多個元素,與pop()方法相對應,返回插入元素后數組的新長度
unshift()方法:在數組的首部插入一個或多個元素,與shift()方法相對應,返回插入元素后的數組新長度。注意一次插入多個元素和多次插入一個元素的效果是不同的
pop()和shift()方法pop()方法:在數組末尾刪除一個元素,返回刪除的元素;
shift()方法:在數組首部刪除一個元素,返回刪除的元素;
var a = []; a.push("one"); // ==> ["one"],在末尾添加一個元素 a.push("two", "zero"); // ==> ["one", "two", "zero"],在末尾添加兩個個元素 a.pop(); // ==>"zero",a變為["one", "two"] a.unshift("four"); // ==> a變為["four", "one", "two"] a.shift(); // ==> 刪除"four"
注:會修改調用該方法的數組
splice()方法splice(start, num, insert1, insert2,...)方法是插入、刪除和替換數組元素的通用方法。
參數start:插入或刪除的起始位置
參數num:需要刪除元素的個數,如果不指定會將起始位置后的所有元素刪除
insert、insert2...:需要插入的元素
var a = [1, 2, 3, 4, 5, 6, 7]; a.splice(5); //==>[6, 7],a變為[1, 2, 3, 4, 5] a.splice(2, 2); //==>[3, 4],a變為[1, 2, 5] a.splice(-1, 1); //==>[5],a變為[1, 2] a.splice(1, 0, "a", false, 0); // ==>[],沒有刪除元素,a變為[1, "a", false, 0, 2] a.splice(2, 2, ["x", "y"]); // ==>[false, 0],a變為[1, "a", ["x", "y"], 2]
注:會修改調用該方法的數組
2.2 數組的遍歷使用for循環是遍歷數組的常見方法,可以配合部分if語句過濾部分元素。
for(var i=0, len=arr.length; i對于稀疏數組,可以使用for-in循環歷來過濾掉不存在的索引。for-in循環會訪問繼承的可枚舉屬性,利用hasOwnProperty()方法過濾掉非自身屬性。
for(var i in p) { if(!p.hasOwnProperty(i)) {continue;} //跳過繼承的屬性 }forEach()方法由于for-in循環本身是未遍歷對象而設計,如果數組有其余可枚舉屬性,需要專門過濾。ES5定義forEach()方法來遍歷數組。
forEach(fn)方法接收一個函數作為參數,將每個元素分別調用該函數。forEach()可以給fn傳遞三個參數,fn(value, index, array)。
value:數組元素
index:數組元素對應的索引
array:數組本身
var a = [1, 2, 3, 4, 5]; //計算數組元素的和 var sum = 0; a.forEach(function(value) { //只傳遞數組元素一個參數 sum += value; }); console.log(sum); // ==> 15 //將數組每個元素加2 a.forEach(function (value, index, array) { array[index] = value + 2; }); console.log(a); // ==>[3, 4, 5, 6, 7]forEach()方法不能在所有元素都傳遞給fn函數調用前終止遍歷(不能使用break跳出循環),如果要提前終止循環,需要將forEach()方法放在try塊中,如果forEach()調用的函數fn能拋出foreach.break異常,遍歷提前終止。
function foreach(value, index, array) { try { a.forEach(index, array); } catch(e) { if(e === foreach.break) { return; } else { throw e; } } }2.3 多維數組JS并不支持真正的多維數組,可以利用數組的數組來進行模擬,使用[][]訪問即可。
var table = new Array(10); //表格10行 var len=table.length; for(let i=0; i3 數組的方法35 在Array.prototype中定義了與數組操作相關的方法,主要分為ES3和ES5兩個部分
3.1 ES3中的數組操作方法 Array.prototype.join():不修改原字符串Array.prototype.join(seperator)方法將數組中所有元素先轉化為字符串,再利用參數seperator傳入的分隔符將元素轉換成的字符串拼接起來,最后返回該字符串。默認使用,分隔。是String.prototype.split()方法的逆向操作
var a = [1, 2, 3]; a.join(); // ==> "1,2,3" a.join(" "); // ==> "1 2 3" a.join(""); // ==> "123" "1,2,3".split(",").join(); //==> "1,2,3"Array.prototype.reverse():會修改原數組將數組中的元素順序顛倒,返回逆序后的數組
var a = [1, 2, 3]; a.reverse.join(); //"3,2,1",并且a變為[3, 2, 1],所以注意使用副本來操作Array.prototype.sort():會修改原數組將數組中元素按照指定的順序后返回,默認按照字母表的順序怕排序。undefined值被排到最后,要使用其他方式排序,需要傳入一個比較函數fn(a, b),依據兩個參數在排序好的數組中的先后順序:
如果第一個參數在第二個參數之前,函數返回值小于0
如果第一個參數在第二個參數值后,函數返回值大于0
如果兩個參數相等,函數返回值等于0
var arr = ["banana", "cherry", "apple"]; arr.sort(); arr.join(","); //==> "apple,banana,cherry",默認按照字母表順序 var a = [1, 2, 3, 4]; a.sort(function(a, b) { return a - b; //如果目標是升序,a在b的前面,函數返回值小于0即可 }); a.sort(function(a, b) { return b - a ; //如果目標是降序,a在b的后面,函數返回值大于0即可 }); //不區分大小寫升序排列 var arr = ["ant", "Dog", "Bug", "cat"]; arr.sort(function(first, second) { first = first.toLowerCase(); //將字符串全部轉化為小寫 second = second.toLowerCase(); if(first < second) { //如果正確順序是first在second前,則返回-1 return -1; } else if (first > second) { return 1; } else { return 0; } });Array.prototype.concat():不修改原數組用于拼接原始數組與傳入的參數,組成一個新的數組并返回。如果傳入的參數是數組,會連接最外層的數組元素
var a = [1, 2, 3]; a.concat(4, 5); // ==> [1, 2, 3, 4, 5] a.concat([4, 5]); // ==> [1, 2, 3, 4, 5] a.concat(4, [5, [6, 7]]); //==> [1, 2, 3, 4, 5, [6, 7]] // 將數組[5, [6, 7]]最外層拆開,但是保留內部Array.prototype.slice():不改變原數組返回指定數組的一個片段或數組:
通過兩個參數指定切割的起始位置與結束位置(不包含第二個位置的元素)
如果只有一個參數,返回從開始位置到數組結束的所有元素
參數接收負數,-1表示最后一個元素,-2表示倒數第二個元素
a = [1, 2, 3, 4, 5]; a.slice(0, 3); // ==> [1, 2, 3] a.slice(3); // ==> [4, 5] a.slice(1, -1); // ==> [2, 3, 4]toString()和toLocalString()先將數組的每個元素轉化為字符串,再利用逗號將其拼接為一個字符串,其中toLocaleString()方法區別在于轉換Date和Number類型的數字、日期和時間時,根據時區、數字來轉化。
轉換結果與不傳入參數的join()方法類似
[1, 2, 3].toString(); // ==> "1,2,3" ["a", [1, "b"]].toString(); // ==> "a,1,b"3.2 ES5中操作數組的方法ES5中定義了9個方法來遍歷forEache()、映射map()、過濾filter()、檢測every() some()、簡化reduce() reduceRight()和搜索indexOf() lastIndexOf()數組。九種方法不會修改調用它的數組,但是傳入的函數會。
九種方法基本都屬于過程抽象,第一個參數基本都是一個函數,對數組的每個元素調用該函數
Array.prototype.map()map(fn)只有一個參數,map()方法傳遞三個參數給fn(value, index, array),根據需要選擇。其調用方式與forEach()相似,但是傳遞給map(fn)的函數fn有返回值。
map()返回的是新數組,不修改原數組
如果是稀疏數組,返回稀疏素組;具有相同的長度與缺失元素
var a = [1, 2, 3]; a.map(function(value) { return value * value; //map()傳入的函數必須要有返回值,將返回值作為返回數組的元素的值 }); //==> [1, 4, 9],原數組a還是[1, 2, 3]不變Array.prototype.filter()filter()方法返回的數組是調用數組的一個子集。通過傳遞的函數進行邏輯判斷,如果返回值是true,當前元素被添加到返回的子集中;如果返回false,則過濾掉該元素;
filter()會跳過稀疏數組中缺失的元素,返回的總是稠密數組。
arr.filter(function() {return true;}); 會過濾掉所有缺失的元素;
arr.filter(funtion(x) {return (x !== undefined && x !=null)}):過濾掉undefined和null
var a = [5, 4, 3, 2, 1]; a.filter(function(value) { return value < 3; }); // ==> [2, 1] a.filter(function(value, index) { return index % 2 === 0; //過濾掉索引為奇數的元素 }); // ==> [5, 3, 1],不會改變原數組Array.prototype.every()和Array.prototype.some()every()和some()用于對數組進行邏輯判斷,返回true或`false;每個元素應用傳入的函數進行判斷:
every()方法:當且僅當數組中所有元素調用函數的判斷結果為true時,才返回true
some()方法:至少有一個元素調用函數的判斷結果為true時,返回true
every()和some()在確定返回true或false后會停止遍歷數組。類似&&和||的短路特性
在空數組上調用,根據慣例,every()返回true,some()返回false
var a = [5, 4, 3, 2, 1]; a.every(function(value) { return value < 10; }); // ==>true,所有的值都小于10 a.every(function(value) { return value % 2 === 0; }); // ==> false,不是所有元素都是偶數 a.some(function(value) { return value % 2 === 0; }); // ==> true,數組a中有偶數 a.some(isNaN); // ==> false,a中所有元素都不是非數值元素Array.prototype.reduce()和Array.prototype.reduceRight()reduce()和reduceRight():使用指定函數將數組中的元素進行組合,生成單個值。在函數式編程中常用,稱為注入和折疊。ruduceRight()的工作原理與reduce()相同,只是從右側開始索引
reduce(fn, init)有兩個參數:
fn是執行簡化操作的函數;
init是傳遞給簡化函數的初始值,如果不指定,默認為數組的第一個元素
reduce()傳遞給化簡函數fn(init, value, index array)四個參數:
init:第一次調用函數時,init是reduce()傳入的初始值,如果reduce()沒有指定第二個參數,默認使用數組的第一個元素;以后的調用中,其值等于化簡函數的返回值
value、index、array:分別是數組元素、元素索引和數組本身。
var a = [1, 2, 3, 4, 5]; a.reduce(function(init, value) { return init + value; }, 0); //初始值init是0,返回累加的結果==> 15 //初始值為1,如果不指定,默認為數組的第一個元素 a.reduce(function(init, value) {return init * value;}, 1); // ==>120 a.reduce(function(init, value) {return (init > value)? init: value;}); var a = [2, 3, 4]; //計算2^(3^4),乘方操作的優先順序是從右到左。 a.reduceRight(function(init, value) {return Math.pow(value, init);});a.reduce(function(init, value) {return init + value;}, 0); 的執行過程:
化簡函數第一次調用時,reduce()方法將0傳遞給函數的init參數,將數組的第一個元素傳遞給value
執行化簡函數,將返回值賦予init,再次繼續下次調用
Array.prototype.indexOf()和Array.prototype.lastIndexOf()搜索整個數組中指定值,返回第一個匹配值的索引,如果沒有找到返回-1。indexOf()從頭到尾查找、lastIndexOf()從尾到頭查找。
indexOf()與lastIndexOf()的參數沒有函數,第一個參數是查找的值;第二個參數可選,指定開始查找的索引位置
//查找數組中所有出現的value,返回一個包含匹配值索引的數組 function findall(arr, value) { var results = []; var len = a.length; var index = 0; //開始查找的索引 while(index < len) { //arr.indexOf(arr, index)中第二個參數是為了過濾掉之前已經查找過的數組元素 index = arr.indexOf(value, index); //避免重復的同時,加快了搜索效率 if(index === -1) {break;} //如果未找到,便退出;因為forEach()退出循環不方便,所以使用while results.push(index); index += 1; } }4 類數組對象 4.1 數組類型判斷一個未知的對象是否為數組,可以使用ES5提供的Array.isArray()方法,定義在Array()構造器函數上,沒有定義在Array.prototype原型上。
Array.isArray([]); // ==>true Array.isArray({}); // ==>false因為typeof和instanceof在判斷Array類型時比較繁復,所以使用同一的Array.isArray()來判斷。isArray()方法的可能實現:
//Function.isArray || function(o)用來判斷程序中是否有同名的isArray函數,確保不會重寫原有函數。 var isArray = Function.isArray || function(o) { return (typeof o === "object") && (Object.prototype.toString.call(o) === "[object Array]"); };4.2 類數組對象JS中數組的部分特性是其余對象沒有的:
新元素添加到數組后,自動更新length屬性
設置length為較小值時,截斷數組
從Array.prototype中繼承屬性
類屬性為Array
這4點并不是數組的本質。但是可以將一個用于length屬性(值為數值),其余屬性為非負整數(索引)的對象看做類數組。由于數組的方法通用性很強,可以使用數組的方法來操作類數組對象,只是類數組對象并未繼承Array.prototype對象,所以需要Function.call()來間接調用。
var a = {"0": "a", "1": "b", "2": "c", "length": 3}; //類數組對象 Array.prototype.join.call(a, ","); // ==> "a,b,c" Array.prototype.slice.call(a, 0); // ==> ["a", "b", "c"]真正數組的副本 Array.prototype.map.call(a, function(value) { return value.toUpperCase(); }); // ==> ["A", "B", "C"]函數的參數arguments對象和document.getElementsByTagName()獲取的對象都是類數組對象。檢測一個對象是否是類數組對象:
//判斷o是否為類數組對象 //字符串和函數有length屬性,使用typeof將其排除 //在DOM中,文本節點有length屬性,要額外調用o.nodeType !== 3排除 function isArrayLike(o) { if(o && typeof o === "object" && //非null和undefined,并且是對象 isFinite(o.length) && o.length >= 0 && o.length == Math.floor(o.length) && //o.length是整數 o.length < Math.pow(2, 32)) { //數組索引的上限是2^32-1 retun true; } else { return false; } }4.3 作為數組的字符串在ES5中,字符串的行為類似于只讀的數組,可以使用charAt()訪問單個字符,也可以通過[]訪問單個字符。
var s = "test"; s.charAt(0); // ==> "t" s[1]; // ==> "e"使用[]的索引形式訪問字符串,可以簡化charAt()的調用。因為字符串用于非負的整數length屬性,每個字符的索引是非負整數,可以將字符串看做類數組對象,使用數組的方法來操作字符串。
調用的方法不能改變原字符串,splice()、sort()、reverse()、pop()、push()、shift()與unshift()方法不能使用,使用數組方法修改字符串會導致錯誤,但是沒有錯誤提示
var s = "javascript"; Array.prototype.join.call(s, " "); // ==>"j a v a s c r i p t"總結使用對象字面量方式創建數組
數組元素的讀寫都可以通過[]
對于稀疏數組,其length屬性大于元素的個數
ES5之后,單純的數組遍歷可以使用forEach(),對于需要判斷跳出循環遍歷的,可以使用for循環替代、或使用try-catch
數組的操作方法都定義在Array.prototype原型對象上,可以對數組進行:forEach()、map()、every()和some()、filter()、reduce()和reduceRinght()、indexOf()和lastIndexOf()、splice()、sort()、reverse()
類數組對象指有非負整數的length值,并且索引為非負整數的對象,類數組對象可以使用數組的方法來操作,使用Function.call()來間接調用即可
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81845.html
摘要:專題系列共計篇,主要研究日常開發中一些功能點的實現,比如防抖節流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數組合專題系列第十六篇,講解函數組合,并且使用柯里化和函數組合實現模式需求我們需要寫一個函數,輸入,返回。 JavaScript 專題之從零實現 jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現一個 jQuery 的 ext...
摘要:數組創建數組數組字面量使用構造函數數組本質上是所以要判斷是不是數組,需要通過判斷。數組長度使用屬性獲取元素的個數。例如函數的對象就是這樣 原文: http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Array.html 源代碼: https://github.com/RobinQu/Programing-In-...
摘要:幾乎所有的編程語言都有類似的數據結構。然而的數組卻略有不同。沒有定義中說的那樣的數據結構,作為替代。元素通過指定的分隔符進行分隔。返回該對象的源代碼。把數組轉換為本地數組,并返回結果。 寫在前面的話: 經常看到技術博客上寫的內容很詳細,對于一個問題,大家的博客內容似乎都是一樣的。不難發現這些技術博客已經成為各路教程的匯總地,而教程一般都是參考國外博客翻譯或者直接在經典的書籍上大片抄錄。...
摘要:中并沒有明確的數組數據類型。返回數組對象的原始值。專門用于篩選出數組中符合函數判斷條件的元素組成的心數組。專門用于對原數組中每個元素執行相同的函數對象規定的操作。 概述 一維數組 數組是一個有序的數據集合,可以通過數組名稱和索引進行訪問。JavaScript中并沒有明確的數組數據類型。 二維數組 數組是可以嵌套的,這就意味著一個數組可以作為一個袁旭被包含在另一個數組里面。利用JavaS...
摘要:屬性是一個值或一組值以數組或對象的形式,是對象的成員。可以使用內置構造函數和創建包裝對象。因此下面的代碼將會使人很迷惑結果結果,此數組長度為應該盡量避免使用數組構造函數創建新數組。給數組對象添加返回數組中最大元素值的方法。 對象部分 Object類型 Object 是一個無序的集合,可以存放任意類型對象,所有其他對象都繼承自這個對象。創建Object類型有兩種,一種是使用new運算符,...
閱讀 1630·2021-10-27 14:13
閱讀 1868·2021-10-11 10:59
閱讀 3367·2021-09-24 10:26
閱讀 1925·2019-08-30 12:48
閱讀 3040·2019-08-30 12:46
閱讀 2032·2019-08-30 11:16
閱讀 1414·2019-08-30 10:48
閱讀 2740·2019-08-29 16:54