您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

《JavaScript 闯关记》之数组

2026/2/14 4:04:31发布20次查看
数组是值的有序集合。每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。
javascript 数组是无类型的,数组元素可以是任意类型,并且同一个数组中的不同元素也可能有不同的类型。数组的元素甚至也可能是对象或其他数组。
javascript数组是动态的,根据需要它们会增长或缩减,并且在创建数组时无须声明一个固定的大小或者在数组大小变化时无须重新分配空间。
javascript 数组可能是稀疏的,数组元素的索引不一定要连续的,它们之间可以有空缺。每个javascript数组都有一个length属性。针对非稀疏数组,该属性就是数组元素的个数。针对稀疏数组,length比所有元素的索引要大。
javascript 数组是 javascript 对象的特殊形式,数组索引实际上和碰巧是整数的属性名差不多。通常,数组的实现是经过优化的,用数字索引来访问数组元素一般来说比访问常规的对象属性要快很多。
数组继承自 array.prototype 中的属性,它定义了一套丰富的数组操作方法。
创建数组
可以使用数组字面量和 new 关键字来创建数组。
使用数组字面量创建数组(推荐)
var empty = []; // 没有元素的数组 var primes = [2, 3, 5, 7, 11]; // 有5个数值的数组 var misc = [1.1, true, a]; // 3个不同类型的元素 // 数组直接量中的值不一定要是常量,可以是任意的表达式 var base = 1024; var table = [base, base+1, base+2, base+3]; // 也可以包含对象直接量或其他数组直接量 var b = [[1, {x:1, y:2}], [2, {x:3, y:4}]];
注意,不要忽略数组字面量的最后一个元素,仅以逗号结尾。下面几个案例,在不同的浏览器下,可能会被识别成2个元素,也有可能识别成3个元素,而造成程序bug。例如:
var nums = [,,,]; // 不好的写法 var names = [stone,,]; // 不好的写法 var colors = [red,green,]; // 不好的写法
var nums = [,,,]; // 不好的写法
var names = [stone,,]; // 不好的写法
var colors = [red,green,]; // 不好的写法
// 调用时没有参数 var a = new array(); // 调用时有一个数值参数,它指定长度 var a = new array(10); // 显式指定多个数组元素或者数组的一个非数值元素 var a = new array(5, 4, 3, 2, 1, testing);
数组元素的读和写
使用 [] 操作符来访问数组中的一个元素。数组的引用位于方括号的左边。方括号中是一个返回非负整数值的任意表达式。使用该语法既可以读又可以写数组的一个元素。例如:
var a = [world]; // 从一个元素的数组开始 var value = a[0]; // 读第0个元素 a[1] = 3.14; // 写第1个元素 var i = 2; a[i] = 3; // 写第2个元素 a[i + 1] = hello; // 写第3个元素 a[a[i]] = a[0]; // 读第0个和第2个元素,写第3个元素
请记住,数组是对象的特殊形式,可以为其创建任意名字的属性。但如果使用的属性是数组的索引,数组的特殊行为就是将根据需要更新它们的length属性值。
注意,可以使用负数或非整数来索引数组。这种情况下,数值转换为字符串,字符串作为属性名来用。既然名字不是非负整数,它就只能当做常规的对象属性,而非数组的索引。同样,如果凑巧使用了是非负整数的字符串,它就当做数组索引,而非对象属性。当使用的一个浮点数和一个整数相等时情况也是一样的。例如:
a[-1.23] = true; // 这将创建一个名为-1.23的属性 a[1000] = 0; // 这是数组的第1001个元素 a[1.000] // 和 a[1] 相等
事实上数组索引仅仅是对象属性名的一种特殊类型,这意味着 javascript 数组没有「越界」错误的概念。当试图查询任何对象中不存在的属性时,不会报错,只会得到 undefined 值。
稀疏数组
稀疏数组就是包含从0开始的不连续索引的数组。通常,数组的 length 属性值代表数组中元素的个数。如果数组是稀疏的,length属性值大于元素的个数。可以用 array() 构造函数或简单地指定数组的索引值大于当前的数组长度来创建稀疏数组。
a = new array(5); // 数组没有元素,但是 a.length = 5 a = []; // 创建一个空数组,a.length = 0 a[1000] = 0; // 添加一个元素,a.length 被自动更新为1001
足够稀疏的数组通常在实现上比稠密的数组更慢、内存利用率更高,在这样的数组中查找元素的时间与常规对象属性的查找时间一样长。
需要注意的是,当省略数组直接量中的值时(使用连续的逗号,比如 [1,,3] ),这时所得到的数组也是稀疏数组,省略掉的值是不存在的:
var a1 = [,'1','2']; // 此数组长度是3 var a2 = [undefined]; // 此数组包含一个值为 undefined 的元素 console.log(0 in a1); // false,a1 在索引0处没有元素 console.log(0 in a2); // true,a2 在索引0处有一个值为 undefined 的元素
了解稀疏数组是了解 javascript 数组的真实本质的一部分。尽管如此,实际上你所碰到的绝大多数 javascript 数组不是稀疏数组。并且,如果你确实碰到了稀疏数组,你的代码很可能像对待非稀疏数组一样来对待它们,只不过它们包含一些 undefined 值。
数组长度
每个数组有一个 length 属性,就是这个属性使其区别于常规的 javascript 对象。针对稠密(也就是非稀疏)数组,length 属性值代表数组中元素的个数。其值比数组中最大的索引大1。例如:
[].length // 0,数组没有元素 ['a','b','c'].length // 3,最大的索引为2,length 为3
当数组是稀疏的时,length 属性值大于元素的个数。而且关于此我们可以说的一切也就是数组长度保证大于它每个元素的索引值。或者,换一种说法,在数组中(无论稀疏与否)肯定找不到一个元素的索引值大于或等于它的长度。为了维持此规则不变化,数组有两个特殊的行为。
第一个如同上面的描述:如果为一个数组元素赋值,它的索引 i 大于或等于现有数组的长度时,length 属性的值将设置为i+1。
第二个特殊的行为就是设置 length 属性为一个小于当前长度的非负整数 n 时,当前数组中那些索引值大于或等于 n 的元素将从中删除。例如:
a = [1,2,3,4,5]; // 从5个元素的数组开始 a.length = 3; // 现在 a 为[1,2,3] a.length = 0; // 删除所有的元素。a 为[ ] a.length = 5; // 长度为5,但是没有元素,就像 new array(5)
还可以将数组的 length 属性值设置为大于其当前的长度。实际上这不会向数组中添加新的元素,它只是在数组尾部创建一个空的区域。
在 ecmascript 5中,可以用 object.defineproperty() 让数组的 length 属性变成只读的。例如:
a = [1,2,3]; // 从3个元素的数组开始 object.defineproperty(a, length, {writable: false}); // 让 length 属性只读 a.length = 0; // a 不会改变
数组元素的添加和删除
我们已经见过添加数组元素最简单的方法,为新索引赋值。例如:
a = [] // 开始是一个空数组 a[0] = zero; // 然后向其中添加元素 a[1] = one;
也可以使用 push() 方法在数组末尾增加一个或多个元素。例如:
a = []; // 开始是一个空数组 a.push(zero); // 在末尾添加一个元素。a = [zero] a.push(one, two); // 再添加两个元素。a = [zero, one, two]
可以像删除对象属性一样使用 delete 运算符来删除数组元素。例如:
a = [1,2,3]; delete a[1]; // a在索引1的位置不再有元素 1 in a // => false: 数组索引1并未在数组中定义 a.length // => 3: delete操作并不影响数组长度
注意,对一个数组元素使用 delete 不会修改数组的 length 属性,也不会将元素从高索引处移下来填充已删除属性留下的空白。如果从数组中删除一个元素,它就变成稀疏数组。
数组遍历
使用 for 循环是遍历数组元素最常见的方法。例如:
var keys = object.keys(o); // 获得 o 对象属性名组成的数组 var values = [] // 在数组中存储匹配属性的值 for(var i = 0; i < keys.length; i++) { // 对于数组中每个索引 var key = keys[i]; // 获得索引处的键值 values[i] = o[key]; // 在 values 数组中保存属性值 }
在嵌套循环或其他性能非常重要的上下文中,可以看到这种基本的数组遍历需要优化,数组的长度应该只查询一次而非每次循环都要查询。例如:
for(var i = 0, len = keys.length; i 2); }); console.log(someresult); // true
下面再看一看 filter() 函数,它利用指定的函数确定是否在返回的数组中包含的某一项。例如:
var numbers = [1,2,3,4,5,4,3,2,1]; var filterresult = numbers.filter(function(item, index, array){ return (item > 2); }); console.log(filterresult); // [3,4,5,4,3]
map() 也返回一个数组,而这个数组的每一项都是在原始数组中的对应项上运行传入函数的结果。例如,可以给数组中的每一项乘以2,然后返回这些乘积组成的数组。例如:
var numbers = [1,2,3,4,5,4,3,2,1]; var mapresult = numbers.map(function(item, index, array){ return item * 2; }); console.log(mapresult); // [2,4,6,8,10,8,6,4,2]
最后一个方法是 foreach(),它只是对数组中的每一项运行传入的函数。这个方法没有返回值,本质上与使用 for 循环迭代数组一样。例如:
var numbers = [1,2,3,4,5,4,3,2,1]; numbers.foreach(function(item, index, array){ //执行某些操作 });
缩小方法
ecmascript 5还新增了两个缩小数组的方法:reduce() 和 reduceright()。这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。其中,reduce() 方法从数组的第一项开始,逐个遍历到最后。而 reduceright() 则从数组的最后一项开始,向前遍历到第一项。
这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为缩小基础的初始值。传给 reduce() 和 reduceright()的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。
使用 reduce() 方法可以执行求数组中所有值之和的操作。例如:
var values = [1,2,3,4,5]; var sum = values.reduce(function(prev, cur, index, array){ return prev + cur; }); console.log(sum); // 15
第一次执行回调函数,prev是1,cur是2。第二次,prev是3(1加2的结果),cur是3(数组的第三项)。这个过程会持续到把数组中的每一项都访问一遍,最后返回结果。
reduceright() 的作用类似,只不过方向相反而已。例如:
var values = [1,2,3,4,5]; var sum = values.reduceright(function(prev, cur, index, array){ return prev + cur; }); console.log(sum); // 15
使用 reduce() 还是 reduceright(),主要取决于要从哪头开始遍历数组。除此之外,它们完全相同。
关卡
完成下面3个数组去重方法。
// 挑战一,一维数组 var arr = [2,3,4,2,3,5,6,4,3,2]; var unique = function(arr){ // 待实现方法体 } console.log(unique(arr)); // [2,3,4,5,6]
// 挑战二,二维数组 var arr = [2,3,4,[2,3,4,5],3,5,[2,3,4,2],4,3,6,2]; var unique = function(arr){ // 待实现方法体 } console.log(unique(arr)); // [2,3,4,5,6]
// 挑战三,三维数组或 n 维数组 var arr = [2,3,4,[2,3,[2,3,4,2],5],3,5,[2,3,[2,3,4,2],2],4,3,6,2]; var unique = function(arr){ // 待实现方法体 } console.log(unique(arr)); // [2,3,4,5,6]
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product