数组

10 小时前
/ ,
1

数组

数组常用方法

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)
})

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...