原文:从头开始学JavaScript (十二)——Array类型
一、数组的创建
注:ECMAscript数组的每一项都可以保存任何类型的数据
1.1Array构造函数
var colors = new Array();
如果预先知道数组要保存的项目数量,也可以给构造函数传递该数量:
var colors = new Array(20);
也可以向构造函数传递数组中应该包含的项:
var colors = new Array("red", "blue", "green");
给构造函数传递一个值也可以创建数组:
如果传递的数值,则创建包含该数值个项的数组,
如果传递的是其他值,则创建包含这个值的只有一项的数组:
var colors = new Array(3);
var names = new Array("Greg");
1.2字面量表示法
数组字面量由一对包含数组项的方括号表示,多个数组项之间以逗号隔开:
var colors = ["red", "blue", "green"]; //创建一个包含3个字符串的数组
var names = [];//创建一个空数组
var values = [1,2,]; //不要这样,会创建一个2或3项的数组
var options = [,,,,,];//会创建一个5或6项的数组
二、数组的访问
2.1访问方法
在读取和设置数组的值时,要用方括号并提供相应值的基于0的数字索引:
var colors = ["red", "blue", "green"]; //定义一个字符串数组
alert(colors[0]); //显示第一项
colors[2]="black";//修改第一项
colors[3]="brown";//新增第一项
2.2length属性
数组的项数保存在length属性中,这个属性始终返回0或者更大的值。
var colors = ["red", "blue", "green"];
var name=[];
alert(colors.length);//
alert(name.length);//
数组length属性不是只读的,通过设置这个属性,可以从数组的末尾移除项或者向数组中添加新项。看下面的例子:
var colors = ["red", "blue", "green"];
colors.length = 2;
alert(colors[2]);//undefined
上述例子中末尾的一项被移除了。
var colors = ["red", "blue", "green"];
colors.length = 4;
alert(colors[3]);//undefined
新增的一项获得undefined值。
var colors = ["red", "blue", "green"];
colors[colors.length] = "black"; //在位置3添加一种颜色
colors[colors.length] = "brown"; //在位置4添加另一种颜色 alert(colors.length); //
alert(colors[3]); //black
alert(colors[4]); //brown
三、转换方法
valueOf():返回数组
toString():返回由数组每个值的字符串形式拼接而成的一个以逗号分隔的字符串。为了创建这个字符串会调用数组每一项的toString()方法
toLocaleString():返回由数组每个值的字符串形式拼接而成的一个以逗号分隔的字符串。为了创建这个字符串会调用数组每一项的toLocaleString()方法
var person1 = {
toLocaleString : function () {
return "Nikolaos";
}, toString : function() {
return "Nicholas";
}
}; var person2 = {
toLocaleString : function () {
return "Grigorios";
}, toString : function() {
return "Greg";
}
}; var people = [person1, person2];
console.log(person1);
console.log(people);
alert(people); //Nicholas,Greg
alert(people.toString()); //Nicholas,Greg
alert(people.toLocaleString()); //Nikolaos,Grigorios
以上3种方法在默认情况下都会以逗号分隔的字符串形式返回数组项。join()方法,可以使用不同的分隔符来构建这个字符串。join()方法只接受一个参数,用作分隔符的字符串,然后返回包含所有数组项的字符串:
var colors = ["red", "green", "blue"];
alert(colors.join(",")); //red,green,blue
alert(colors.join("||")); //red||green||blue
如果不给join方法传入任何值,或者传入undefined,则用逗号作为分隔符。
四、栈方法
栈:一种LIFO(Last-In—First-Out)后进先出的数据结构,新添加的项会被最早移除。而栈中项的推入(插入)和弹出(移除),只发生在栈的顶部。
利用push()+pop()方法可以实现类似栈的行为。
push():接受任意数量的参数,把他们逐个添加到数组末尾,并返回修改后数组的长度。
pop():从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。
栈案例:
var colors = new Array();
var count = colors.push("red", "green"); //推入两项
alert(count); // count = colors.push("black"); //再推入一项
alert(count); // var item = colors.pop(); //取得最后一项
alert(item); //"black"
alert(colors.length); //
五、队列方法
队列:一种FIFO(First-In—First-Out)先进先出的数据结构。
shift():能够移除数组中的第一个项并返回该项,同时将数组长度-1.
使用shift()+push()方法,可以像使用队列一样使用数组。
队列案例:
var colors = new Array();
var count = colors.push("red", "green"); //推入两个项
alert(count); // count = colors.push("black"); //再推入一个项
alert(count); // var item = colors.shift(); //获取第一项
alert(item); //"red"
alert(colors.length); //
unShift():能够在数组前端添加任意个项并返回新数组的长度.
使用unShift()和pop()方法能从反方向模拟队列
案例:
var colors = new Array();
var count = colors.unshift("red", "green"); //推入两项
alert(count); // count = colors.unshift("black"); //再推入一项
alert(count); // var item = colors.pop(); //取得最后一项
alert(item); //"green"
alert(colors.length); //
六、重排序方法
6.1reverse()
反转数组项的顺序
var values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); //5,4,3,2,1
6.2sort()
sort() 方法用于对数组的元素进行排序。
语法:数组名称.sort(参数)
参数:可选的,规定数组的排序方式。要么没有参数,要么只能是函数作为参数
返回值:对数组的引用,数组在原数组上进行排序,不生成副本。
如果调用该方法时没有使用参数,将按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
例如:
var fruit = ['apples', 'bananas', 'Cherries'];
fruit.sort(); // ['Cherries', 'apples', 'bananas'];
大写字母的编码比小写字母靠前。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
- 若 a 小于 b,则返回一个小于 0 的值。
- 若 a 等于 b,则返回 0。
- 若 a 大于 b,则返回一个大于 0 的值。
对于sort来说:
- 返回值<0,a在b之前。
- 返回值>0,a在b之后。
举一个很直观的例子返回值大于0:
function sortNumber(a, b)
{
return ;//返回值永远大于0,a在b之后,所以,数组会逆序排列
} var arr = new Array()
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
document.write(arr.sort(sortNumber))
上述例子输出:1,1000,150,40,5,10
再看返回值小于0的例子:
function sortNumber(a, b)
{
return -;//返回值永远小于0,a在b之前,所以数组排列顺序不变
} var arr = new Array()
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = "" document.write(arr.sort(sortNumber))
上述例子输出:10,5,40,150,1000,1
再看一个小到大排列的例子:
function sortNumber(a, b)
{
return a -b//如果返回值大于0,b在a前,如果返回值小于0,那么a在b前,也就是小的数在前,大的数在后。
} var arr = new Array()
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = "1"
arr[] = ""
arr[] = "" document.write(arr.sort(sortNumber))
上述代码输出:1,5,10,40,150,1000
同样,一个从大到小的例子:
function sortNumber(a, b)
{
return b-a;//返回值大于0,b在前,返回值小于0,a在前,也就是大的数总是在小的数前面。
} var arr = new Array()
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = ""
arr[] = "" document.write(arr.sort(sortNumber))
上述代码输出:1000,150,40,10,5,1
此外,还可以用sort()给对象按照某一个属性的属性值排序:
var items = [
{ name: 'Edward', value: },
{ name: 'Sharpe', value: },
{ name: 'And', value: },
{ name: 'The', value: - },
{ name: 'Magnetic',value: },
{ name: 'Zeros', value: }
];
function compare (a, b) {
if (a.value > b.value) {
return ;
}
if (a.value < b.value) {
return -;
}
return ;
}
console.log(items.sort(compare));
七、操作方法
ECMAScript为操作已经包含在数组中的项提供了很多方法,下面介绍三种
7.1concat()方法
该方法会先创建当前数组的一个副本,然后将接收到的参数添加到副本的末尾,并返回新构建的数组
传递给concat方法的参数有3种情况:
1、没有参数
如果没有给concat方法传递参数,那么它只复制当前数组并返回副本
举个栗子:
var a = [,,];
document.write(a.concat());
上述代码输出:1,2,3
2、如果传递给concat()方法的是一个或多个数组,则该方法将这个数组中的每一项都添加到副本数组中
var arr = new Array()
arr[] = "George"
arr[] = "John"
arr[] = "Thomas" var arr2 = new Array()
arr2[] = "James"
arr2[] = "Adrew"
arr2[] = "Martin" var arr3 = new Array()
arr3[] = "William"
arr3[] = "Franklin" document.write(arr.concat(arr2,arr3))
上述代码输出:George,John,Thomas,James,Adrew,Martin,William,Franklin
3、如果传递的参数不是数组,那这些参数就会被简单的添加到副本数组中去
var a = [,,];
document.write(a.concat(,));
上述代码输出:1,2,3,4,5
7.2slice()方法
基于当前数组创建选定元素的新数组。
语法:arrayObject.slice(start,end)
start:规定从哪个数组下标处开始选取
end:规定从哪个数组下标处结束选取,可选参数
如果只有一个参数:返回从该参数指定位置开始到当前数组末尾的所有项
如果有两个参数:返回起始和结束位置之间的项,但不包括结束位置项。
var colors = ["red", "green", "blue", "yellow", "purple"];
var colors2 = colors.slice();
var colors3 = colors.slice(,); alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow
如果参数中有负值:用数组长度加上参数来确定相应位置
var colors = ["red", "green", "blue", "yellow", "purple"];
var colors2 = colors.slice(-);
var colors3 = colors.slice(-,-); alert(colors2); //purple
alert(colors3); //yellow
注:slice方法不会影响原来的数组
7.3splice()方法
该方法主要有如下3种用法:
1、删除:删除任意数量的项,并返回这些项。语法arrayObject.splice(index,howmany).index:要删除的第一项的位置,howmany:要删除的项数
var colors = ["red", "green", "blue"];
var removed = colors.splice(,); //删除第一项
alert(colors); //green,blue
alert(removed); //red 被删除的项
2、插入:向指定位置插入任意数量的项,返回空数组。语法arrayObject.splice(index,0,item1,item2...itemN),index:起始位置、0:要删除的项数(纯插入不删除任何项),item:要插入的项
removed = colors.splice(, , "yellow", "orange"); //在位置1插入两项
alert(colors); //red,green,yellow,orange,blue
alert(removed); //空数组
3、添加:向指定位置插入任意数量的项,删除任意数量的项,语法arrayObject.splice(index,howmany,item1,item2...itemN),index:起始位置、howmany:要删除的项数,item:要插入的项
var colors = ["red", "green", "blue"];
removed = colors.splice(, , "red", "purple"); //插入两项,删除一项
alert(colors); //red,red,purple,blue
alert(removed); //green 删除的项
八、位置方法
indexOf(要查找的项,起点位置):从数组的开头开始向后查找
lastIndexOf(要查找的项,起点位置):从数组的末尾开始向前查找
这两个方法都返回要查找的项在数组中第一次出现的位置,没找到的情况下返回-1.如果 起点位置为负,则搜索从数组长度加上起点位置处开始。在比较要查找的项与数组中的每一项时,会要求两项必须严格相等(===)。
举个栗子:
indexOf:
var ar = ["ab", "cd", "ef", "ab", "cd"];
document.write(ar.indexOf("cd") + "<br/>");//
document.write(ar.indexOf("cd", ) + "<br/>");//从2号位置的ef向后查找,第一次出现的位置在4号位置,所以返回4
document.write (ar.indexOf("gh")+ "<br/>");//-1
document.write (ar.indexOf("ab", -) + "<br/>");//从3号位置ab向后查找,第一次出现的位置为3号位置,所以返回3
lastIndexOf:
var ar = ["ab", "cd", "ef", "ab", "cd"];
document.write(ar.lastIndexOf("cd") + "<br/>");//从4号位置向前查找,第一次出现的位置为4号位置,返回4
document.write(ar.lastIndexOf("cd", ) + "<br/>");//从2号位置ef向前查找,第一次出现的位置为1号位置,返回1
document.write(ar.lastIndexOf("gh")+ "<br/>");//-1
document.write(ar.lastIndexOf("ab", -) + "<br/>");//从2号位置向前查找,第一次出现的位置为0号位置,返回0
九、迭代方法
以下5个迭代方法。每个方法都接受两个参数:要在每一项上运行的函数、运行该函数的作用域。传入这些方法中的函数会接受三个参数:数组项的值、该项在数组中的位置、数组对象本身。
这些方法都不会修改数组本身包含的值。
1、every()
对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true.否则返回false,如果数组没有元素,则返回true。
every 方法会按升序顺序对每个数组元素调用一次 callbackfn 函数,直到 callbackfn 函数返回 false。 如果找到导致 callbackfn 返回 false 的元素,则 every 方法会立即返回 false。 否则,every 方法返回 true。
举个栗子:
function CheckIfEven(value, index, ar) {
document.write(value + " "+"<br/>"); if (value % == )
return true;
else
return false;
}
var numbers = [, , , , ];
if (numbers.every(CheckIfEven)){
document.write("Yes."+"<br/>");
}
else{
document.write("No."+"<br/>");
}
2、filter()
对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组。
举个栗子:
function CheckIfPrime(value, index, ar) {
high = Math.floor(Math.sqrt(value)) + ; for (var div = ; div <= high; div++) {
if (value % div == ) {
return false;
}
}
return true;
}
var numbers = [, , , , , , , , , , , ];
var primes = numbers.filter(CheckIfPrime); document.write(primes);//31,37,41,43,47,53
3、forEach()
对数组的每一项运行给定函数,这个方法没有返回值,但是回调函数可能会有返回值。这个方法本质上与使用for循环迭代数组一样。
function ShowResults(value, index, ar) {
document.write("value: " + value);
document.write(" index: " + index);
document.write("<br />");
}
var letters = ['ab', 'cd', 'ef'];
letters.forEach(ShowResults);
// value: ab index: 0
// value: cd index: 1
// value: ef index: 2
4、map()
对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
function AreaOfCircle(radius) {
var area = Math.PI * (radius * radius);
return area.toFixed();
}
var radii = [, , ];
var areas = radii.map(AreaOfCircle); document.write(areas);
// 314,1257,2827
5、some()
对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true。
unction CheckIfEven(value, index, ar) {
if (value % == )
return true;
} var numbers = [, , , , , ]; var evens = numbers.some(CheckIfEven);
document.write(evens);// true
十、归并方法
reduce()和reduceright()
迭代数组所有的项,并构建一个最终返回的值。
reduce()从数组的第一项开始,遍历后面的项
reduceright()从数组的最后一项开始,向前遍历到第一项
这两个方法都接收两个参数:在每一项上调用的函数、作为归并基础的初始值。
传给二者的函数接收4个参数:前一个值、当前值、项的索引、数组对象
这个函数返回的任何值都会作为第一个参数传给下一项,第一次迭代发生在数组的第二项上,所以第一个参数是数组的第一项,第二个参数是数组的第二项。
举个栗子:
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum);//15
var values = [1,2,3,4,5];
var sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
alert(sum);//15
这两个方法的主要区别在于从哪头开始遍历数组,除此之外完全相同
随堂小测试:
测试一、
var stringArray = ['Blue', 'Humpback', 'Beluga'];
var numericStringArray = ['', '', ''];
var numberArray = [, , , ];
var mixedNumericArray = ['', '', '', , , , ]; function compareNumbers(a, b) {
return a - b;
}
console.log('stringArray:', stringArray.join());
console.log('Sorted:', stringArray.sort()); console.log('numberArray:', numberArray.join("|"));
console.log('Sorted without a compare function:', numberArray.sort());
console.log('Sorted with compareNumbers:', numberArray.sort(compareNumbers)); console.log('numericStringArray:', numericStringArray.join(";"));
console.log('Sorted without a compare function:', numericStringArray.sort());
console.log('Sorted with compareNumbers:', numericStringArray.sort(compareNumbers)); console.log('mixedNumericArray:', mixedNumericArray.join("-"));
console.log('Sorted without a compare function:', mixedNumericArray.sort());
console.log('Sorted with compareNumbers:', mixedNumericArray.sort(compareNumbers));
测试二、
var numbers = [,,,,,,,,]; alert(numbers.indexOf());
alert(numbers.lastIndexOf()); alert(numbers.indexOf(, ));
alert(numbers.lastIndexOf(, )); var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person]; alert(people.indexOf(person));
alert(morePeople.indexOf(person));