javascript 数组总结
刚刚结束春节假期,这个春节想了很多,关于未来长远的发展方向也大致明确了。。。
言归正传,下面来总结一下js中数组的用法,以后发现有其他用法也会更新这篇文章。
一:定义
- 使用Array构造函数
let test1 = new Array();// [] let test2 = new Array(3);// [undefined, undefined] // 使用Array.of方法创建数组时可以消除这种差异 let test3 = new Array(3, 4);// [3, 4]
- 使用数组字面量方法
let test1 = [];// [] let test2 = [3];// [3] let test3 = [3, 4];// [3,4]
二:属性
- 索引
- 索引是基于0的
- 索引小于0时返回undefined
- 索引最大值为arr.length - 1,获取超过索引最大值对应的值时返回undefined,赋值超过索引最大值对应的值时添加元素。arr[arr.length] = value相当于arr.push(value)
- length
- length是基于1的,是数组的项数
- 数组的length不是readonly项目,所以可以通过设置数组的length进行在数组末尾的增项减项(Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
三:检测
- 假定只有一个全局执行环境, array instanceof Array
- ES5新方法, Array.isArray(array)
四:数组方法
数组实现了Array这个接口,讨论数组的方法就是要搞明白这个接口定义。
1 // ES5定义的接口 2 interface Array<T> { 3 /** 4 * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array. 5 * 数组的length属性不是readonly的,可以通过数组length来实现在数组末尾的增项减项(可以多个一起), 6 * 和数组的栈方法(push pop)(只能单个)一致, 7 */ 8 length: number; 9 /** 10 * Returns a string representation of an array. 11 * 中间加上, 相当于array.join(',') 12 */ 13 toString(): string; 14 /** 15 * Returns a string representation of an array. The elements are converted to string using their toLocalString methods. 16 * 一般情况下返回的结果和toString方法相同 17 */ 18 toLocaleString(): string; 19 /** 20 * Removes the last element from an array and returns it. 21 * 栈方法,弹出数组末尾的项目 22 */ 23 pop(): T | undefined; 24 /** 25 * Appends new elements to an array, and returns the new length of the array. 26 * 栈方法,在数组末尾增加项目 27 * @example 28 * let array = [1, 2]; 29 * array.push(3); // [ 1, 2, 3 ] 30 * array.push(3, 4); // [ 1, 2, 3, 4 ] 注意push方法的参数不是数组 31 * array.push([3, 4]); // [ 1, 2, [ 3, 4 ] ] 32 * @param items New elements of the Array. 33 */ 34 push(...items: T[]): number; 35 /** 36 * Removes the first element from an array and returns it. 37 * 队列方法,弹出数组开头项目 38 */ 39 shift(): T | undefined; 40 /** 41 * Inserts new elements at the start of an array. 42 * 队列方法,在数组开头增加项目 43 * 和栈方法类似,unshift方法的参数不是数组。 44 * 栈方法和队列方法是js实现栈数据结构和队列数据结构的具体表现,使用时大多数情况下不会刻意的想到数据结构, 45 * 不过还是要锻炼把问题简化为数据结构的能力。 46 * @param items Elements to insert at the start of the Array. 47 */ 48 unshift(...items: T[]): number; 49 /** 50 * Reverses the elements in an Array. 51 * 翻转数组,基本没什么用 52 * @example 53 * let array = [1, 2]; 54 * array.reverse(); 55 * console.log(array)// [ 2, 1 ] 56 */ 57 reverse(): T[]; 58 /** 59 * Sorts an array. 60 * 排序方法,可选参数,省略时默认升序,按照Ascll码进行比较 61 * 比较函数接受数组中的任意2个项目,返回一个数字,数字小于0时,第一个参数在前,数字大于0时,第二个参数在前 62 * 大规模的排序使用这个方法会造成性能问题,这要研究sort方法的实现原理,这里留个坑,以后来补。(TODO) 63 * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order. 64 */ 65 sort(compareFn?: (a: T, b: T) => number): this; 66 /** 67 * Combines two or more arrays. 68 * 使用concat方法主要要分清与push方法的差别, 69 * push方法会改变原来的数组,返回的是新的数组的长度,concat方法是创建原来数组的副本,不改变原来的数组,返回的是连接好的新的数组 70 * push方法的参数是数组时,只会把数组当做一个元素进行处理,concat方法的参数是数组时则会展开 71 * concat方法更符合函数式编程思想(concat可以用来创建数组的副本) 72 * @param items Additional items to add to the end of array1. 73 */ 74 concat(...items: ConcatArray<T>[]): T[]; 75 /** 76 * Combines two or more arrays. 77 * concat方法的参数可以是单个元素,也可以是多个数组,数组会被展开成多个元素进行连接 78 * @param items Additional items to add to the end of array1. 79 */ 80 concat(...items: (T | ConcatArray<T>)[]): T[]; 81 /** 82 * Adds all the elements of an array separated by the specified separator string. 83 * 把数组转换为字符串,可以指定连接符,不指定连接符时默认为逗号 84 * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma. 85 */ 86 join(separator?: string): string; 87 /** 88 * Returns a section of an array. 89 * 返回数组的一部分,对原数组没有影响,这里可以原来创建数组的副本。根据函数式编程的思想,编写操作数组的函数时,应尽量使用slice创建副本,不改变传递参数数组 90 * @example1 91 * let array = [5, 6, 3, 8]; 92 * let array1 = array;//这里array1和array指向内存的同一个地址,值改变时相互影响 93 * console.log(array1)// [ 5, 6, 3, 8 ] 94 * array.length = 3; 95 * console.log(array1)// [ 5, 6, 3 ] 96 * @example2 97 * let array = [5, 6, 3, 8]; 98 * let array1 = array.slice();//这里array1和array指向内存的不同地址,值改变时不会相互影响 99 * console.log(array1)// [ 5, 6, 3, 8 ] 100 * array.length = 3; 101 * console.log(array1)// [ 5, 6, 3, 8 ] 102 * 指定开始位置和结束位置,位置都是从0开始的,注意,返回的数组包含开始位置的值,不包含结束位置的值 103 * 这里特殊的是位置可以为负数,为负数时则会加上数组的长度重新进行计算(为了方便从数组末尾取值) 104 * @example3 105 * console.log(array.slice(0, 2))//[ 5, 6 ]取得数组前面2个项目 106 * console.log(array.slice(-2))//[ 3, 8 ]取得数组后面2个项目 107 * console.log(array.slice(3, 2))//[]开始位置大于结束位置时,返回空数组 108 * @param start The beginning of the specified portion of the array. 109 * @param end The end of the specified portion of the array. 110 */ 111 slice(start?: number, end?: number): T[]; 112 /** 113 * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. 114 * 向数组中(删除、插入、替换)项目,会改变原来的数组,不符合函数式编程的思想 115 * (这里返回的是删除的项目,如果返回的是删除后的数组,就可以做到不改变原来的数组,不过这样和slice提取数组中的部分元素类似) 116 * @example1 删除项目 117 * let array = [5, 6, 3, 8]; 118 * console.log(array.splice(0, 2))//[ 5, 6 ] 从位置0开始删除2个元素,返回删除的元素组成的数组 119 * console.log(array)// [ 3, 8 ] 原来的数组被改变了 120 * @example2 插入项目 121 * let array = [5, 6, 3, 8]; 122 * console.log(array.splice(1, 0, 7, 9))//[] 插入项目时第2个参数为0,后面的参数就是要插入的元素 123 * console.log(array)// [ 5, 7, 9, 6, 3, 8 ] 124 * @example3 替换项目 125 * let array = [5, 6, 3, 8]; 126 * console.log(array.splice(1, 1, 7, 9))//[ 6 ] 替换项目就是把原来的项目删除,把新的项目添加进去 127 * console.log(array)// [ 5, 7, 9, 3, 8 ] 128 * @param start The zero-based location in the array from which to start removing elements. 129 * @param deleteCount The number of elements to remove. 130 */ 131 splice(start: number, deleteCount?: number): T[]; 132 /** 133 * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. 134 * @param start The zero-based location in the array from which to start removing elements. 135 * 开始位置 136 * @param deleteCount The number of elements to remove. 137 * 要删除的项数 138 * @param items Elements to insert into the array in place of the deleted elements. 139 * 从开始位置插入的项目,参数不是数组,传递数组则会被当做一个元素 140 */ 141 splice(start: number, deleteCount: number, ...items: T[]): T[]; 142 /** 143 * Returns the index of the first occurrence of a value in an array. 144 * 位置方法,如果没有找到返回-1,indexOf方法主要用来找index,但是一直以来使用都是判断数组中是否包含某个元素 145 * @example1 判断数组中是否包含某个元素 146 * array.indexOf(value) !== -1 // 包含这个元素 147 * ES7中提供includes方法,返回的是true或者false,更适合判断数组中是否包含某个元素 148 * @param searchElement The value to locate in the array. 149 * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0. 150 */ 151 indexOf(searchElement: T, fromIndex?: number): number; 152 /** 153 * Returns the index of the last occurrence of a specified value in an array. 154 * 与indexOf方法的区别在于搜索顺序 155 * @param searchElement The value to locate in the array. 156 * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array. 157 */ 158 lastIndexOf(searchElement: T, fromIndex?: number): number; 159 /** 160 * Determines whether all the members of an array satisfy the specified test. 161 * 数组中的所有元素运行给定的判定函数,判定函数都返回true时,every方法的返回结果才为true,否则为false 162 * 一旦遇到false就不会继续执行其他的元素,直接返回false 163 * @example1 判断数组中的元素是否都是奇数 164 * array.every((v) => {return v % 2 !== 0}) 165 * 判定函数接受3个参数,当前元素,当前元素在数组中对应的位置,当前数组 166 * @example2 every方法接受第2个可选参数,this对象指向的对象,不指定时this对象指向空对象。every方法中想要使用外部的数据时,可以使用thisArg,但是要注意不能使用箭头函数 167 * let array = [5]; 168 * let obj = {} 169 * obj.name = 'WT' 170 * array.every(function (v) {console.log(this)}, obj) // { name: 'WT' } 171 * array.every((v) => {console.log(this)}, obj) // {} 注意,如果使用了箭头函数,指定thisArg是没有作用的 172 * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array. 173 * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. 174 */ 175 every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; 176 /** 177 * Determines whether the specified callback function returns true for any element of an array. 178 * 数组中的所有元素运行给定的判定函数,判定函数有一个返回true时,some方法的返回结果就为true,运行结果都为false时,some方法的结果才为false 179 * 一旦遇到true就不会继续执行其他的元素,直接返回true 180 * 想要使用外部的数据时,可以使用thisArg,但是要注意不能使用箭头函数,参考every方法的说明 181 * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array. 182 * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. 183 */ 184 some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; 185 /** 186 * Performs the specified action for each element in an array. 187 * 没有返回值,单纯的遍历数组中的元素,不能中途return,如果需要return使用for循环替代 188 * 想要使用外部的数据时,可以使用thisArg,但是要注意不能使用箭头函数,参考every方法的说明 189 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. 190 * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. 191 */ 192 forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; 193 /** 194 * Calls a defined callback function on each element of an array, and returns an array that contains the results. 195 * 重组数组,返回参数函数的返回值组成的数组,不改变原来的数组,可以用来创建数组的副本(slice和concat方法也可以),符合函数式编程思想 196 * 想要使用外部的数据时,可以使用thisArg,但是要注意不能使用箭头函数,参考every方法的说明 197 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. 198 * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. 199 */ 200 map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; 201 /** 202 * Returns the elements of an array that meet the condition specified in a callback function. 203 * 过滤数组,返回参数函数的返回值为true时对应的元素组成的数组 204 * 想要使用外部的数据时,可以使用thisArg,但是要注意不能使用箭头函数,参考every方法的说明 205 * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. 206 * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. 207 */ 208 filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; 209 /** 210 * Returns the elements of an array that meet the condition specified in a callback function. 211 * 想要使用外部的数据时,可以使用thisArg,但是要注意不能使用箭头函数,参考every方法的说明 212 * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. 213 * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. 214 */ 215 filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; 216 /** 217 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. 218 * 规约方法,用于需要保留状态的情况,也就是说,想得到一个值,必须知道上一个值是什么 219 * 接受可选参数,初始值,没有指定时初始值为数组的第一个元素 220 * 规约函数接受4个参数,之前的值,当前元素,当前元素对应的index, 数组 221 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. 222 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. 223 */ 224 reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; 225 reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; 226 /** 227 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. 228 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. 229 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. 230 */ 231 reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; 232 /** 233 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. 234 * 规约方法,reduce方法是从数组的第一个开始合并,reduceRight方法是从数组的最后一个元素开始合并 235 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. 236 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. 237 */ 238 reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; 239 reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; 240 /** 241 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. 242 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. 243 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. 244 */ 245 reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; 246 247 // 索引取得值 248 [n: number]: T; 249 }
ES5的数组方法是最基本的,在实际的业务开发中用到的也是最多的。ES6中对数组进行了扩展
- 数组实例的遍历(返回的都是遍历器,操作遍历器可以使用for of ,Array.from)
1 interface Array<T> { 2 /** Iterator */ 3 [Symbol.iterator](): IterableIterator<T>; 4 // 注意,3个方法返回的都是遍历器,不是返回的数组 5 // 要想取得遍历器的值,提供3种方法 6 7 // let array = [5,6]; 8 // for (let v of array.entries()) { // for of 遍历接口 9 // console.log(v)// [ 0, 5 ] [ 1, 6 ] 10 // } 11 // let entries = array.entries(); // 当做遍历器来遍历 12 // console.log(entries.next().value); // [ 0, 5 ] 13 // console.log(entries.next().value); // [ 1, 6 ] 14 // Array.from(array.entries()).forEach((v) => {console.log(v)}) // 使用Array.from方法转换为数组 15 /** 16 * Returns an iterable of key, value pairs for every entry in the array 17 * 返回键值对组成的遍历器(用来把一维数组转成2维数组) 18 */ 19 entries(): IterableIterator<[number, T]>; 20 21 /** 22 * Returns an iterable of keys in the array 23 * 返回键组成的遍历器 24 */ 25 keys(): IterableIterator<number>; 26 27 /** 28 * Returns an iterable of values in the array 29 * 返回值组成的遍历器 30 */ 31 values(): IterableIterator<T>; 32 }
2. ES6中在数组实例上还添加了其他的操作方法
1 interface Array<T> { 2 /** 3 * Returns the value of the first element in the array where predicate is true, and undefined 4 * otherwise. 5 * @param predicate find calls predicate once for each element of the array, in ascending 6 * order, until it finds one where predicate returns true. If such an element is found, find 7 * immediately returns that element value. Otherwise, find returns undefined. 8 * @param thisArg If provided, it will be used as the this value for each invocation of 9 * predicate. If it is not provided, undefined is used instead. 10 * 找到第一个返回值为true的元素,返回这个元素,如果都为false返回undefined(使用indexof也可以完成同样的操作,先取得index,再通过array[index]取得元素,不过这没有find方便) 11 */ 12 find<S extends T>(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined; 13 find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined; 14 15 /** 16 * Returns the index of the first element in the array where predicate is true, and -1 17 * otherwise. 18 * @param predicate find calls predicate once for each element of the array, in ascending 19 * order, until it finds one where predicate returns true. If such an element is found, 20 * findIndex immediately returns that element index. Otherwise, findIndex returns -1. 21 * @param thisArg If provided, it will be used as the this value for each invocation of 22 * predicate. If it is not provided, undefined is used instead. 23 * 找到第一个返回值为true的元素,返回这个元素,如果都为false返回-1 24 */ 25 findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number; 26 27 /** 28 * Returns the this object after filling the section identified by start and end with value 29 * @param value value to fill array section with 30 * @param start index to start filling the array at. If start is negative, it is treated as 31 * length+start where length is the length of the array. 32 * @param end index to stop filling the array at. If end is negative, it is treated as 33 * length+end. 34 * 使用给定值替换数组中的元素 35 */ 36 fill(value: T, start?: number, end?: number): this; 37 38 /** 39 * Returns the this object after copying a section of the array identified by start and end 40 * to the same array starting at position target 41 * @param target If target is negative, it is treated as length+target where length is the 42 * length of the array. 43 * @param start If start is negative, it is treated as length+start. If end is negative, it 44 * is treated as length+end. 45 * @param end If not specified, length of the this object is used as its default value. 46 */ 47 copyWithin(target: number, start: number, end?: number): this; 48 }
find 和findIndex弥补了indexOf方法在检测NaN时的不足
[NaN].indexOf(NaN) // -1
[NaN].findIndex(v => Object.is(NaN, v)) // 0
补充: fill的作用是替换数组中的一些值(使用开始和结束的index),可以使用splice实现,不过没有fill方便
1 let a = [1, 2, 3]; 2 // a.fill(8); // [ 8, 8, 8 ] 3 // a.fill(8, 0, 1); // [ 8, 2, 3 ] 4 // a.fill(8, -1); // [ 1, 2, 8 ]
3.ES6还在Array这个全局对象上添加了2个方法
1 interface ArrayConstructor { 2 /** 3 * Creates an array from an iterable object. 4 * @param iterable An iterable object to convert to an array. 5 */ 6 from<T>(iterable: Iterable<T> | ArrayLike<T>): T[]; 7 8 /** 9 * Creates an array from an iterable object. 10 * @param iterable An iterable object to convert to an array. 11 * @param mapfn A mapping function to call on every element of the array. 12 * @param thisArg Value of 'this' used to invoke the mapfn. 13 */ 14 from<T, U>(iterable: Iterable<T> | ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; 15 }
Array.from方法可以把2类数据转换为数组,一是遍历器(使用扩展运算符...也可以把遍历器转换为数组),二是类数组对象(有length属性)
1 let array = [5,6]; 2 let entries = array.entries(); 3 console.log(entries)// {} 4 console.log([...entries])// [ [ 0, 5 ], [ 1, 6 ] ] 5 console.log(Array.from(entries))// [] 这里是因为遍历器已经被遍历完成,从这里可以看出了遍历器不符合函数式编程的思想
1 let array = [5,6]; 2 let entries = array.entries(); 3 console.log(entries)// {} 4 console.log(Array.from(entries))// [ [ 0, 5 ], [ 1, 6 ] ] 这里就符合预期了
of<T>(...items: T[]): T[]; of方法是为了弥补Array构造函数的不足
new Array(3) // [undefined, undefined, undefined]
Array.of(3) // [3] 更加符合预期,Array.of方法总是符合参数值组成的数组。
五:总结
js对数组的支持是比较友好的,可以进行链式调用,并且一部分方法符合函数式编程的思想。
数组的方法很多,在什么场景是使用什么方法非常重要。
关于数组的总结就到这里了,后期会持续维护文章
作成: 2019-02-08
修改:
- 2019-02-10 23:26:18 添加分类
- 2019-02-16 18:03:45 添加fill方法的例子