数组
数组常用方法
let array = Array.from({length:10}, (_, i) => i + 1)
// array.push(item) 从尾端添加元素
// 返回: 新增的元素
// 特性: 改变原数组
console.log(array.push(11))
console.log(array)
// array.unshift(item) 从首端添加元素
// 返回: 新增的元素
// 特性: 改变原数组
console.log(array.unshift(0))
console.log(array)
//array.pop() 从尾端提取元素
// 返回: 删除的尾部元素
// 特性: 改变原数组
console.log(array.pop())
console.log(array)
//array.shift() 从首端提取元素
// 返回: 删除的首步元素
// 特性: 改变原数组
console.log(array.shift())
console.log(array)
//array.splice() 增加 | 删除 | 插入
//原型 arr.splice(start[, deleteCount, elem1, ..., elemN])
//返回: 删除的元素
//特性:改变原数组
console.log(array.splice(1, 1)) //索引 1 开始删除 1 个元素
console.log(array.splice(0, 3, 'let', 'use' , 'book')) // 删除前三个元素 并增加替换
console.log(array.splice(0,0,'start')) // 从头部插入元素
console.log(array.splice(array.length, 0 , 'end')) //从尾部插入元素
console.log(array)
console.log(array.splice(0)) // 没有提供 deleteCount 参数:默认删除从起始位置到数组末尾的所有元素
console.log(array)
array = Array.from({length:10}, (_, i) => i + 1)
//array.slice()
/*
它会返回一个新数组,将所有从索引 start 到 end(不包括 end)的数组项复制到一个新的数组。
start 和 end 都可以是负数,在这种情况下,从末尾计算索引。
*/
//返回: start - end 数组 不包括end
//特性: 不改变原数组
console.log(array.slice(0,5))
console.log(array.slice(-5, -1)) //倒数第五个到倒数第一个
// array.concat()
//返回: 合并之后的数组
//特性: 不改变原数组
console.log(array.concat(11,12))
// array.forEach
// 特性: 为每一个元素执行此函数
array.forEach((item, index , array) => {
console.log(`${item} is at index ${index} in ${array}`)
})
/**
* arr.indexOf(item, from) —— 从索引 from 开始搜索 item,如果找到则返回索引,否则返回 -1。
arr.includes(item, from) —— 从索引 from 开始搜索 item,如果找到则返回 true(译注:如果没找到,则返回 false)。
*/
// arr.find
// 为每一个元素都执行方法中的函数
// 如果函数返回 true,则搜索停止,并返回 item。如果没有搜索到,则返回 undefined。
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"}
];
console.log(users.find((item, index) => item.id === 1).name)
/**
* arr.findIndex 方法(与 arr.find)具有相同的语法,但它返回找到的元素的索引,而不是元素本身。如果没找到,则返回 -1。
*
* arr.findLastIndex 方法类似于 findIndex,但从右向左搜索,类似于 lastIndexOf。
*/
//arr.filter(fn)
//特性: 如果需要匹配的有很多,我们可以使用 arr.filter(fn)。
const result = users.filter((item) => item.id < 3)
console.log(result)
// arr.map()
// 特性: 它对数组的每个元素都调用函数,并返回结果数组。
const userNameLength = users.map((item) => item.name.length)
console.log(userNameLength)
// arr.sort() 默认按字符进行排序
// 对数组进行 原位(in-place) 排序,更改原数组元素的顺序。
let array2 = [1,15,2]
array2.sort((a, b) => {
if(a > b) return 1
if(a === b) return 0
if(a < b ) return -1
})
console.log(array2)
// arr.sort(fn)中fn的排序只根据返回值的正负,所以可以极度简写
array2.sort((a, b) => b -a) // 倒排
console.log(array2)
//arr.reverse 方法用于颠倒 arr 中元素的顺序。
console.log(array2.reverse())
//str.split(delim) 它通过给定的分隔符 delim 将字符串分割成一个数组。
//特性:不改变原数组
let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');
for (let name of arr) {
console.log( `A message to ${name}.` ); // A message to Bilbo(和其他名字)
}
//若参数为空字符,则将字符串拆分为字母
const foo = 'hello-world'
console.log(foo.split(''))
//arr.join(glue) 与 split 相反。它会在它们之间创建一串由 glue 粘合的 arr 项。
const array3 = Array.from({length:10}, (_, i) => i+ 1)
console.log(array3.join(';'))数组初始化方法
// 数组字面量(最常用)
const a1 = [1, 2, 3];
// 构造器 + 参数列表
// 适合“已知元素”且代码里想显式表达“这是数组”的场合。
const a2 = new Array(1, 2, 3); // [1, 2, 3]
// 构造器 + 单数字长度
// 快速创建指定长度、元素全是 empty 的“稀疏数组”,后续可填充。
const a3 = new Array(5); // [empty × 5]
// Array.of
// ES6 新增,弥补 new Array 的“单数字歧义”问题;无论几个参数都会原样变成数组元素。
const a4 = Array.of(5); // [5] 而不是 [empty]
// Array.from
// “把任何可迭代/类数组对象转成真正的数组”——最灵活,还能顺手 map。
const a5 = Array.from({0:'a',1:'b',length:2}); // ['a','b']
const a5b = Array.from({length:3}, (_,i) => i*i); // [0,1,4]
// 展开运算符(...)
// 语法糖,本质上依赖迭代器接口;最常见的是克隆或合并。
const a6 = [...'abc']; // ['a','b','c']
const a6b = [...new Set([1,2,2,3])]; // [1,2,3]
// 静态方法 + fill
// 想一次性拿到“长度固定且元素相同”的数组时最简洁。
const a7 = new Array(4).fill(0); // [0, 0, 0, 0]
// 原型方法“借调”创建(冷门技巧)
// 借助 slice / concat 等返回新数组的特性,从空数组“借”一个实例。
const a8 = [].slice.call({0:'x',1:'y',length:2}); // ['x','y']lib.es2015.d.ts 关于数组的构造签名
interface ArrayConstructor {
/**
* 从一个类数组对象创建数组。
* @param arrayLike 要转换为数组的类数组对象。
*/
from<T>(arrayLike: ArrayLike<T>): T[];
/**
* 从一个可迭代对象创建数组。
* @param arrayLike 要转换为数组的类数组对象。
* @param mapfn 对数组每个元素调用的映射函数。
* @param thisArg 调用 mapfn 时使用的 this 值。
*/
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
/**
* 从一组元素返回新数组。
* @param items 要包含在新数组对象中的一组元素。
*/
of<T>(...items: T[]): T[];
}总结
- Array.from 负责“把别的东西变成数组”,还能顺手做映射。
- Array.of 负责“把一堆值变成数组”,写法更直观、安全。
数组进阶
/**
* 数组本质上是特殊的对象
* 如果你在元素key中给数组运算符的是一个非整型数值
* 那么它将作为一个表示数组的对象的属性创建,而不是数组的元素。
*/
const arr4 = []
arr4[5.5] = 7
console.log(arr4.length) // 0
console.log(Object.hasOwn(arr4,5.5)) //true
// 也就是说,length属性并不会更新非整型key的记录
/**
* length 属性是特殊的,如果存在最后一个元素,则其length值总是大于其索引的正整数 + 1
*/
const arr5 = [1,2,3]
arr5[100] = 4
console.log(arr5.length) // 101
/**
* length 属性赋值, 置0为清空数组
*/
const arr6 = [1,2,3,4,5]
arr6.length = 0
console.log(arr6) // []
console.log(arr6[2]) // undefined
arr6.length = 4
console.log(arr6) // [ <4 empty items> ] 确实是彻底清空了
/**
* 稀疏数组
* 数组可以包含“空槽”(empty item),这与用值 undefined 填充的槽不一样。空槽可以通过以下方式之一创建
*/
// Array 构造函数:
const a = Array(5); // [ <5 empty items> ]
// 数组字面量中的连续逗号:
const b = [1, 2, , , 5]; // [ 1, 2, <2 empty items>, 5 ]
// 直接给大于 array.length 的索引设置值以形成空槽:
const c = [1, 2];
c[4] = 5; // [ 1, 2, <2 empty items>, 5 ]
// 通过直接设置 .length 拉长一个数组:
const d = [1, 2];
d.length = 5; // [ 1, 2, <3 empty items> ]
// 删除一个元素:
const e = [1, 2, 3, 4, 5];
delete e[2]; // [ 1, 2, <1 empty item>, 4, 5 ]
/**
* 数组的遍历
*
*/
//for...of 会原样输出,这包括 empty item 和 undefined ,统一输出 undefiend
const arr7 = [1,2,3,,,4,5,6,undefined,7]
for(let arr of arr7){
console.log(arr)
}
// 使用一些数组迭代方法时,空槽(empty item)是被跳过的
// map,filter,some,Object.keys
console.log("==============")
arr7.forEach((ele) => {
console.log(ele)
})