摘要:唯一需要注意的的是回調函數(shù)需要有值,否則新數(shù)組都是。唯一需要注意的的是回調函數(shù)需要布爾值或,如果忘記寫語句,返回得到的是空數(shù)組,表示一個都不匹配。
JavaScript數(shù)組的應用應該都比較熟悉了。
? forEach,map,filter
? some,every
? reduce,reduceRight
引用塊內容
? slice,splice
? indexOf,lastIndexOf
? sort
? 類數(shù)組對象
forEach,map,filter
forEach遍歷數(shù)組,函數(shù)聲明:[].forEach( function(value, index, array) { … }, [thisArg] );。
第一個參數(shù)是回調函數(shù),它支持3個參數(shù),第1個是遍歷的數(shù)組內容,第2個是對應索引,第3個是數(shù)組自身。
第二個參數(shù)thisArg可選,可用于以改變回調函數(shù)里面的this指針
因為forEach是第一個被介紹的數(shù)組方法,所以稍微詳細點用console.log看一下回調函數(shù)的3個參數(shù)。(之后的數(shù)組方法有興趣的可以自己用console.log看一下回調函數(shù),不贅述)
[1, 2 ,3, 4].forEach(console.log); // 1, 0, [1, 2, 3, 4] // 2, 1, [1, 2, 3, 4] // 3, 2, [1, 2, 3, 4] // 4, 3, [1, 2, 3, 4]
上面已經清晰地展現(xiàn)了遍歷的結果,第一列是value,第二列是對應的index值,第三列是數(shù)組本身。
現(xiàn)在用forEach實現(xiàn)數(shù)組求和:
var price = 0; [1, 2, 3, 4].forEach(function (value) { price += value; }); console.log(price); //10
相比for循環(huán),上述代碼除了更簡單外,還避免了常見的for循環(huán)的起始,終止條件越界等錯誤。對于數(shù)組遍歷來說,forEach和map是優(yōu)于for循環(huán)的。
現(xiàn)在看看第二個參數(shù)thisArgs的作用,如果不指定該參數(shù),回調函數(shù)內的this指向的是window(關于this可以參照這里),例如上例中的回調函數(shù)里,你可以寫成this.price += value;,效果是一樣的(當然前提是變量確實是window的全局屬性)。但有時this指向window就不對了,如下:
var group = { members: ["Jack", "Andy", "Natasha"], joinParty: "Yes", getInfo: function (m) { this.isJoinParty(m); console.log(m + " " + this.joinParty); }, isJoinParty: function (m) { switch(m) { case "Andy" : this.joinParty = "No"; break; default: this.joinParty = "Yes"; break; } } }; group.members.forEach(group.getInfo);
代碼很簡單,小組內3人,Andy不參加聚會,另兩人參加聚會。期望把統(tǒng)計結果打印出來。但很遺憾上面代碼會報Error。按理說getInfo函數(shù)里的this應該指向group對象,但遺憾地是getInfo作為[].forEach的回調函數(shù)時相當于普通函數(shù),因此getInfo里的this指向的是window。而window對象里顯然不存在isJoinParty。
因此正確的調用方式是,添加第二個參數(shù),明確指定this的綁定對象:
group.members.forEach(group.getInfo, group);
//Jack Yes
//Andy No
//Natasha Yes
map映射創(chuàng)建新數(shù)組,函數(shù)聲明:[].map( function(value, index, array) { … }, [thisArg] );。和forEach一樣,不贅述。唯一需要注意的的是回調函數(shù)需要有return值,否則新數(shù)組都是undefined。
其實map能干的事forEach都能干,你可以把map理解為forEach的一個特例,專門用于:通過現(xiàn)有的數(shù)組建立新數(shù)組。例如將舊數(shù)組中字符串都trim一下,去除空格后生成新數(shù)組:
var trimmed = [" Jack","Betty "," Chirs "].map(function(s) { return s.trim(); //需要return值,否則新數(shù)組里都是undefined }); console.log(trimmed); //["Jack", "Betty", "Chirs"]
在沒有map之前是通過forEach來創(chuàng)建新數(shù)組的。你需要先定義一個空數(shù)組,再將每次trim后的字符串push到新數(shù)組內,比較麻煩。因為“通過現(xiàn)有的數(shù)組建立新數(shù)組”這個需求是如此的普遍,因此ES5中干脆追加了map方法,相比forEach代碼簡單優(yōu)雅多了。
filter用于過濾數(shù)組,函數(shù)聲明:[].filter( function(value, index, array) { … }, [thisArg] );。和forEach一樣,不贅述。唯一需要注意的的是回調函數(shù)需要return布爾值true或false,如果忘記寫return語句,返回得到的是空數(shù)組,表示一個都不匹配。例如:
var newArray = [0, 1, 2].filter(function(value) {}); console.log(newArray); //[],沒有return語句得到的是空數(shù)組 //過濾出不超過10的正數(shù) var newArray2 = [0, 1, 2, 14].filter(function(value) { return value > 0 && value <= 10; }); console.log(newArray2); //[1, 2]
some,every
some表示只要某一個滿足條件就OK,every表示全部滿足條件才OK。
some的函數(shù)聲明:[].some( function(value, index, array) { … }, [thisArg] );
every的函數(shù)聲明:[].every( function(value, index, array) { … }, [thisArg] );
參照MDN。其實都和上面的forEach一樣,不贅述。唯一需要注意的的是回調函數(shù)需要return布爾值true或false,如果忘記寫return語句,表示不滿足條件,返回false
[1, 10, 100].some(function(x) { x > 5; }); //false,忘記寫return了 [1, 2, 3, 4, 5].every(function(x) { x > 0; }); //false,忘記寫return了 [1, 10, 100].some(function(x) { return x > 5; }); // true [1, 10, 100].some(function(x) { return x < 0; }); // false [1, 2, 3, 4, 5].every(function(x) { return x > 0; }); // true [1, 2, 3, 4, 5].every(function(x) { return x < 3; }); // false
reduce,reduceRight
兩者都是用于迭代運算。區(qū)別是reduce從頭開始迭代,reduceRight從尾開始迭代。
reduce的函數(shù)聲明:[].reduce( function(previousValue, currentValue, currentIndex, array) { … }, [initialValue] );
第一個參數(shù)是回調函數(shù),有4個參數(shù):previousValue,currentValue,currentIndex,array。看名字也能知道意思:前一個值,當前值,當前索引,數(shù)組本身。
第二個參數(shù)initialValue可選,表示初始值。如果省略,初始值為數(shù)組的第一個元素,這樣的話回調函數(shù)里previousValue就是第一個元素,currentValue是第二個元素。因此不設initialValue的話,會少一次迭代。例如:
var sum = [1, 2, 3, 4].reduce(function (previous, current) { return previous + current; }); console.log(sum); //10 //給它加上initialValue初始值10 var sum2 = [1, 2, 3, 4].reduce(function (previous, current) { return previous + current; }, 10); console.log(sum2); //20
上圖清楚地表明了各個運算步驟,很容易理解。如果不設initialValue,會少一次迭代。
reduceRight的函數(shù)聲明:[].reduceRight( function(previousValue, currentValue, currentIndex, array) { … }, [initialValue] );。和reduce一樣,不贅述
用reduce和reduceRight很容易就能實現(xiàn)二維數(shù)組扁平化,如下:
var flat1 = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) { return a.concat(b); }); console.log(flat1); //[0, 1, 2, 3, 4, 5] var flat2 = [[0, 1], [2, 3], [4, 5]].reduceRight(function(a, b) { return a.concat(b); }); console.log(flat2); //[4, 5, 2, 3, 0, 1]
slice,splice
兩者做的事情還不太一樣,但名字實在太像了,所以放一起介紹。
slice用于復制數(shù)組,復制完后舊數(shù)組不變,返回得到的新數(shù)組是舊數(shù)組的子集。函數(shù)聲明:[].slice(begin, [end])。參照MDN
第一個參數(shù)begin是開始復制的位置,需要注意的是,可以設負數(shù)。設負數(shù)表示從尾往前數(shù)幾個位置開始復制。例如slice(-2)將從倒數(shù)第2個元素開始復制。另外需要注意的是,該參數(shù)雖未標注為可選,但實際上是可以省略的,省略的話默認為0。
第二個參數(shù)end可選,表示復制到該位置的前一個元素。例如slice(0,3)將得到前3個元素,但不包含第4個元素。不設的話默認復制到數(shù)組尾,即等于array.length。
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"].slice(0, 3); console.log(fruits); //["Banana", "Orange", "Lemon"] var fruits2 = ["Banana", "Orange", "Lemon", "Apple", "Mango"].slice(-1); console.log(fruits2); //["Mango"]
當然slice最常見的是用在將類數(shù)組arguments對象轉換為真正的數(shù)組:
var args = [].slice.call(arguments);
splice用于剝離數(shù)組,從舊數(shù)組中移除元素,返回得到的新數(shù)組是被移除的元素。函數(shù)聲明:[].splice(start, deleteCount, [item…])。參照MDN
第一個參數(shù)start是開始剝離的位置,需要注意的是,可以設負數(shù)。設負數(shù)表示從尾往前數(shù)幾個位置開始剝離。例如splice (-2)將從倒數(shù)第2個元素開始剝離。
第二個參數(shù)deleteCount是要剝離的元素個數(shù),設0表示一個都不剝離。
第三個參數(shù)開始可選,用于替換舊數(shù)組中被移除的元素
var oldArray = ["a", "b", "c"]; var newArray = oldArray.splice(1, 2, "Jack", "Betty", "Andy"); console.log(oldArray); //["a", "Jack", "Betty", "Andy"] console.log(newArray); //["b", "c"]
一個常見的應用就是刪除數(shù)組內某元素,用delete的話會留下空洞,應該用splice方法:
//錯誤的方法用delete
var numbers = [0, 1, 2, 3, 4]; delete numbers[2]; console.log(numbers); //[0, 1, undefined, 3, 4] //正確的方法用splice numbers.splice(2, 1); console.log(numbers); //[0, 1, 3, 4]
indexOf,lastIndexOf
兩者都用于返回項目的索引值。區(qū)別是indexOf從頭開始找,lastIndexOf從尾開始找。如果查找失敗,無匹配,返回-1
indexOf的函數(shù)聲明:[].indexOf( searchElement, [fromIndex = 0] );。參照MDN
lastIndexOf的函數(shù)聲明:[].lastIndexOf( searchElement, [fromIndex = arr.length – 1] );
第一個參數(shù)searchElement即需要查找的元素。第二個參數(shù)fromIndex可選,指定開始查找的位置。如果忽略,indexOf默認是0,lastIndexOf默認是數(shù)組尾。
["a", "b", "d", "e"].indexOf("b"); //1 ["a", "b", "d", "e"].indexOf("b", 2); //-1,從2號位開始找沒找到 ["a", "b", "d", "e"].indexOf("c"); //-1,沒找到 ["a", "b", "d", "e"].lastIndexOf("b"); //1 ["a", "b", "d", "e"].lastIndexOf("b", 2); //1,逆向2號位等價于正向1號位 ["a", "b", "d", "e"].lastIndexOf("c"); //-1,沒找到
sort
sort用于排序數(shù)組,函數(shù)聲明:[].sort( [sortfunction] );。參照MDN
它就一個參數(shù),就是排序函數(shù)指針。而且是可選的,不設的話有默認的排序函數(shù),數(shù)字的話會升序排列,string會根據(jù)Unicode升序排列。
var sumArray = [4, 3, 1, 0, 2]; var sumArray2 = ["d", "z", "a"]; sumArray.sort(); sumArray2.sort(); console.log(sumArray); //[0, 1, 2, 3, 4] console.log(sumArray2); //["a", "d", "z"]
但是內置的默認排序函數(shù),是不可靠的,如下:
var scores = [1, 10, 2, 21]; scores.sort(); console.log(scores); //[1, 10, 2, 21]
因此保險起見最好自定義排序函數(shù):
var scores = [1, 10, 2, 21]; function compareNumbers(x, y) { if (x < y) { return -1; } if (x > y) { return 1; } return 0; } scores.sort(compareNumbers); console.log(scores); //[1, 2, 10, 21]
而且如果數(shù)組內是對象,或排序邏輯復雜的話,那默認排序函數(shù)更是力不從心了,必須自定義排序函數(shù):
var items = [ { name: "Jack", value: 37 }, { name: "Betty", value: 21 }, { name: "Andy", value: 45 } ]; items.sort(function (a, b) { if (a.value < b.value) { return -1; } if (a.value > b.value) { return 1; } return 0; }); console.log(items); //[{ name="Betty", value=21}, // { name="Jack", value=37}, // { name="Andy", value=45}]
剩下的比較簡單,大致說一下,就不詳細介紹了。
push和pop用于數(shù)組尾處壓入和彈出元素。
unshift和shift用于數(shù)組頭部壓入和彈出元素。
reverse用于反轉數(shù)組,concat用于連接數(shù)組,join用于數(shù)組元素間插入些東西后拼接成string。
類數(shù)組
var arr1 = new Array();
arr1.push(1);
arr1.push(2);
arr1.push(3);
console.log(arr1); //[1,2,3]
console.log(arr1.pop()); //3 彈出棧頂數(shù)據(jù)
JS里有很多類數(shù)組對象。什么叫類數(shù)組對象呢?它們首先是對象,并沒有繼承Array,但長的卻很像數(shù)組。最典型的如arguments對象,HTMLCollection對象。
類數(shù)組對象不能直接使用數(shù)組方法,但數(shù)組方法是如此簡單便利,要在類數(shù)組對象身上使用數(shù)組方法,需要讓數(shù)組函數(shù)通過call綁定類數(shù)組對象。
處理arguments對象:
var args = [].slice.call(arguments);
處理HTMLCollection對象:
//用forEach遍歷頁面所有div,輸入className
var divs = document.getElementsByTagName("div");
Array.prototype.forEach.call(divs, function(div) {
console.log("該div類名是:" + (div.className || "空"));
});
//下面這樣直接調用forEach將報錯,因為divs是HTMLCollection對象而非Array
divs.forEach(function(div) {
console.log("該div類名是:" + (div.className || "空"));
});
處理字面量對象:
var arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 }; var result = Array.prototype.map.call(arrayLike, function(s) { return s.toUpperCase(); }); console.log(result); //["A", "B", "C"] 處理字符串: var result = Array.prototype.map.call("abc", function(s) { return s.toUpperCase(); }); console.log(result); //["A", "B", "C"]
但Array的concat會檢查參數(shù)的[[Class]]屬性,只有參數(shù)是一個真實的數(shù)組才會將數(shù)組內容連接起來,否則將作為單個元素來連接。要完全實現(xiàn)連接,我們需要自己在對象上增加slice方法:
//單用concat的話,arguments對象將作為一個單一整體被連接 function namesColumn() { return ["Jack"].concat(arguments); } var newNames = namesColumn("Betty", "Andy", "Chris"); console.log(newNames); //["Jack", ["Betty", "Andy", "Chris"]] //配合slice能實現(xiàn)完全連接 function namesColumn() { return ["Jack"].concat([].slice.call(arguments)); } var newNames = namesColumn("Betty", "Andy", "Chris"); console.log(newNames); //["Jack", "Betty", "Andy", "Chris"]
更多資源上:去轉盤;或者加我的QQ群一起討論學習js,css等技術(QQ群:512245829)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80163.html
摘要:個人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經一年的時間了,由于工作比較忙,更新緩慢,后面還是會繼更新,現(xiàn)將已經寫好的文章整理一個目錄,方便更多的小伙伴去學習。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個人前端文章整理 從最開始萌生寫文章的想法,到著手...
摘要:看下面一個例子優(yōu)點使用構造器函數(shù)的好處在于,它可以在創(chuàng)建對象時接收一些參數(shù)。按照慣例,構造函數(shù)的函數(shù)名應始終以一個大寫字母開頭,以區(qū)分普通函數(shù)。返回該對象的源代碼。使您有能力向對象添加屬性和方法。 基本概念 ECMA關于對象的定義是:無序屬性的集合,其屬性可以包含基本值、對象或者函數(shù)。對象的每個屬性或方法都有一個名字,而每個名字都映射到一個值。 類 在現(xiàn)實生活中,相似的對象之間往往都有...
摘要:不會對空數(shù)組進行遍歷遍歷數(shù)組的每一項,數(shù)組當前項的下標,原數(shù)組函數(shù)內沒有執(zhí)行,證明數(shù)組為空是并不執(zhí)行遍歷返回一個新數(shù)組,長度等于原數(shù)組長度遍歷數(shù)組的每一項,數(shù)組當前項的下標,原數(shù)組即便函數(shù)返回空結果數(shù)組的 map() 不會對空數(shù)組進行遍歷 let arr = [] let newArr = arr.map((item, i, arr) => { ...
摘要:使用一元加模擬函數(shù)原理對非數(shù)值類型的數(shù)據(jù)使用一元加,會起到與函數(shù)相同的效果。中,若判斷不為則不再進行下一步操作。使用邏輯或設置默認值邏輯或也屬于短路操作,即當?shù)谝粋€操作數(shù)可以決定結果時,不再對第二個操作數(shù)進行求值。 善于利用JS中的小知識的利用,可以很簡潔的編寫代碼 1. 使用!!模擬Boolean()函數(shù) 原理:邏輯非操作一個數(shù)據(jù)對象時,會先將數(shù)據(jù)對象轉換為布爾值,然后取反,兩個!!...
摘要:很簡單,不是數(shù)組,但是有屬性,且屬性值為非負類型即可。至于屬性的值,給出了一個上限值,其實是感謝同學指出,因為這是中能精確表示的最大數(shù)字。如何將函數(shù)的實際參數(shù)轉換成數(shù)組 這篇文章拖了有兩周,今天來跟大家聊聊 JavaScript 中一類特殊的對象 -> Array-Like Objects。 (本文節(jié)選自 underscore 源碼解讀系列文章,完整版請關注 https://githu...
閱讀 1378·2021-10-08 10:04
閱讀 2681·2021-09-22 15:23
閱讀 2724·2021-09-04 16:40
閱讀 1172·2019-08-29 17:29
閱讀 1492·2019-08-29 17:28
閱讀 2988·2019-08-29 14:02
閱讀 2221·2019-08-29 13:18
閱讀 838·2019-08-23 18:35