4. 数组

4.1. 脚本 [tab-01]
以下脚本展示了 JavaScript 数组的一些特性。它们与 PHP 数组相似,但有一个显著区别:它们通过指针进行操作,并且被视为对象。
'use strict';
// 数组是通过其地址操作的对象
const tab1 = [1, 2, 3];
// 地址复制
const tab2 = tab1;
// tab1 和 tab2 指向同一个数组
console.log("tab1===tab2 :", tab1 === tab2);
// 可以通过 tab1 或 tab2 任意一个来修改数组
tab2[1] = 10;
console.log("tab1=", tab1);
console.log("tab2=", tab2);
执行
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\tableaux\tab-01.js"
tab1===tab2 : true
tab1= [ 1, 10, 3 ]
tab2= [ 1, 10, 3 ]
注释
- 结果的第 2 行表明 [tab1] 和 [tab2] 是两个相等的实体,实际上是两个相等的指针;
- 结果的第 4 行和第 5 行显示,这两个指针指向同一个数组;
4.2. 脚本 [tab-02]
该脚本表明,JavaScript 数组与编译型语言中的数组有所不同。
'use strict';
// 数组
const tab = [];
console.log("tab=", tab, ", longueur=[", tab.length, "]");
console.log("-------------------------------");
// 初始化一个元素
tab[3] = 100;
tab[1] = "huit";
// 数组
console.log("tab=", tab, ", longueur=[", tab.length, "]");
console.log("-------------------------------");
// toString
console.log("tab.toString=[", tab.toString(), "]");
console.log("-------------------------------");
// 数组的键即其索引
for (let key of tab.keys()) {
console.log("clé=[", key, "], valeur=[", tab[key], "]");
}
console.log("-------------------------------");
// 数组的值
for (let value of tab.values()) {
console.log("valeur=[", value, "]");
}
- 第 4 行:一个空数组;
- 第8行:数组没有固定大小。它仅仅是一系列通过编号索引的元素。即使其他元素尚未定义,也可以初始化第3个元素;
- 第16-24行:JavaScript数组的行为与PHP数组类似;
执行
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\tableaux\tab-02.js"
tab= [] , longueur=[ 0 ]
-------------------------------
tab= [ <1 empty item>, 'huit', <1 empty item>, 100 ] , longueur=[ 4 ]
-------------------------------
tab.toString=[ ,huit,,100 ]
-------------------------------
clé=[ 0 ], valeur=[ undefined ]
clé=[ 1 ], valeur=[ huit ]
clé=[ 2 ], valeur=[ undefined ]
clé=[ 3 ], valeur=[ 100 ]
-------------------------------
valeur=[ undefined ]
valeur=[ huit ]
valeur=[ undefined ]
valeur=[ 100 ]
4.3. 脚本 [tab-03]
该脚本演示了 [tableau] 对象的各种方法。
'use strict';
// 数组可以包含不同类型的数据
const tab = [1, 2, "un", "deux", true, [10, 20], { prop1: 10, prop2: "abc" }];
// console.log 能够显示数组的内容
show(1);
console.log("tab=", tab);
show(2);
// 使用 foreach 遍历数组
tab.forEach(element => {
console.log("élément=", element, typeof (element));
});
show("2b");
// 实现相同功能的另一种写法
tab.forEach(function (element) {
console.log("élément=", element, typeof (element));
});
show(3);
// 使用 for 循环遍历数组
for (let i = 0; i < tab.length; i++) {
console.log("i=", i, "tab[i]=", tab[i]);
}
show(4);
// 修改 tab[i]
tab[5] = [];
// 显示
console.log("tab=", tab);
show(5);
// 删除最后一个元素
let element = tab.pop(tab);
console.log("élément=", element, "tab=", tab);
show(6);
// 在数组末尾添加一个元素
tab.push('xyz');
console.log("tab=", tab);
show(7);
// 在数组开头添加一个元素
tab.unshift(1000);
console.log("tab=", tab);
show(8);
// 从数组中移除第一个元素
element = tab.shift();
console.log("élément=", element, "tab=", tab);
show(9);
// 从数组中移除第2个元素
element = tab.splice(2, 1);
console.log("élément=", element, "tab=", tab);
show(10);
// 从数组中移除从第 1 个元素开始的两个元素
element = tab.splice(1, 2);
console.log("élément=", element, "tab=", tab);
// 函数
function show(param) {
console.log("[", param, ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ]");
}
注释
- 第 3 行和第 24 行展示了 PHP 数组与 JavaScript 数组之间的区别:
- 第 3 行将变量 [tab] 声明为常量;
- 第24行修改了元素tab[5];
第 3 行,被声明为常量的只是指向该数组的指针,而不是数组本身。数组本身是可以被修改的。
- 第14-16行:通过数组[tab]中的方法[forEach]遍历数组[tab]。 该方法接收一个函数定义作为参数,可称为字面量函数。该参数函数接收一个参数:数组 [tab] 的当前元素。该函数会针对数组的每个元素被调用。这种写法在 JavaScript 中很常见;
- 第 9-10 行:这里使用另一种语法来定义参数函数。与通常的写法:
- function(p1, p2, …, pn){….}
而是写成:
- (续)
- (p1,p2, ..,pn)=>{.…}。这被称为“箭头”语法;
- 其余代码通过注释进行说明;
关于此脚本,需注意:
- 数组是一个由指针引用的对象;
- 该对象具有 [forEach, pop, push, shift, unshift] 方法;
4.4. 脚本 [tab-04]
该脚本展示了数组对象的其他方法。
'use strict';
// 数组操作方法
// 一个数组
const tab = [];
for (let i = 0; i < 10; i++) {
tab[i] = i * 10;
}
// 显示
console.log("tab=", tab);
// 映射
const tab2 = tab.map(element => {
return { prop1: element, prop2: element * element }
});
// 显示
console.log("tab=", tab);
console.log("tab2=", tab2);
// 无初始值的 reduce
const somme = tab.reduce((accumulator, currentValue) => accumulator + currentValue);
console.log("somme tab=", somme);
// 带初始值的 reduce
const somme2 = tab.reduce((accumulator, currentValue) => accumulator + currentValue, 10);
console.log("somme2 tab=", somme2);
// 过滤
const tab4 = tab.filter((element) => {
if (element > 50) {
return element;
}
});
console.log("tab4=", tab4);
// 查找
const element1 = tab.find((element) => (element > 20));
console.log("élément1=", element1);
// findIndex
const index1 = tab.findIndex((element) => (element === 20));
console.log("index1 20=", index1);
// indexOf
const index2 = tab.indexOf(30);
console.log("index2 30=", index2);
const index3 = tab.indexOf(31);
console.log("index3 31=", index3);
// lastIndexOf
const index4 = [4, 5, 4, 2].lastIndexOf(4);
console.log("index4 4=", index4);
// 排序
const tab5 = [4, 5, 4, 2].sort();
console.log("tab5=", tab5);
// 反向排序
const tab6 = [4, 5, 4, 2].sort((e1, e2) => {
if (e1 > e2) {
return -1;
}
else if (e1 === e2) {
return 0;
} else {
return +1;
}
});
console.log("tab6=", tab6);
注释
- 第 13-15 行:方法 [map] 接受一个转换函数作为参数。该函数会针对数组的每个元素被反复调用。其作用是将该元素转换为其他形式,此处为具有属性 [prop1, prop2] 的对象。 方法 [map] 返回一个新数组。原数组保持不变:
tab= [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 ]
tab2= [ { prop1: 0, prop2: 0 },
{ prop1: 10, prop2: 100 },
{ prop1: 20, prop2: 400 },
{ prop1: 30, prop2: 900 },
{ prop1: 40, prop2: 1600 },
{ prop1: 50, prop2: 2500 },
{ prop1: 60, prop2: 3600 },
{ prop1: 70, prop2: 4900 },
{ prop1: 80, prop2: 6400 },
{ prop1: 90, prop2: 8100 } ]
- 第 20 行:方法 [reduce] 接受一个双参数函数作为参数,该函数会针对数组的每个元素被反复调用。该函数接受两个参数:
- [currentValue] 是数组中的当前元素;
- [accumulator] 是该函数获得的最新结果。如果未为该累加器指定初始值,则其值为 0;
- 首次调用累加函数时,它返回 [0+tab[0]]。累加器被赋值为该值;
- 第二次调用时,它返回累加器+tab[1],即 tab[0]+tab[1];
- 第三次,它返回累加器+tab[2],即 tab[0]+tab[1]+tab[2];
- 等等。最终,累加器将表示数组中所有元素的和 [tab];
- 第26行:方法[filter]的参数是一个筛选函数。该函数针对数组中的每个元素被反复调用,并接收该元素作为参数。如果该元素需要保留,则该函数应返回:
- [true](若需保留该元素);
- 否则返回 [false];
- 第 33 行:方法 [find] 的参数是一个搜索函数。该函数会针对数组中的每个元素反复被调用,并接收该元素作为参数。如果接收到的元素满足搜索条件,则该函数应返回 [true]。此时,该过程即告结束。 因此,方法 [find] 返回 0 或 1 个元素;
- 第 36 行:方法 [findIndex] 的工作原理与方法 [find] 相同,但它不返回找到的元素,而是返回该元素在数组中的索引;
- 第39、41行:方法 [indexOf(valeur)] 在数组中搜索 [valeur] 并返回其索引,若未找到则返回 -1;
- 第 44 行:方法 [lastIndexOf(valeur)] 的工作原理与方法 [indexOf(valeur)] 相同,但从数组的末尾开始搜索;
- 第 47 行:无参数的 [sort] 方法返回按自然顺序(数字、字符串)排序的数组;
- 第50行:当自然排序不适用时,需向方法[sort]传递一个包含两个参数(e1,e2)的函数,该函数返回:
- 若 e1 应排在 e2 之后,则返回 +1;
- -1 表示 e1 应排在 e2 之前;
- 0 表示两个元素应具有相同的排序位置;
方法 [sort] 会反复调用作为参数传递的该函数,以比较数组中的两个元素;