犀牛书笔记 (第7章 数组)
每个数组都有length属性,对于非稀疏数组是元素个数,对于稀疏数组,length大于所有元素的最高索引。
数组从Array.prototype继承属性和方法。
ES6增加了typed array, 定型数组。固定长度和类型。支持二进制数据字节级访问。
创建数组:
数组字面量: 如果数组字面量中连续包含多个逗号,且逗号之间没有值,那么这个数组就是稀疏数组,访问时返回undefined。数组字面量语法允许末尾出现逗号,因此[,,]长度是2而不是3。
…扩展符:扩展操作符是创建数组浅副本的一种方式。
let original = [1,2,3]
let copy = [...original]
扩展操作符适用于任何可迭代对象。包括字符串、集合。
let digits = [..."12345"]
let letters = [..."hello world"]
[... new Set(letters)] //数组去重
Array()构造函数:
1. 不传参数调用: let a = new Array()
2. 传长度: let a = new Array(10)
3. 传元素
Array.of()/Array.from()工厂方法:
为什么ES6中要有Array.of ? Array构造函数,传一个参数是长度,传一个以上数值时才是元素,这意味着构造函数无法创建只包含一个数值元素的数组。
Array.from期待一个可迭代对象或者类数组对象作为其第一个参数,并返回包含该对象元素的新数组。Array.from(iterable)等价于[…iterable], 所以也是创建数据副本的一种简单方式。还可以有第二个参数,传入一个类似于Map的映射函数。
读写数组元素:
方括号语法。
数组特殊的地方在于,会自动维护length属性的值。数组是一种特殊对象。js会将数值索引转换为字符串,然后用这个字符串作为属性名去取值。
关于索引和对象属性名:所有索引都是属性名,但只有介于0-(2^32 – 2)的整数属性名才是索引。所有数组都是对象,可以在这对象上创建任意名字的属性,只是如果这个属性是索引的话,js引擎会自动维护这个对象的length属性。a[“1000”]是数组的1001个元素,a[1.000]是数组的第二个元素。js数组没有越界的错误。查询任何对象中不存在的属性都不会导致错误,只是会返回undefined。
稀疏数组:可以认为稀疏数组是包含undefined元素的稠密数组。
数组长度:
长度不变式:length > 最大索引。为了维护这个invariant, 数组有两个特殊行为。1. 如果给数组赋值索引i, 且i >= length, 则length会更新为i+1。 2. 给length赋值为小于其当前值的当前n, 则任何索引大于或等于n的数组元素都会从数组中被删掉。
添加和删除数组元素:
添加:1. 新索引赋值;2. push方法(相当于给a[a.length]赋值);3. unshift方法(把已有数组元素移动到更高索引位,然后在0索引处插入元素);
删除:pop ->对应于push, 操作队尾;shift: 对应于unshift, 删除并返回第一个元素,并把所有元素移动到低一位的索引;delete操作符:delete a[2], 类似于但不完全等同于给该元素赋值undefined; 把length设置一个新的比原来小的长度值,也可以从末尾删除元素。
splice方法可以插入/删除/替换 数组元素。
迭代数组:
最简单方法:使用for/of循环。如果想知道数组元素的索引,可以用entries方法和解构赋值
let everyother = ""
for (let [index, letter] of letters.entries()) {
if (index % 2 === 0) everyother += letter;
}
forEach()方法:
let uppercase = ""
letters.forEach(l => { uppercase += l.toUpperCase()})

多维数组:不支持,js里的多维数组实际是数组的数组。
数组方法:
Array类的方法,有的会修改调用它们的数组,有些不会。返回数组的方法,有时候返回的是新数组,原数组保持不变;有的原始数组会被修改,返回的是被修改后的数组的引用。
迭代器方法用于遍历数组元素,通常会对每个元素调用一次我们指定的函数。
栈和队列方法用于在开头或末尾向数组中添加元素或从数组中删除元素。
子数组方法用于提取、删除、插入、填充和复制更大数组的连续区域。
排序和搜索方法用于在数组中查找元素和对数组元素排序。
迭代器方法:第一个参数是自定义的函数。如果数组是稀疏的,不会对undefined的数组元素调用传入的这个函数。提供的函数被调用时会收到3个参数,分别是数组元素的值,数组元素的索引和数组本身。第二个参数是一个对象,扮演传入函数内部的this值。
forEach(): 没有break机制。
map(): 第一个参数,传入的函数,需要返回一个值。map返回一个新数组,而不修改调用它的数组。
filter()返回调用它的数组的子数组。传入的函数是个断言谓词。会跳过稀疏数组中缺失的元素,始终返回一个稠密的数组。
find()和findIndex(): 接收谓词函数,并在找到第一个元素时(函数值为true)停止迭代。此时find返回匹配的元素,findIndex返回匹配元素的索引。如果没有找到匹配的元素,则find返回undefiend, findIndex返回-1。
every()和some(): every与数学上的全称量词类似,只在断言函数对数组的所有元素都返回true时才返回true. some类似于存在量词,只要数组元素中有一个让它返回true就返回true。这两个都是短路的,即some在第一次返回true时返回true; every在第一次返回false时返回false。
reduce()和reduceRight(): 使用我们指定的函数归并数组元素,产生一个值。有时也称为inject/fold. reduce接受两个参数,第一个参数是执行归并操作的函数,第二个可选参数是初始值。归并函数的目的是把两个值归并为一个值。reduce中使用的函数与上面的函数不同点是,第一个参数是目前为止归并操作的累计结果;第二个参数开始才是值、索引、数组。如果reduce不指定第二个参数,则会使用调用数组的第一个元素为初始值,但如果数组为空,则会导致TypeError。reduceRight的不同点在于,它是从右到左遍历,而不是从左到右遍历。两者都不接受第二个参数作为归并函数的this值。
flat/flatMap打平数组
flat接收一个数值参数,作为打平数组的层级。flatMap则类似map, 但是映射的结果会被自动打平。即,a.flatMap(f) = a.map(f).flat()
concat()添加元素
concat创建并返回一个新数组,新数组包含调用concat方法的数组的元素,以及传给concat的参数。参数中的数组也会被打平一级,但不会递归打平。不修改调用它的参数。
栈和队列
栈操作:push/pop操作队尾,shift/unshift操作队头。都可以用于栈,但push/pop效率更高。可以用push/shift的组合来模拟队列。shift传多个参数时,是一次插入。

slice/splice/fill/copyWithin
slice:返回一个数组的切片或子数组。两个参数分别指定要返回切片的起止位置(包含起点不包含终点),一个参数指定起点到末尾。一个参数如果是负值,则相对于数组长度指定数组元素。这个方法不会修改调用它的数组。
splice:可以用于对数组进行插入和删除。原地修改。第一个参数指定插入或删除操作的起点位置。第二个参数指定要从数组中删除的元素个数。


前两个参数指定删除哪些元素,后面的参数指定在第一个参数index处插入到数组中的元素。
fill:

copyWithin:
把数组切片复制到数组中的新位置。就地修改数组并返回修改后的数组,但不会改变数组的长度。第一个参数指定要把第一个元素复制到的目的索引。第二个参数指定要复制的第一个元素的索引,默认值0。第三个参数指定要复制的元素切片的终止索引(不包含),默认值数组长度。与使用slice一样可以传入负值相对于数组末尾指定索引。

数组索引与排序方法:indexOf/lastIndexOf/includes/sort/reverse
indexOf和lastIndexOf使用===进行比较。
includes:测试是否包含某元素。与indexOf的不同在于,使用的相等算法不同,即认为NaN与自身相等。所以indexOf/lastIndexOf无法检测数组中的NaN值,但是includes可以。
sort(): 就地排序并返回排序后的数组。undefined会被排到末尾。默认字符序,可以自定义比较函数。
reverse(): 就地反转,并返回反序后的数组。
数组到字符串的转换
join, toString, toLocalString
静态数组函数:
Array.of, Array.from, Array.isArray
类数组对象:
有length属性和非负整数属性的对象,视同为数组。
在客户端JavaScript中,很多操作HTML文档的方法返回类数组对象。
多数数组方法有意设计成了泛型方法,因此除了真正的数组,同样可以用于类数组对象。但由于类数组对象不会继承Array.prototype, 所以无法直接在它们上面调用数组方法,为此可以使用Function.call方法。
作为数组的字符串:
js中的字符串类似于UTF-16 字符的只读数组。