数组对象(Array object)
数组(array)是一个有序的数据集合,可以通过数组名称(name)和索引(index)进行访问。
JavaScript中没有明确的数组数据类型。但是,可以通过使用内置Array对象和它的方法对数组进行操作。Array对象有很多操作数组的方法,比如合并、反转、排序等。数组对象有一个决定数组长度和使用正则表达式操作其他属性的属性。
创建数组
var arr = new Array(element0, element1, ..., elementN);
var arr = Array(element0, element1, ..., elementN);
var arr = [element0, element1, ..., elementN];
//创建一个长度不为0,又没有任何元素的数组
var arr = new Array(arrayLength);
var arr = Array(arrayLength);
// 这样有同样的效果
var arr = [];
arr.length = arrayLength;
//数组(array)也可以作为一个属性(property)分配给一个新的或者已存在的对象(object)
var obj = {};
// ...
obj.prop = [element0, element1, ..., elementN];
// OR
var obj = {prop: [element0, element1, ...., elementN]}
/*用单个元素初始化一个数组,而这个元素恰好又是数字(Number),必须使用括号语法。
当单个的数字(Number)传递给Array()构造函数时,将会被解释为数组长度,并非单个元素。*/
var arr = [42]; // 创建一个只有唯一元素的数组:
// the number 42.
var arr = Array(42); // 创建一个没有元素的数组,
// 但是数组的长度被设置成42.
// 上面的代码与下面的代码等价
var arr = [];
arr.length = 42;
填充数组
//通过给元素赋值来填充数组
var emp = [];
emp[0] = "Casey Jones";
emp[1] = "Phil Lesh";
emp[2] = "August West";
/*给数组操作符的是一个非整形数值,那么将作为
一个代表数组的对象的属性(property)创建*/
var arr = [];
arr[3.4] = "Oranges";
console.log(arr.length); // 0
console.log(arr.hasOwnProperty(3.4)); // true
//也可以在创建数组的时候去填充它
var myArray = new Array("Hello", myVar, 3.14159);
var myArray = ["Mango", "Apple", "Orange"]
引用数组元素
var myArray = ["Wind", "Rain", "Fire"];
var arr = ["one", "two", "three"];
arr[2]; // three
arr["length"]; // 3
理解length
在实施层面, JavaScript实际上是将元素作为标准的对象属性来存储,把数组索引作为属性名。长度属性是特殊的,它总是返回最后一个元素的索引值加1。
var cats = [];
cats[30] = ['Dusty'];
console.log(cats.length); // 31
//也可以分配length属性。写一个小于数组元素数量的值会缩短数组,写0会彻底清空数组
var cats = ['Dusty', 'Misty', 'Twiggy'];
console.log(cats.length); // 3
cats.length = 2;
console.log(cats); // logs "Dusty,Misty" - Twiggy has been removed
cats.length = 0;
console.log(cats); // logs nothing; the cats array is empty
cats.length = 3;
console.log(cats); // [undefined, undefined, undefined]
遍历数组
var colors = ['red', 'green', 'blue'];
for (var i = 0; i < colors.length; i++) {
console.log(colors[i]);
}
colors.forEach(function(color) {
console.log(color);
});
在数组定义时省略的元素不会在forEach遍历时被列出,但是手动赋值为undefined的元素是会被列出的
var array = ['first', 'second', , 'fourth'];
// returns ['first', 'second', 'fourth'];
array.forEach(function(element) {
console.log(element);
})
if(array[2] === undefined) { console.log('array[2] is undefined'); } // true
var array = ['first', 'second', undefined, 'fourth'];
// returns ['first', 'second', undefined, 'fourth'];
array.forEach(function(element) {
console.log(element);
})
数组的方法
- concat()——连接两个数组并返回一个新的数组。
var myArray = new Array("1", "2", "3");
myArray = myArray.concat("a", "b", "c");
// myArray is now ["1", "2", "3", "a", "b", "c"]
- join(deliminator = ',') ——将数组的所有元素连接成一个字符串。
var myArray = new Array("Wind", "Rain", "Fire");
var list = myArray.join(" - "); // list is "Wind - Rain - Fire"
- push() ——在数组末尾添加一个或多个元素,并返回数组操作后的长度。
var myArray = new Array("1", "2");
myArray.push("3"); // myArray is now ["1", "2", "3"]
- pop() ——从数组移出最后一个元素,并返回该元素。
var myArray = new Array("1", "2", "3");
var last = myArray.pop();
// myArray is now ["1", "2"], last = "3"
- shift() ——从数组移出第一个元素,并返回该元素。
var myArray = new Array ("1", "2", "3");
var first = myArray.shift();
// myArray is now ["2", "3"], first is "1"
- unshift() ——在数组开头添加一个或多个元素,并返回数组的新长度。
var myArray = new Array ("1", "2", "3");
myArray.unshift("4", "5");
// myArray becomes ["4", "5", "1", "2", "3"]
- slice(start_index, upto_index) ——从数组提取一个片段,并作为一个新数组返回。
var myArray = new Array ("a", "b", "c", "d", "e");
myArray = myArray.slice(1, 4); // starts at index 1 and extracts all elements
// until index 3, returning [ "b", "c", "d"]
- splice(index, count_to_remove, addElement1, addElement2, ...)——从数组移出一些元素,(可选)并替换它们。
var myArray = new Array ("1", "2", "3", "4", "5");
myArray.splice(1, 3, "a", "b", "c", "d");
// myArray is now ["1", "a", "b", "c", "d", "5"]
// This code started at index one (or where the "2" was),
// removed 3 elements there, and then inserted all consecutive
// elements in its place.
- reverse()—— 颠倒数组元素的顺序:第一个变成最后一个,最后一个变成第一个。
var myArray = new Array ("1", "2", "3");
myArray.reverse();
// transposes the array so that myArray = [ "3", "2", "1" ]
- sort() ——给数组元素排序。
var myArray = new Array("Wind", "Rain", "Fire");
myArray.sort();
// sorts the array so that myArray = [ "Fire", "Rain", "Wind" ]
- indexOf(searchElement[, fromIndex]) ——在数组中搜索searchElement 并返回第一个匹配的索引。
var a = ['a', 'b', 'a', 'b', 'a'];
console.log(a.indexOf('b')); // logs 1
// Now try again, starting from after the last match
console.log(a.indexOf('b', 2)); // logs 3
console.log(a.indexOf('z')); // logs -1, because 'z' was not found
- lastIndexOf(searchElement[, fromIndex]) ——和 indexOf 差不多,但这是从结尾开始,并且是反向搜索。
var a = ['a', 'b', 'c', 'd', 'a', 'b'];
console.log(a.lastIndexOf('b')); // logs 5
// Now try again, starting from before the last match
console.log(a.lastIndexOf('b', 4)); // logs 1
console.log(a.lastIndexOf('z')); // logs -1
- forEach(callback[, thisObject]) ——在数组每个元素项上执行callback。
var a = ['a', 'b', 'c'];
a.forEach(function(element) { console.log(element);} );
// logs each item in turn
- map(callback[, thisObject]) ——遍历数组,并通过callback对数组元素进行操作,并将所有操作结果放入数组中并返回该数组。
var a1 = ['a', 'b', 'c'];
var a2 = a1.map(function(item) { return item.toUpperCase(); });
console.log(a2); // logs A,B,C
- filter(callback[, thisObject]) ——返回一个包含所有在回调函数上返回为true的元素的新数组(callback在这里担任的是过滤器的角色,当元素符合条件,过滤器就返回true,而filter则会返回所有符合过滤条件的元素)。
var a1 = ['a', 10, 'b', 20, 'c', 30];
var a2 = a1.filter(function(item) { return typeof item == 'number'; });
console.log(a2); // logs 10,20,30
- every(callback[, thisObject]) ——当数组中每一个元素在callback上被返回true时就返回true(every其实类似filter,只不过它的功能是判断是不是数组中的所有元素都符合条件,并且返回的是布尔值)。
function isNumber(value){
return typeof value == 'number';
}
var a1 = [1, 2, 3];
console.log(a1.every(isNumber)); // logs true
var a2 = [1, '2', 3];
console.log(a2.every(isNumber)); // logs false
- some(callback[, thisObject]) ——只要数组中有一项在callback上被返回true,就返回true(类似every,不过前者要求都符合筛选条件才返回true,后者只要有符合条件的就返回true)。
function isNumber(value){
return typeof value == 'number';
}
var a1 = [1, 2, 3];
console.log(a1.some(isNumber)); // logs true
var a2 = [1, '2', 3];
console.log(a2.some(isNumber)); // logs true
var a3 = ['1', '2', '3'];
console.log(a3.some(isNumber)); // logs false
- reduce(callback[, initialValue]) ——使用回调函数 callback(firstValue, secondValue) 把数组列表计算成一个单一值(数组元素两两递归处理的方式把数组计算成一个值)
var a = [10, 20, 30];
var total = a.reduce(function(first, second) { return first + second; }, 0);
console.log(total) // Prints 60
- reduceRight(callback[, initalvalue]) ——和 reduce()相似,但这从最后一个元素开始的。
多维数组
var a = new Array(4);
for (i = 0; i < 4; i++) {
a[i] = new Array(4);
for (j = 0; j < 4; j++) {
a[i][j] = "[" + i + "," + j + "]";
}
}
/*
Row 0: [0,0] [0,1] [0,2] [0,3]
Row 1: [1,0] [1,1] [1,2] [1,3]
Row 2: [2,0] [2,1] [2,2] [2,3]
Row 3: [3,0] [3,1] [3,2] [3,3]
*/
数组和正则表达式
当一个数组作为字符串和正则表达式的匹配结果时,该数组将会返回相关匹配信息的属性和元素。 RegExp.exec(), String.match() 和 String.split() 的返回值是一个数组。
使用类数组对象
一些 JavaScript 对象, 例如 document.getElementsByTagName() 返回的 NodeList 或者函数内部可用的 arguments 对象,他们表面上看起来,外观和行为像数组,但是不共享他们所有的方法。arguments 对象提供一个 length 属性,但是不实现 forEach() 方法。
//Array的原生(prototype)方法可以用来处理类似数组行为的对象
function printArguments() {
Array.prototype.forEach.call(arguments, function(item) {
console.log(item);
});
}
/*Array的常规方法也可以用于处理字符串,
因为它提供了序列访问字符转为数组的简单方法:*/
Array.prototype.forEach.call("a string", function(chr) {
console.log(chr);
});
数组推导式(Array comprehensions)
计划在 ECMAScript 7, array comprehensions 被规范化并提供一个有用的快捷方式,用来实现如何在另一个数组的基础上构造一个新的数组。推导式可以经常被用在那些需要调用 map() 和 filter()函数的地方,或作为一种结合这两种方式。
var numbers = [1, 2, 3, 4];
var doubled = [for (i of numbers) i * 2];
console.log(doubled); // logs 2,4,6,8
/*map()方法
var doubled = numbers.map(function(i){return i * 2;});
*/
推导式也可以用来筛选满足条件表达式的元素
var numbers = [1, 2, 3, 21, 22, 30];
var evens = [i for (i of numbers) if (i % 2 === 0)];
console.log(evens); // logs 2,22,30
/*filter()
var evens = numbers.filter(function(i){return i % 2 === 0;});
*/
类型化数组(Typed Arrays )
JavaScript typed arrays 是类数组对象(array-like object),其提供访问原始二进制数据的机制。 Array 对象动态增长和收缩,可以有任何JavaScript值。但对于类型化数组,JavaScript引擎执行优化使得这些数组访问速度快速。 随着Web应用程序变得越来越强大,添加音频和视频处理等功能、可以使用 WebSockets 、使用原始数据, 这都需要访问原始的二进制数据,所以专门的优化将有助于JavaScript代码能够快速和容易地操纵原始二进制数据类型的数组。
缓冲区和视图:类型化的数组结构
为了实现最大的灵活性和效率,JavaScript类型数组被分解为缓冲(Buffer)和视图(views)。缓冲(由ArrayBuffer 实现)是代表数据块的对象,它没有格式可言,并没有提供任何机制来访问其内容。为了访问包含在缓冲区中的内存,需要使用视图。视图提供了一个上下文,即数据类型、起始偏移量和元素数,这些元素将数据转换为实际类型数组。
ArrayBuffer
ArrayBuffer是一种数据类型,用于表示一个通用的、固定长度的二进制数据缓冲区。不能直接操纵一个ArrayBuffer中的内容;需要创建一个数组类型视图或DataView来代表特定格式的缓冲区,并从而实现读写缓冲区的内容。
类型数组视图(Typed array views)
类型数组视图具有自描述性的名字,并且提供数据类型信息,例如Int8, Uint32, Float64等等。如一个特定类型数组视图Uint8ClampedArray. 它意味着数据元素只包含0到255的整数值。它通常用于Canvas数据处理。