标签:
数组是值的有序集合。每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。
JavaScript数组的索引是基于0的32位数值:第一个元素的索引是0,最大可能为4294967294(2^32 - 2)。
通常,数组的实现是经过优化的,用数字索引来访问数组元素一般比访问常规的对象属性要快很多。
实际上,数组是对象的特殊形式,索引可理解为对象的属性,使用[]
访问数组时,索引首先转换为字符串,然后作为属性使用。
JavaScript数组有以下特点:
var empty = []; // 空数组
var misc = [1.1, true, "a"]; // 包含3个不同类型的数组
var count = [1,,3]; // 包含2个元素的数组,中间的值为undefined
var a = new Array(10); // 定义长度为10的数组,注:元素为空
var b = new Array(5, 4, 3, "a");// 定义包含4个元素的数组,长度也为4
所有的数组都是对象,可以为其创建任意名字的属性。但如果使用的属性是数组的索引,数组就会更新length属性值。
var a = [1]; // 数组的length为 1
a[-1.23] = true; // 数组的length为 1,只是数组多了个属性"-1.23"
a["1000"] = 0; // 数组的length为 1001
a[0.00]; // =>1,相当于a[0]
由于数组也是对象,所以JavaScript数组没有”越界”的情况。当试图查询不存在的属性时,不会报错,只会得到undefined值。
稀疏数组就是包含不连续索引的数组,此时数组的length属性值大于元素的个数(undefined不计入元素个数)。
var a = [1,,3]; // 第2个元素为undefined
0 in a; // true
1 in a; // false,元素不存在
2 in a; // true
a.length; // 3,实际元素为2个
var b = new Array(3);
0 in b; // false
1 in b; // false
2 in b; // false
b.length; // 3,实际元素为0个
var c = [undefined]; // 显式定义,元素存在
0 in c; // true
c.length; // 1,实际元素为1个
JavaScript的数组长度length是可写的。
var a = [1,2,3,4,5];
a.length = 3; // 现在a为[1,2,3]
a.length = 0; // 现在a为[]
a.length = 5; // 长度为5,但是没有元素,相当于new Array(5)
var b = [1,2,3,4,5];
b.length = 7; // 增大数组长度
alert(6 in b); // false, 并没有添加元素
alert(b.length); // 7,但是只有5个元素
元素的添加有3种方法:
直接量、push()、unshift(),这3个方法添加元素后都会影响数组的length属性值。
元素的删除有3种方法:
delete、pop()、shift(),这3个方法中只有delete不会影响数组的length属性值,pop()、shift()都会影响length属性值。
var a = [1, 2];
a[2] = 3; // a.length = 3
a.push(4); // a.length = 4
a.pop(); // a.length = 3
delete a[1]; // a.length = 3,注意:delete不改变length属性,但是a[1]元素变成了undefined
for(var i=0; i < a.length; i++) {
// 跳过元素值为undefined的元素和不存在的元素
if (a[i] == undefined) continue;
}
for(var i=0; i < a.length; i++) {
// 跳过不存在的元素
if (!(i in a)) continue;
}
由于数组也是对象,所以可以使用for/in对数组进行遍历,但是遍历出的属性会包含继承的属性,所以一般不使用for/in对数组进行遍历。如果使用,则需要添加过滤条件:
for(var i in a) {
// 跳过继承属性
if (!a.hasOwnProperty(i)) continue;
}
或者
for(var i in a) {
// 跳过不是非负整数的i
if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
}
JavaScript不支持真正的多维数组,但可以用数组的数组来近似。访问数组的数组中的元素,只要简单地使用两次[]
操作符即可。
var table = new Array(10);
for(var i=0; i < table.length; i++)
table[i] = new Array(10);
table[5][7] = 35;
var a = [1, 2, 3];
a.join(); // => "1,2,3",默认使用","隔开元素
a.join("&"); // => "1&2&3",指定分隔符
var b = new Array(10); // 空数组
b.join("-"); // => "---------",9个分隔符
var a = [1, 2, 3];
a.reverse().join(); // => "3,2,1",此时的a是[3, 2, 1]
var a = new Array("banana", "cherrry", "apple");
a.sort();
var s = a.join(", "); // => "apple, banana, cherrry",数组a现在是["apple", "banana", "cherrry"]
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]
a.concat(4, [5, [6,7]]);// 返回[1,2,3,4,5,[6,7]]
a.join(); // "1,2,3",原始值不发生改变
var a = [1,2,3,4,5];
a.slice(0, 3); // 返回[1,2,3]
a.slice(3); // 返回[4,5]
a.slice(-3, -1); // 返回[3,4],反向索引,从倒数第3个到倒数第1个元素
var a = [1,2,3,4,5,6,7,8];
a.splice(4); // 返回[5,6,7,8],a是[1,2,3,4]
a.splice(1,2); // 返回[2,3],a是[1,4]
a.splice(1,1); // 返回[4],a是[1]
var b = [1,2,3,4,5];
a.splice(2,0, "a", "b"); // 返回[],a是[1,2, "a","b", 3,4,5]
a.splice(2,2, [1,2], 3); // 返回["a", "b"],a是[1,2, [1,2],3, 3,4,5]
var stack = [];
stack.push(1,2); // stack:[1,2],返回2
stack.push([1,2]); // stack:[1,2, [1,2]],返回3
stack.pop(); // stack:[1,2],返回[1,2]
var a = [1];
a.unshift(2); // a:[2, 1],返回2
a.unshift(3, [4,5]); // a:[3, [4,5], 2,1],返回4。 注意:"3,[4,5]"是一次性插入的,顺序不变
a.shift(); // a:[[4,5], 2, 1],返回3
[1,2,3].toString(); // "1,2,3"
[1, [2, "c"]].toString(); // "1,2,c"
ECMAScript5中大部分数组方法的第1个参数接收一个函数,并且对数组的每个元素调用一次该函数。如果是稀疏数组,对不存在的元素不调用传递的函数。
在大多数情况下,传递的函数使用3个参数:数组元素、元素的索引和数组本身。通常,只需要第1个参数值,可以忽略后2个参数。
var data = [1,2,3,4,5];
var sum = 0;
data.forEach(function(value) { sum += value;} );
sum; // => 15
function foreach(a, f, t) {
try {
a.forEach(f, t);
}
catch(e) {
if(e === foreach.break) return; // 提前终止
else throw e;
}
}
foreach.break = new Error("StopIteration");
a = [1,2,3];
b = a.map(function(x) {return x*x; }); // b是[1,4,9]
注意:map()返回的是新数组,它不修改原始数组,如果是稀疏数组,返回的也是相同方式的稀疏数月:它具有相同的长度,相同的缺失元素。
a = [5,4,3,2,1];
smallvalues = a.filter(function(x) { return x < 3; }); // smallvalues是[2, 1]
var a = [1,2,3,4,5];
a.every(function(x) { return x < 10; }); // => true,所有的值<10
a.every(function(x) { return x % 2 === 0}); // => false,不是所有的值都是偶数
a.some(function(x) { return x % 2 === 0; }) // => true,a含有偶数值
a.some(isNaN); // => false,a不包含非数值元素
var a = [1,2,3,4,5];
var sum = a.reduce(function(x,y) { return x+y; }, 0); // 数组求和
var max = a.reduce(function(x,y) { return (x>y)?x:y; }); // 求最大值
在求和的调用中,第1次传递的参数为0(初始值)和1(数组的第1个元素),返回1;第2次调用使用参数1(返回值)和2(数组的第2个元素),返回3;然后计算3+3=6、6+4=10、10+5=15。
- 在空数组上,不带初始值调用reduce将导致类型错误异常。
- 如果数组只有一个元素并且没有指定初始值,或者有一个空数组并且指定一个初始值,reduce()只是简单地返回那个值而不会调用函数。
var a = [0,1,2,1,0];
a.indexOf(1); // =>1: a[1] = 1
a.lastIndexOf(1); // =>3: a[3] = 1
a.indexOf(3); // =>-1: a中没有值为3的元素
在ECMAScript5中,可以使用Array.isArray()来判断一个对象是否是数组。
Array.isArray([]); // true
Array.isArray({}); // false
在ECMAScript3中isArray()函数的代码可以这样写:
var isArray = Function.isArray || function(o) {
return typeof o === "object" &&
Object.prototype.toString.call(o) === "[objet Array]";
};
数组有一些特性是其他对象所有没有的:
这些特性让数组与常规的对象有明显的区别。但是它们不是定义数组的本质特性。
可以把拥有数值length属性和对应非负整数属性的对象看作是一种类型的数组。
很多数组算法针对类数组对象工作得很好,就像针对真正的数组一样。
定义一个类数组对象,如下所示:
var a = {};
var i = 0;
while(i < 10) {
a[i] = i*i;
i++;
}
a.length = i;
// 现在,可以当真正的数组进行遍历操作
var total = 0;
for(var j=0; j < a.length; j++)
total += a[j];
Arguments对象就是一个类数组对象;在客户端JavaScript中,一些DOM方法(如document.getElementsByTagName())也返回类数组对象。
s = "JavaScript";
Array.prototype.join.call(s, " "); // => "J a v a S c r i p t"
注意:不能使用会修改数组原始值的算法(如,reverse(), sort())操作字符串,否则会抛出类型错误异常。
标签:
原文地址:http://blog.csdn.net/byrantch/article/details/51417730