迭代器方法
这些方法对数组中的每个元素应用一个函数, 可以返回一个值、 一组值或者一个新数组。
1 不生成新数组的迭代器方法
forEach(), 该方法接受一个函数作为参数, 对数组中的每个元素使用该函数。
function square(num) {
console.log(num, num * num);
}
var nums = [1,2,3,4,5,6,7,8,9,10];
nums.forEach(square);
every(), 该方法接受一个返回值为布尔类型的函数, 对数组中的每个元素使用该函数。 如果对于所有的元素, 该函数均返回 true, 则该方法返回 true。
function isEven(num) {
return num % 2 == 0;
}
var nums = [2,4,6,8,10];
var even = nums.every(isEven);
if (even) {
console.log("all numbers are even");
} else {
console.log("not all numbers are even");
}
输出为:all numbers are even
将数组改为:var nums = [2,4,6,7,8,10];
输出为: not all numbers are even
some() 方法也接受一个返回值为布尔类型的函数, 只要有一个元素使得该函数返回 true,该方法就返回 true。
比如:
function isEven(num) {
return num % 2 == 0;
}
var nums = [1,2,3,4,5,6,7,8,9,10];
var someEven = nums.some(isEven)
if (someEven) {
print("some numbers are even");
} else {
print("no numbers are even");
}
输出 some numbers are even
nums = [1,3,5,7,9];
someEven = nums.some(isEven);
if (someEven) {
console.log("some numbers are even");
} else {
console.log("no numbers are even");
}
输出 no numbers are even
reduce() 方法接受一个函数, 返回一个值。 该方法会从一个累加值开始, 不断对累加值和数组中的后续元素调用该函数, 直到数组中的最后一个元素, 最后返回得到的累加值。
function add(runningTotal, currentValue) {
return runningTotal + currentValue;
}
var nums = [1,2,3,4,5,6,7,8,9,10];
var sum = nums.reduce(add);
console.log(sum); // 显示 55
执行过程
add(1,2) -> 3
add(3,3) -> 6
add(6,4) -> 10
add(10,5) -> 15
add(15,6) -> 21
add(21,7) -> 28
add(28,8) -> 36
add(36,9) -> 45
add(45,10) -> 55
reduce() 方法也可以用来将数组中的元素连接成一个长的字符串:
function concat(accumulatedString, item) {
return accumulatedString + item;
}
var words = ["the ", "quick ","brown ", "fox "];
var sentence = words.reduce(concat);
console.log(sentence); // 显示 "the quick brown fox"
reduceRight() 方法, 和 reduce() 方法不同, 它是从右到左执行。
function concat(accumulatedString, item) {
return accumulatedString + item;
}
var words = ["the ", "quick ","brown ", "fox "];
var sentence = words.reduceRight(concat);
console.log(sentence); // 显示 "fox brown quick the"
2 生成新数组的迭代器方法
两个迭代器方法可以产生新数组: map() 和 filter()。 map() 和 forEach() 有点儿像, 对数组中的每个元素使用某个函数。 两者的区别是 map() 返回一个新的数组, 该数组的元素是对原有元素应用某个函数得到的结果。
function curve(grade) {
return grade += 5;
}
var grades = [77, 65, 81, 92, 83];
var newgrades = grades.map(curve);
console.log(newgrades); //[ 82, 70, 86, 97, 88]
对一个字符串数组使用 map() 方法的例子:
function first(word) {
return word[0];
}
var words = ["for","your","information"];
var acronym = words.map(first);
console.log(acronym.join("")); // 显示 fyi
数组 acronym 保存了数组 words 中每个元素的第一个字母。 然而, 如果想将数组显示为真正的缩略形式, 必须想办法除掉连接每个数组元素的逗号, 如果直接调用 toString() 方法, 就会显示出这个逗号。 使用 join() 方法, 为其传入一个空字符串作为参数, 则可以帮助我们解决这题。
简单的说就是 word【0】是获取数组元素中的首字母并返回出来存入一个新数组中 得到的就是 【f , y , i】
然后 用join("") 方法去掉逗号 转成字符串,
filter() 和 every() 类似, 传入一个返回值为布尔类型的函数。 和 every() 方法不同的是,当对数组中的所有元素应用该函数, 结果均为 true 时, 该方法并不返回 true, 而是返回一个新数组, 该数组包含应用该函数后结果为 true 的元素。
function isEven(num) {
return num % 2 == 0;
}
function isOdd(num) {
return num % 2 != 0;
}
var nums = [];
for (var i = 0; i < 20; ++i) {
nums[i] = i+1;
}
var evens = nums.filter(isEven);
console.log("Even numbers: "+ evens); // Even numbers: [2,4,6,8,10,12,14,16,18,20]
var odds = nums.filter(isOdd);
console.log("Odd numbers: " +odds); Odd numbers: [1,3,5,7,9,11,13,15,17,19]
使用 filter() 方法的有趣案例:
function passing(num) {
return num >= 60;
}
var grades = [];
for (var i = 0; i < 20; ++i) {
grades[i] = Math.floor(Math.random() * 101);
}
var passGrades = grades.filter(passing);
console.log("All grades: ");
console.log(grades); //[63, 81, 11, 47, 83, 19, 53, 89, 39, 54, 94, 3, 84, 71, 3, 61, 96, 2, 62, 2]
console.log("Passing grades: ");
console.log(passGrades); //[63, 81, 83, 89, 94, 84, 71, 61, 96, 62] 过滤小于60以下的
还可以使用 filter() 方法过滤字符串数组,
function afterc(str) {
if (str.indexOf("cie") > -1) {
return true;
}
return false;
}
var words = ["recieve","deceive","percieve","deceit","concieve"];
var misspelled = words.filter(afterc);
console.log(misspelled); // 显示 recieve,percieve,concieve
二维和多维数组
JavaScript 只支持一维数组, 但是通过在数组里保存数组元素的方式, 可以轻松创建多维
数组。 本节将讨论如何在 JavaScript 中创建二维数组。
1 创建二维数组
二维数组类似一种由行和列构成的数据表格。 在 JavaScript 中创建二维数组, 需要先创建一个数组, 然后让数组的每个元素也是一个数组。 最起码, 我们需要知道二维数组要包含多少行, 有了这个信息, 就可以创建一个 n 行 1 列的二维数组了
根据传入的参数, 设定了数组的行数、 列数和初始值。
Array.matrix = function(numrows, numcols, initial) {
var arr = [];
for (var i = 0; i < numrows; ++i) {
var columns = [];
for (var j = 0; j < numcols; ++j) {
columns[j] = initial;
}
arr[i] = columns;
}
return arr;
}
var nums = Array.matrix(5,5,0);
console.log(nums[1][1]); // 显示 0
var names = Array.matrix(3,3,"");
names[1][2] = "Joe";
console.log(names[1][2]); // Joe
还可以仅用一行代码就创建并且使用一组初始值来初始化一个二维数组:
var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]];
console.log(grades[2][2]); // 显示 89
对于小规模的数据, 这是创建二维数组最简单的方式
2 处理二维数组的元素
处理二维数组中的元素, 有两种最基本的方式: 按列访问和按行访问。
var grades = [
[89, 77, 78],
[76, 82, 81],
[91, 94, 89]
];
var total = 0;
var average = 0.0;
for (var row = 0; row < grades.length; ++row) {
for (var col = 0; col < grades[row].length; ++col) {
total += grades[row][col];
}
average = total / grades[row].length;
console.log("学生 " + parseInt(row + 1) + " 平均数: " +average.toFixed(2));
total = 0;
average = 0.0;
}
学生 1 平均数: 81.33
学生 2 平均数: 79.67
学生 3 平均数: 91.33
3 参差不齐的数组
参差不齐的数组是指数组中每行的元素个数彼此不同。 有一行可能包含三个元素, 另一行可能包含五个元素, 有些行甚至只包含一个元素。 很多编程语言在处理这种参差不齐的数组时表现都不是很好, 但是 JavaScript 却表现良好, 因为每一行的长度是可以通过计算得到的。
var grades = [
[89, 77],
[76, 82, 81],
[91, 94, 89, 99]
];
var total = 0;
var average = 0.0;
var data = []
for (var row = 0; row < grades.length; ++row) {
for (var col = 0; col < grades[row].length; ++col) {
total += grades[row][col];
}
average = total / grades[row].length;
data.push(average.toFixed(2))
console.log("Student " + parseInt(row + 1) + " average: " + average.toFixed(2));
total = 0;
average = 0.0;
}
console.log(data) // ["83.00", "79.67", "93.25"]
Student 1 average: 83.00
Student 2 average: 79.67
Student 3 average: 93.25
对象数组
数组还可以包含对象, 数组的方法和属性对对象依然适用。
function Point(x, y) {
this.x = x;
this.y = y;
}
function displayPts(arr) {
for (var i = 0; i < arr.length; ++i) {
console.log(arr[i].x + ", " + arr[i].y);
}
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 5);
var p3 = new Point(2, 8);
var p4 = new Point(4, 4);
var points = [p1, p2, p3, p4];
for (var i = 0; i < points.length; ++i) {
console.log("Point " + parseInt(i + 1) + ": " + points[i].x + ", " + points[i].y);
// Point 1: 1, 2
// Point 2: 3, 5
// Point 3: 2, 8
// Point 4: 4, 4
}
var p5 = new Point(12, -3);
points.push(p5);
console.log("After push: ");
displayPts(points);
// After push:
// 1, 2
// 3, 5
// 2, 8
// 4, 4
// 12, -3
points.shift();
console.log("After shift: ");
displayPts(points);
//After shift:
// 3, 5
// 2, 8
// 4, 4
// 12, -3
使用 push() 方法将点 (12, -3) 添加进数组, 使用 shift() 方法将点 (1, 2) 从数组中移除。
对象中的数组
在对象中, 可以使用数组存储复杂的数据。 本书中讨论的很多数据都被实现成一个对象,对象内部使用数组保存数据。
例子中, 我们创建了一个对象, 用于保存观测到的周最高气温。 该对象有两个方法, 一个方法用来增加一条新的气温记录, 另外一个方法用来计算存储在对象中的平均气温。 代码如下所示:
function weekTemps() {
this.dataStore = [];
this.add = add;
this.average = average;
}
function add(temp) {
this.dataStore.push(temp);
}
function average() {
var total = 0;
for (var i = 0; i < this.dataStore.length; ++i) {
total += this.dataStore[i];
}
return total / this.dataStore.length;
}
var thisWeek = new weekTemps();
thisWeek.add(52);
thisWeek.add(55);
thisWeek.add(61);
thisWeek.add(65);
thisWeek.add(55);
thisWeek.add(50);
thisWeek.add(52);
thisWeek.add(49);
console.log(thisWeek.average()); // 显示 54.875