Array 对象
Array
对象时用于构造数组的全局对象,类似时类似于列表的高阶对象。
Array
对象主要用于存储多个数据项,数据可以是任意类型。
所有主流浏览器均支持该对象。
语法
字面量
[element0, element1, ..., elementN]
数组类型转换函数
Array(element0, element1, ..., elementN)
构造函数
new Array(element0, element1, ..., elementN) new Array(arrayLength)
Array.from()
⭐️ ES2015(ES6)新特性
Array.from()
方法用于将一个类数组对象或可迭代对象转换成一个新的数组实例。
语法
Array.from(arrayLike [, mapfn [, thisArg]])
类型声明:
interface ArrayLike<T> { readonly length: number; readonly [n: number]: T; } interface ArrayConstructor { from<T>(arrayLike: ArrayLike<T>): T[]; from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; }
参数说明:
返回值:
返回一个新的数组实例。
方法说明
具备以下两种条件的的对象可以通过
Array.from()
方法转换成真正的数组:
- 类数组对象:即拥有
length
属性和若干索引属性的任意对象 - 可迭代对象:即部署了 Iterator 接口的对象,可以获取对象中的元素,如
Map
和Set
等 - Array.from() 方法有一个可选参数 mapfn,让你可以在最后生成的数组上再执行一次 Array.prototype.map 方法后再返回。也就是说 Array.from(arrayLike, mapfn, thisArg) 就相当于 Array.from(arrayLike).map(mapfn, thisArg) ,除非创建的不是可用的中间数组。 这对一些数组的子类,如对类型化数组来说很重要,因为中间数组的值在调用 map() 时需要是适当的类型。
- from() 的 length 属性为 1 ,即 Array.from.length === 1。
- 在 ES2015 中, Class 语法允许我们为内置类型(比如 Array)和自定义类新建子类(比如叫 SubArray)。这些子类也会继承父类的静态方法,比如 SubArray.from(),调用该方法后会返回子类 SubArray 的一个实例,而不是 Array 的实例。
代码示例
基本用法
const bar = ['a', 'b', 'c']; Array.from(bar); // ["a", "b", "c"] Array.from('foo'); // ["f", "o", "o"]
Array.isArray()
Array.isArray()
方法用于确定某个值是否是数组类型。
语法
Array.isArray(arg);
类型声明:
interface ArrayConstructor { isArray(arg: any): arg is any[]; } declare var Array: ArrayConstructor;
参数说明:
返回值:
如果对象是 Array
的实例,则返回 true
;否则为 false
。
代码示例
下面的函数调用都返回 true
Array.isArray([]); Array.isArray([1]); Array.isArray(new Array()); Array.isArray(Array.prototype);
鲜为人知的事实:其实 Array.prototype
也是一个数组。
Array.isArray(Array.prototype);
下面的函数调用都返回 false
。
Array.isArray(); Array.isArray({}); Array.isArray(null); Array.isArray(undefined); Array.isArray(17); Array.isArray('Array'); Array.isArray(true); Array.isArray(false); Array.isArray({ __proto__: Array.prototype });
Array.prototype.concat()
Array.prototype.concat()
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
语法
const new_array = old_array.concat( item1[, itemN ] )
类型声明:
interface ConcatArray<T> { readonly length: number; readonly [n: number]: T; join(separator?: string): string; slice(start?: number, end?: number): T[]; } interface Array<T> { concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; }
参数说明:
返回值:
返回合并后新的 Array
实例。
方法说明
concat 方法创建一个新的数组,它由被调用的对象中的元素组成,每个参数的顺序依次是该参数的元素(如果参数是数组)或参数本身(如果参数不是数组)。它不会递归到嵌套数组参数中。
concat 方法不会改变 this 或任何作为参数提供的数组,而是返回一个浅拷贝,它包含与原始数组相结合的相同元素的副本。 原始数组的元素将复制到新数组中,如下所示:
- 对象引用(而不是实际对象):
concat
将对象引用复制到新数组中。原始数组和新数组都引用相同的对象。 也就是说,如果引用的对象被修改,则更改对于新数组和原始数组都是可见的。这包括也是数组的数组参数的元素。 - 数据类型如字符串,数字和布尔(不是
String
,Number
和Boolean
对象):concat
将字符串和数字的值复制到新数组中。
注意:数组/值在连接时保持不变。此外,对于新数组的任何操作(仅当元素不是对象引用时)都不会对原始数组产生影响,反之亦然。
代码示例
连接两个数组
以下代码将两个数组合并为一个新数组。
const alpha = ['a', 'b', 'c']; const numeric = [1, 2, 3]; alpha.concat(numeric); // Outputs: ['a', 'b', 'c', 1, 2, 3]
Array.prototype.indexOf()
Array.prototype.indexOf()
方法用于查找数组成员第一次出现指定字符的位置。
语法
arr.indexOf( searchElement [, fromIndex] )
类型声明:
interface Array<T> { indexOf(searchElement: T, fromIndex?: number): number; }
参数说明:
返回值:
返回数组元素在当前数组中第一次查找到的起始位置(索引)
方法说明
该方法使用 Strict Equality(无论是绝对相等 ===
,还是 Triple-equals 操作符都基于同样的方法)进行判断查找的元素与数组中包含的元素之间的关系。
代码示例
基本用法
var arr = [1, 2, 3, 4, 5]; arr.indexOf(1); // 0 arr.indexOf(7); // -1 arr.indexOf(4, 2); // 3 arr.indexOf(3, -1); // -1 arr.indexOf(3, -3); // 2
Array.prototype.join()
Array.prototype.join()
方法将数组(或类数组对象)的所有成员连接到字符串中。
语法
const str = arr.jon(separator);
类型声明:
interface Array<T> { join(separator?: string): string; }
参数说明:
返回值:
返回一个所有数组成员连接的字符串。如果数组长度为 0,则返回空字符串。
方法说明
所有的数组成员被转换成字符串,再用一个分隔符将这些字符串连接起来。如果元素是 undefined
或者 null
, 则会转化成空字符串。
代码示例
基本用法
const arr = ['1', '2', '3', '4', '5']; // 不传参数默认以逗号作为分隔符 arr.join(); // '1,2,3,4,5' arr.join(', '); // '1, 2, 3, 4, 5' arr.join(' + '); // '1 + 2 + 3 + 4 + 5' arr.join(''); // '12345'
Array.prototype.flat()
⭐️ ES2019(ES10)新特性
Array.prototype.flat()
方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
语法
arr.flat([depth]);
类型声明:
type FlatArray<Arr, Depth extends number> = { done: Arr; recur: Arr extends ReadonlyArray<infer InnerArr> ? FlatArray< InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth] > : Arr; }[Depth extends -1 ? 'done' : 'recur']; interface ReadonlyArray<T> { flat<A, D extends number = 1>(this: A, depth?: D): FlatArray<A, D>[]; } interface Array<T> { flat<A, D extends number = 1>(this: A, depth?: D): FlatArray<A, D>[]; }
参数说明:
返回值:
返回一个包含将数组与子数组种所有元素的新数组。
代码示例
基本用法
const arr1 = [0, 1, 2, [3, 4]]; console.log(arr1.flat()); // exprected output: [0, 1, 2, 3, 4] const arr2 = [0, 1, 2, [[[3, 4]]]]; console.log(arr2.flat()); // exprected output: [0, 1, 2, [ 3, 4]];
Array.prototype.every()
every()
方法遍历数组中每个成员,通过回调函数判断是否所有成员都满足特定条件。
语法
arr.every( predicate [, thisArg ] )
类型声明:
interface Array<T> { every<S extends T>( predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any ): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; }
参数说明:
callback
函数的参数:
currentValue
:当前数组中处理的元素index
:数组中正处理的当前元素的索引array
:被调用的数组
返回值:
返回当所有数组元素满足回调函数的判断时返回 true
,否则返回 false
。
方法说明
- 执行该方法会为数组每个成员执行一次回调函数,回调函数需要通过判断代码块后,返回布尔值作为该成员是否通过检测的凭证,如果通过则再为下一个数组成员执行回调函数,直到遇到第一个判断为 false 的数组成员则立即给实例方法返回 false,否则全部成员都通过检测的回调函数,则返回 true。
- 回调函数只会为那些已经被赋值的索引调用,不会为那些被删除或从来没有被赋值的索引调用。
- 如果为实例方法提供一个
thisArg
参数,则该参数为调用回调函数时的this
值。如果省略该参数,则为回调函数被调用时的this
值,在非严格模式下为全局对象,在严格模式下传入undefined
。 - 遍历的数组成员范围在第一次调用回调函数之前就已确定了。在调用
every()
之后添加到数组中的成员不会被回调函数访问到。如果数组中存在的成员被更改,则他们传入回调函数的值是every()
访问到他们那一刻的值。那些被删除的成员或未被赋值的成员将不会被访问到。
代码示例
下例检测数组中的所有元素是否都大于 10。
const isBigEnough = (element, index, array) => (element >= 10)[(12, 5, 8, 130, 44)].every(isBigEnough)[ // false (12, 54, 18, 130, 44) ].every(isBigEnough); // true
Array.prototype.filter()
Array.prototype.filter()
方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。
语法
arr.filter( callback = function (currentValue, index, arr) {} [, thisArg ] )
类型声明:
interface Array<T> { filter<S extends T>( predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any ): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; }
参数说明:
callback
函数的参数:
currentValue
:当前数组中处理的元素index
:数组中正处理的当前元素的索引array
:被调用的数组
返回值:
返回一个新的通过测试的成员的集合的数组。
方法说明
- 该方法为数组中的每个成员调用一次回调函数,并利用所有使得回调函数返回
true
或 等价于true
的值的成员创建一个新数组。回调函数只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过回调函数测试的元素会被跳过,不会被包含在新数组中。 - 如果提供
thisArg
参数,则它会被作为回调函数被调用时的this
值。否则,回调函数的this
值在非严格模式下将是全局对象,严格模式下为undefined
。 - 遍历的元素范围在第一次调用回调函数之前就已经确定了。在调用该方法之后被添加到数组中的元素不会被 遍历到。如果已经存在的元素被改变了,则他们传入回调函数的值是遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。
代码示例
基本用法
const isBigEnough = (value) => value >= (10)[(12, 5, 8, 130, 44)].filter(isBigEnough); // false
Array.prototype.find()
Array.prototype.find()
方法返回数组中满足提供的判定函数的第一个成员。
语法
arr.find( callback [, thisArg ] )
类型声明:
interface Array<T> { find<S extends T>( predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any ): S | undefined; find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T | undefined; }
参数说明:
callback
函数的参数:
currentValue
:当前数组中处理的元素index
:数组中正处理的当前元素的索引array
:被调用的数组
返回值:
当遍历到的数组成员通过回调函数的判定时,返回数组中该成员,否则返回 undefined
。
代码示例
用对象的属性查找数组里的对象
let foo = [ { name: 'a', quantity: 2 }, { name: 'b', quantity: 0 }, { name: 'c', quantity: 5 }, ]; const getFoo = (key) => (arr) => arr.name === key; console.log(foo.find(getFoo('c'))); // { name: 'c', quantity: 5 }
Array.prototype.findIndex()
findIndex()
方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
语法
arr.findIndex( callback [, thisArg ])
类型声明:
interface Array<T> { findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number; }
参数说明:
callback
函数的参数:
currentValue
:当前数组中处理的元素index
:数组中正处理的当前元素的索引array
:被调用的数组
代码示例
基本用法
const arr = [1, 2, 3, 4, 5, 12, 22, 2, 2, 2]; const foo = arr.findIndex(function (currentValue, index, array) { return currentValue === 2; }); console.log(foo); // 1
Array.prototype.forEach()
Array.prototype.forEach()
方法用于迭代数组的每项成员。
语法
arr.forEach( callbackfn [, thisArg ] )
类型声明:
interface Array<T> { forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; }
参数说明:
callbackfn
函数的参数:
currentValue
:当前数组中处理的元素index
:数组中正处理的当前元素的索引array
:被调用的数组
返回值:
返回 undefined
。
方法说明
- 该方法按升序为数组中含有效值的每一项执行一次回调函数,那些已删除(使用
delete
方法等情况)或者未初始化的项将被跳过(但不包括那些值为undefined
的项,例如在稀疏数组中)。 - 该方法遍历的范围在第一次调用回调函数前就会确定。调用 forEach() 后添加到数组中的项不会被 callbackfn 访问到。如果已经存在的值被改变,则传递给 callbackfn 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift() ) ,之后的元素将被跳过。
forEach()
为每个数组元素执行callbackfn
函数;不像map()
或者reduce()
,它总是返回undefined
值,并且不可链式调用。典型用例是在一个链的最后执行副作用。
注意: 没有办法中止或者跳出 forEach
循环,除了抛出一个异常。如果你需要这样,使用 forEach()
函数是错误的,你可以用一个简单的循环作为替代。如果您正在测试一个数组里的元素是否符合某条件,且需要返回一个布尔值,那么可使用 every()
或 some()
。如果可用,新方法 find()
或者 findIndex()
也可被用于真值测试的提早终止。
代码示例
const arr = ['a', 'b', 'c']; arr.forEach(function (element) { console.log(element); }); arr.forEach((element) => console.log(element)); // a b c
Array.prototype.map()
Array.prototype.map()
根据传递的转换函数,更新给定数组中的每个值,并返回一个相同长度的新数组。它接受一个回调函数作为参数,用以执行转换过程。
const new_arr = old_arr.map(callback = function(currentValue, index, array){} [, thisArg])
类型声明:
interface Array<T> { map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; }
参数说明:
callback
函数的参数:
currentValue
:当前数组中处理的元素index
:数组中正处理的当前元素的索引array
:被调用的数组
返回值:
返回回调函数的结果,如果未设定返回值,则返回当前遍历的数组成员。
方法说明
- 该方法按升序为数组中含有效值的每一项执行一次回调函数,那些已删除(使用
delete
方法等情况)或者未初始化的项将被跳过(但不包括那些值为undefined
的项,例如在稀疏数组中)。 - 使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。在 map 方法执行的过程中:原数组中新增加的元素将不会被 callback 访问到;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map 方法遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。
代码示例
下面的代码创建了一个新数组,值为原数组中对应数字的平方根。
const numbers = [1, 4, 9]; const roots = numbers.map(Math.sqrt); // Math.sqrt(x) console.log(numbers); // [1, 4, 9] console.log(roots); // [1, 2, 3],
Array.prototype.push()
Array.prototype.push()
方法用于向当前数组的末尾添加一个或多个元素,并返回新的数组长度。
语法
arr.push( item1 [, items...] )
类型声明:
interface Array<T> { push(...items: T[]): number; }
参数说明:
如果添加的元素类型为数组类型,仍然会被当作一个元素看待,只是这个元素是数组类型而已。如果要合并两个数组,请使用 concat()
函数。
返回值:
返回添加元素后的数组长度。
方法说明
当向数组中添加新的元素时,数组的 length
属性也会随之改变。一般而言,数组的 length
属性将会加 N
( N
为添加的元素个数)。
push() 方法有意具有通用性。该方法和 call() 或 apply() 一起使用时,可应用在类似数组的对象上。push() 方法根据 length 属性来决定从哪里开始插入给定的值。如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。
代码示例
基本用法
const foo = ['a', 'b']; const bar = foo.push('c', 'd'); console.log(foo); // ['a', 'b', 'c', 'd'] console.log(bar); // 4
Array.prototype.pop()
Array.prototype.pop()
方法用于移除数组最后一个成员,并返回该数组成员。
语法
arr.pop();
类型声明:
interface Array<T> { pop(): T | undefined; }
返回值:
返回被移除的数组成员。如果该数组为空(没有任何元素),则返回 undefined
。
方法说明
- 该方法和
call()
或apply()
一起使用时,可应用在类数组对象上。pop
方法根据length
属性来确定最后一个元素的位置。如果不包含length
属性或length
属性不能被转成一个数值,会将length
置为 0,并返回undefined
。 - 由于该方法会移除数组中的最后一个元素,数组的
length
属性也会随之改变(如果数组中有元素的话),一般而言,数组的length
属性将会减 1。 - 如果你在一个空数组上调用
pop()
,它返回undefined
。
代码示例
基本用法
let foo = ['a', 'b', 'c', 'd']; let popped = foo.pop(); console.log(foo); // ['a', 'b', 'c', 'd'] console.log(popped); // 'd'
Array.prototype.sort()
Array.prototype.sort()
方法用于将数组对象的成员按指定顺序进行排序,并返回排序后的数组。
语法
arr.sort(compareFn);
类型声明:
interface Array<T> { sort(compareFn?: (a: T, b: T) => number): this; }
参数说明:
返回值:
返回排序后的数组对象。
在排序过程中,并不会创建新的数组对象,返回的数组对象就是经过排序后的当前数组本身。
方法说明
如果省略 compareFn
参数,元素将按 ASCII 字符顺序的升序进行排列。ASCII 字符表
如果提供了 compareFn
参数,那么该函数必须返回下列值之一:
- 如果所传递的第一个参数小于第二个参数,则返回负值。
- 如果两个参数相等,则返回零。
- 如果第一个参数大于第二个参数,则返回正值。
比较函数格式如下:
function compare(a, b) { if (a is less than b by some ordering criterion) { return -1; } if (a is greater than b by the ordering criterion) { return 1; } return 0; }
代码示例
基本用法
const foo = ['b', 'c', 'a']; fruit.sort(); // ['a', 'b', 'c'] const bar = [1, 10, 21, 2]; bar.sort(); // [1, 10, 2, 21]
注意 10 在 2 之前,因为在 Unicode 指针顺序中 "10"
在 "2"
之前。
const baz = ['word', 'Word', '1 Word', '2 Words']; baz.sort(); // ['1 Word', '2 Words', 'Word', 'word']
在 Unicode 中,数字在大写字母之前,大写字母在小写字母之前。
总结
在本篇博客中,我们一起探索了JavaScript内置对象,比如:Object、Array、全局对象、String和Funtion。JavaScript是一门非常强大且广泛应用的编程语言。掌握了这些基本的语法和概念,你已经具备了入门JavaScript编程的基础。未来,你将能够创建更加交互性的网页,实现更多惊艳的动态效果,甚至搭建出属于自己的Web应用。但这只是一个开始,还有许多更深入的主题等待你去探索。