typeScript 之 Array

工具: PlayGround

源码:GitHub TypeScript


数组简介

在TypeScript中, 使用[]表示数组, 它的结构:let valus: 类型名[] = 数据;

// 数字
let numList: number[] = [1, 2, 3];
// 字符串
let strList: string[] = ["hello", 'typeScript'];
// 任意类型
let data: any[] = [1, "hello", 3];

console.log(typeof(numList));       // "object"
console.log(typeof(strList));       // "object"
console.log(typeof(data));          // "object"

object类型前文曾说过: 它表示一个非原始类型(数字,字符串,布尔)的值,主要作用于数组,对象和函数等,它是一种泛指的类型,可以包括任意类型值。

object提供的主要接口有:

接口 返回值 描述
constructor Function 构造函数相关
toString() string 返回字符串相关
toLocaleString() string
valueOf() Object 返回指定对象的原始值
hasOwnProperty() boolean 判断对象是否具有指定名称的属性
isPrototypeOf() boolean 判断一个对象是否存在于另一个对象的原型链中
propertyIsEnumerable() boolean 判断指定的属性是否可枚举

简单的实例:

let obj = { name: "John", age: 30 };

console.log(obj.toString()); 			 // "[object Object]"
console.log(obj.toLocaleString()); // "[object Object]" 
console.log(obj.valueOf()); 			 // { name: "John", age: 30 }

console.log(obj.hasOwnProperty("name"));   // true
console.log(obj.hasOwnProperty("gender")); // false

console.log(Object.prototype.isPrototypeOf(obj)); // true
console.log(Object.prototype.isPrototypeOf({}));  // true

console.log(obj.propertyIsEnumerable("name"));     // true
console.log(obj.propertyIsEnumerable("toString")); // false

Array

数组的构建,同样支持使用Array对象进行构建, 它被称为泛型数组。 源码参考:es5.d.ts

interface ArrayConstructor {
  // 创建指定长度的数组, 返回any类型
  new(arrayLength?: number): any[];
  // 创建指定长度的数组,返回T类型
  new <T>(arrayLength: number): T[];
  // 创建包含元素的素组,返回T类型
  new <T>(...items: T[]): T[];
  isArray(arg: any): arg is any[];
  readonly prototype: any[];
}

T在TypeScript中表示泛型,方便我们编写更加通用和灵活性的代码,并使其适用于不同的类型。

简单的创建实例:

const arr_1 = new Array(3);
console.log(arr_1);     // [, , ]

const arr_2 = new Array<number>(3);
console.log(arr_2);     // [, , ]

const arr_3 = new Array(1, 2, 3);
console.log(arr_3);     // [1, 2, 3] 

// 均为"object"
console.log(typeof(arr_1), typeof(arr_2), typeof(arr_3));

数组也是支持创建多维数组的, 比如:

// 使用基础类型构建
const numList = [[0, 1, 2], [0, 1, 2]];
console.log(numList);           // [[0, 1, 2], [0, 1, 2]] 
console.log(numList.length);    // 2

// 使用Array创建
let dataList = [];
for (let i = 0; i < 2; ++i) {
    let strs = [];
    for (let j = 0; j < 3; ++j) {
        strs.push(j);
    }
    dataList.push(strs);
}
console.log(dataList);          // [[0, 1, 2], [0, 1, 2]]
console.log(dataList.length);   // 2

关于Array提供的常用接口如下:

接口 返回值 描述
length number 返回数组长度
toString() string 返回数组的字符串
toLocaleString() string 返回数组中各个元素的本地化字符串表示
push() number 数组末尾添加新元素,并返回数组的新长度
pop() T | undefined 移除数组的最后一个元素,并返回该元素
concat() T[] 合并两个或多个数组,并返回一个新的数组
join() string 将数组的所有元素连接成一个字符串,并使用指定的分隔符进行分隔
reverse() T[] 反转数组中元素的顺序
shift() T 移除数组的第一个元素,并返回该元素
unshift() number 向数组的开头添加新元素,并返回数组的新长度
slice() T[] 返回数组中指定范围的元素
sort() this 对数组中的元素进行排序
splice() T[] 从数组中移除元素,并可以在指定位置插入新元素
indexOf() number 返回指定元素在数组中第一次出现的索引
lastIndexOf() number 返回指定元素在数组中最后一次出现的索引
every() boolean 检测数组中的所有元素是否满足指定条件
some() boolean 检测数组中是否存在满足指定条件的元素
forEach() void 遍历数组中的每个元素,并执行指定的回调函数
map() U[] 遍历数组中的每个元素,并根据回调函数的返回值创建一个新数组
filter() T[] 遍历数组中的每个元素,并返回满足指定条件的元素组成的新数组
reduce() T 使用指定的回调函数对数组中的元素进行累积计算,并返回最终的累积结果
reduceRight() T 使用指定的回调函数对数组中的元素进行逆向累积计算,并返回最终的累积结果

源码相关:

interface Array<T> {
  // 返回Array数组长度
  length: number;
  // 返回字符串
  toString(): string;
  // 返回数组中各个元素的本地化字符串表示
  toLocaleString(): string;
  // 移除数组的最后一个元素,并返回该元素,
  // 如果数组为空,则返回undefined且不修改数组
  pop(): T | undefined;
  // 在数组末尾添加新元素,并返回数组的新长度
  push(...items: T[]): number;
  // 合并两个或多个数组,并返回一个新的数组,原有数组不发生改变
  concat(...items: ConcatArray<T>[]): T[];
  concat(...items: (T | ConcatArray<T>)[]): T[];
  /*
  @func: 将数组的所有元素添加到一个字符串中,用指定的分隔符字符串分隔
  @param: separator 分割符号,如果省略则使用逗号
  */
  join(separator?: string): string;
  // 反转数组,它会导致数组改变
  reverse(): T[];
  // 从数组中移除第一个元素并返回它
  // 如果数组为空,则返回undefined且不修改数组
  shift(): T | undefined;
  // 在数组的开头插入新元素,并返回新的数组长度
  unshift(...items: T[]): number;
  /*
  @func: 返回数组中指定范围的元素
  @param: start 开始位置,允许使用负数,比如-1表示倒数第一个元素
  @param: end 结束位置,元素不包括end索引处元素,如果忽略则为末尾
  */
  slice(start?: number, end?: number): T[];
  // 数组排序,如果忽略则为ASCII升序排列
  sort(compareFn?: (a: T, b: T) => number): this;
  /*
  @func: 从数组中删除元素,如果需要,在原来的位置插入新元素,并返回被删除的元素
  @param: start 开始位置,位置索引0开始
  @param: deleteCount 要删除的元素数量
  */
  splice(start: number, deleteCount?: number): T[];
  splice(start: number, deleteCount: number, ...items: T[]): T[];
  /*
  @func: 返回数组中值第一次出现的索引,如果不存在则返回-1
  @param: searchElement 要在数组中找到的值
  @param: fromIndex 开始索引,如果忽略从0开始
  */
  indexOf(searchElement: T, fromIndex?: number): number;
  /*
  @func: 返回指定值在数组中最后出现的索引,如果不存在则返回-1
  @param searchElement 要在数组中找到的值
  @param fromIndex 开始的索引,如果忽略,则从最后一个索引开始
  */
  lastIndexOf(searchElement: T, fromIndex?: number): number;
  /*
  @func: 检测数组中的所有元素是否满足指定条件
  @param predicate 最多接受三个参数的函数
  @param thisArg 可以引用的对象, 如果忽略则使用undefined作为this值
  */
  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;
  // 检测数组中是否存在满足指定条件的元素
  some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
  /*
  @func: 遍历数组中的每个元素,并执行指定的回调函数
  @param callbackfn 回调函数,最多接受三个参数
  @param thisArg 可以引用的对象, 如果忽略则使用undefined作为this值
  */
  forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
  /*
  @func: 遍历数组中的每个元素,并根据回调函数的返回值创建一个新数组
  @param callbackfn 回调函数,最多接受三个参数
  @param thisArg 可以引用的对象, 如果忽略则使用undefined作为this值
  */
  map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
  /*
  @func: 返回满足回调函数中指定条件的数组元素
  @param predicate 回调函数,最多接受三个参数
  @param thisArg 可以引用的对象, 如果忽略则使用undefined作为this值
  */
  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[];
  /*
  @func: 为数组中的所有元素调用指定的回调函数
  	回调函数的返回值是累积的结果,并在下次调用回调函数时作为参数提供
  @param: callbackfn 一个最多接受四个参数的回调函数
  */
  reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;
  reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
  reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
  // 使用指定的回调函数对数组中的元素进行逆向累积计算,并返回最终的累积结果
  reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;
  reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
  reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;

  [n: number]: T;
}

基本使用:

let dataList:number[] = []
// 插入数值
dataList.push(1);
console.log(dataList);          // [1] 

// 删除数值 
const value = dataList.pop();
console.log(value, dataList);   // 1,  [] 
// 数组已经为空,如果再删除则返回undefined
console.log(dataList.pop());    // undefined 

针对于删除可做下拓展,比如删除重复数值:

// 方法1: 使用push相关增加新数组
let arr: number[] = [1, 2, 2, 3, 4, 4, 5, 5];
let uniqueArr: number[] = [];
for (let i = 0; i < arr.length; i++) {
  if (uniqueArr.indexOf(arr[i]) === -1) {
    uniqueArr.push(arr[i]);
  }
}
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]

// 方法2:使用filter方法进行遍历获取新的数组
let arr: number[] = [1, 2, 2, 3, 4, 4, 5, 5];
let uniqueArr: number[] = arr.filter((value, index, self) => {
    return self.indexOf(value) === index;
});
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]

// 方法3: 使用reduce方法
let arr: number[] = [1, 2, 2, 3, 4, 4, 5, 5];
let uniqueArr: number[] = arr.reduce((prev, curr) => {
    if (!prev.includes(curr)) {
        prev.push(curr);
    }
    return prev;
}, []);
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]

如果要移除或插入特定的元素相关也可以考虑unshiftshift相关:

// 使用Array对象
let arrObj = new Array();
console.log(arrObj);            // []

// 使用 unshift 在数组开头插入元素, 并返回长度
arrObj.unshift(1);
arrObj.unshift(2);
let len = arrObj.unshift(0);
console.log(len, arrObj);       // 3,  [0, 2, 1] 

// 使用shift移除首位置元素,并返回删除元素
let newLen = arrObj.shift();
console.log(newLen, arrObj);    // 0,  [2, 1] 

数组的遍历,如果需要有回调方法的支持,可以使用forEach

const numList = [1, 2, 3]
numList.forEach((value, index, array) => {
    if (value % 2 === 0) {
        console.log(`索引是:${index} 为偶数`);	// "索引是:1 为偶数" 
    }
    console.log("数据是" + array.join("#"));		// "数据是1#2#3" 
});

数组是支持排序的,可以使用sort

const numList: number[] = [1,3,2,5,4];
// 默认为升序
numList.sort(); 
console.log(numList);       // [1, 2, 3, 4, 5]    

// 使用比较函数排序
numList.sort((a, b) => b - a);
console.log(numList);       // [5, 4, 3, 2, 1] 

// 元素反转
numList.reverse()
console.log(numList);       // [1, 2, 3, 4, 5] 

获取数组中某个元素

获取数组中的元素可以通过索引来简单获取

const arr_1 = [1, 2, 3, 4];
const arr_2 = [[1, 2, 3], [4, 5,6]];
console.log(arr_1[0], arr_2[1][0]);     // 1, 4
// 如果索引错误,则返回undefined
console.log(arr_1[5], arr_2[1][10]);    // undefined,  undefined 

也可以使用indexOflastIndexOf相关查找元素的索引位置相关

const arrObj = new Array<number>(1, 2, 2, 3);

// indexOf 查找元素首次出现的位置
const firstIndex = arrObj.indexOf(2);
console.log(firstIndex);            // 1

// lastIndexOf 查找元素最后出现的位置
const lastIndex = arrObj.lastIndexOf(2);
console.log(lastIndex);             // 2

// 如果查找不到,返回-1
console.log(arrObj.indexOf(0), arrObj.indexOf(0));

合并数组

可以使用contact方法

const arr_1 = [1,2,3,4,5];
const arr_2 = [1,2,3,6,7];
// 使用concat合并数组, 原有数组不会发生改变
let newArr_1 = arr_1.concat(arr_2);
console.log(arr_1, arr_2);  // [1, 2, 3, 4, 5],  [1, 2, 3, 6, 7] 
console.log(newArr_1);      // [1, 2, 3, 4, 5, 1, 2, 3, 6, 7] 

拓展下,如果想剔除重复元素,可以考虑filter

let arr1: number[] = [1, 2, 3];
let arr2: number[] = [2, 3, 4];

let mergedArr: number[] = [...arr1, ...arr2].filter((value, index, self) => {
  return self.indexOf(value) === index;
});

console.log(mergedArr);     // [1, 2, 3, 4] 

再进行拓展下,使用最笨的循环方法实现:

let arr1: number[] = [1, 2, 3];
let arr2: number[] = [2, 3, 4];

// 获取排序的合并数组
function getMergeArr(originArr: any, destArr: any) {
    if (originArr.length <= 0) {
        return console.error("originArr is nil");
    }
    if (destArr.length <= 0) {
        return console.error("originArr is nil");
    }

    let mergeArr: any = [];
    // 遍历originArr
    for (let i = 0; i < originArr.length; ++i) {
        if (!mergeArr.includes(originArr[i])) {
            mergeArr.push(originArr[i]);
        }
    }
    // 遍历destArr
    for (let i = 0; i < destArr.length; ++i) {
        if (!mergeArr.includes(destArr[i])) {
            mergeArr.push(destArr[i]);
        }
    }
    return mergeArr;
}
console.log(getMergeArr(arr1, arr2));       // [1, 2, 3, 4] 

includes方法来源于Array对象 ES2016中, 它主要用于判定数组中是否包含指定元素。

// es2016.array.include.d.ts
interface Array<T> {
    includes(searchElement: T, fromIndex?: number): boolean;
}

其他

  • map 遍历数组中的每个元素,并根据回调函数的返回值创建一个新数组
let arr: number[] = [1, 2, 3, 4, 5];

let doubledArr: number[] = arr.map((value, index, array) => {
  return value * 2;
});

console.log(doubledArr); // [2, 4, 6, 8, 10]

你可能感兴趣的:(typeScript,typescript,前端)