JS数组最全方法解读!!!

数组方法一直是面试热点问题所在,博主花了一整天时间整理学习,足足13000多字,在此分享给大家,希望能给大家带来帮助,祝大家技能++,offer++

数组属性

 1、Array.prototype  - 原型

2、 Array.prototype.length - 返回或设置一个数组中的元素个数。

数组的创建方法

1. 使用Array构造函数创建 -- new可省略

let arr = new Array();
let arr = new Array(11); //知道数组长度
let arr = new Array('one','two','three'); //直接给构造函数传入要保存的元素

2.  数组字面量创建

let arr = []; //创建一个空数组
let arr = ['one','two','three']; //创建一个包含三个元素的数组
let arr = [1,2,];   //创建一个包含两个元素的数组,最后一个值后面加逗号也是一样的效果 

3.  ES6新增静态方法--from( )创建

    Array.from()第一个参数是一个类数组对象

const arr = Array.from("array") ;//["a","r","r","a","y"]字符串被拆分成单个数组

//可以使用from()将集合和映射转换为一个新数组
const m = new Map().set(1,2)
                   .set(3,4);
const s = new Set().add(1)
                   .add(2)
                   .add(3)
                   .add(4);
const arr = Array.from(m); //[[1,2],[3,4]]
const arr = Array.from(s); //[1,2,3,4]

//可以使用from()将参数对象转换成数组
function array(){
     return Array.from(arguments);
}
let arr = array(1,2,3,4);  //[1,2,3,4]


//from()可定义带有必要属性的自定义对象
const arrLikeObject = {
    0:1,
    1:2,
    2:3,
    3:4,
    length:4;
};
let arr = Array.from(arrLikeObject); //[1,2,3,4]

 可接受第二个参数---映射函数

let arr1 = [1,2,3,4];
let arr2 = Array.from(arr1,x=>x**2); //[1,4,9,16]

 可接收第三个参数---指定映射函数中的this的值

let arr = Array.from(arr1,
                     function(x){
                         return x**this.a
                     },
                     {a:2}); //[1,4,9,16]

4. ES6新增静态方法--of( )创建

  Array.of() 可以把一组参数转换为数组 ,支持任意的参数数量和类型

  可以替换Array.prototype.slice.call(arguments)方法

let arr = Array.of(1,2,3,4); //[1,2,3,4]
let arr = Array.of(undefined); //[undefined]

数组方法

1、数组索引和length

要获取和设置数组的值,需要使用中括号并提供相应值的数字索引

let arr = ["one","two","three"];
console.log(arr[0]);  //获取数组第一个元素one
arr[1] = "2"; // 修改数组第二项为"2"

 数组中元素的数量保存在length属性中,可以修改length属性从数组末尾删除或者添加元素

let arr = ["one","two","three"];
arr.length = 2;  //删除了最后一个位置的元素["one","two"];
console.log(arr[2]);  //undefined
arr.length = 3;
console.log(arr[2]);  //undefined 新添加的元素都用undefined填充
arr[arr.length]="three"; //末尾添加一个元素

2、搜索数组的方法

·indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。

·lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。

·includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false

这些方法都接收两个参数:要查找的元素和一个可选的起始搜索位置。

const arr = ['ant', 'bison', 'camel', 'duck', 'bison','ant'];

console.log(arr.indexOf('bison')); //1

console.log(arr.lastIndexOf('ant'));  //5

console.log(arr.includes('bison')); //true

·find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回undefined。

·findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。

以上两种方法接收两个参数:

1、callback断言函数,接收三个参数元素、索引和数组本身,即element当前元素。index当前元素的索引。array当前正在搜索的数组。

2、可选参数thisArg。执行callback时作为this对象的值。

用法:arr.find(callback[, thisArg])

const arr = [5, 12, 8, 130, 44];
const found = arr.find(element => element > 10);
console.log(found); //12

用法:arr.findIndex(callback[, thisArg])
const isLargeNumber = (element) => element > 13;
console.log(arr.findIndex(isLargeNumber)); //3

3、判断数组类型的方法

instanceof方法,假定只有一个全局执行上下文,如果网页里有多个框架,则可能涉及两个不同的全局执行上下文,因此就会有两个版本不同的Array构造函数

if(value instanceof Array){
   // 操作数组
}

Array.isArray()方法,目的就是确定一个值是否为数组

if(Array.isArray(value)){
     //操作数组
}

4、检索数组内容的方法--迭代器方法

·keys() 方法返回一个包含数组中每个索引键的Array Iterator对象

·values() 方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值。

·entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。Array Iterator是对象,它的原型(__proto__:Array Iterator)上有一个next方法,可用用于遍历迭代器取得原数组的 [key,value]。

注:数组迭代器是一次性的,或者说临时对象

       数组迭代器中存储的是原数组的地址,而不是数组元素值。

       数组迭代器对象方法可以使用for...of循环及next方法进行迭代

const arr = ['a', 'b', 'c'];
const arrkeys = Array.from(arr.keys()); //[0,1,2]
const arrVals = Array.from(arr.values()); //['a', 'b', 'c']
const arrEntries = Array.from(arr.entries()); //[[0,'a'],[1,'b'],[2,'c']]
cosole.log(arrEntries);
/*Array Iterator {}
         __proto__:Array Iterator
         next:ƒ next()
         Symbol(Symbol.toStringTag):"Array Iterator"
         __proto__:Object
*/

//索引迭代器中会包含没有元素的索引
var arr = ["a", , "c"];
var denseKeys = [...arr.keys()];
console.log(denseKeys);  // [0, 1, 2]

//数组迭代器对象方法可以使用for...of循环进行迭代
for (let letter of arrVals) {
  console.log(letter); 
}   //a  b  c
//使用.next()迭代
iterator.next();               // Object { value: "a", done: false }
iterator.next().value;         // "b"
iterator.next()["value"];      // "c"
iterator.next().value;         // undefined

//Array.prototype.values 是 Array.prototype[Symbol.iterator] 的默认实现。
Array.prototype.values === Array.prototype[Symbol.iterator]  // true 

5、复制和填充方法

copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。

用法:arr.copyWithin(target[, start[, end]])
/*
target:复制序列到该位置。
       如果是负数,target 将从末尾开始计算。
       如果 target 大于等于 arr.length,将不会发生拷贝。
       如果 target 在 start 之后,复制的序列将被修改以符合 arr.length。
start开始复制元素的起始位置。
       如果是负数,start 将从末尾开始计算。
       如果 start 被忽略,copyWithin 将会从 0 开始复制。
end开始复制元素的结束位置。
       copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。
       如果是负数, end 将从末尾开始计算。
       如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)。
*/
const arr = ['a', 'b', 'c', 'd', 'e'];

// 将下标为3的元素复制到0位置
console.log(arr.copyWithin(0, 3, 4));  // ["d", "b", "c", "d", "e"]

//复制arr中从0位置开始的内容,插入到索引4开始的位置
//超出边界时停止
console.log(arr.copyWithin(4)); //['d', 'b', 'c', 'd', 'd']

//复制索引为2开始的内容,插入到索引0开始的位置
console.log(arr.copyWithin(0,2)); //["c", "d", "d", "d", "d"]

//索引为负值,从末尾开始计算
const arr1 = ['a', 'b', 'c', 'd', 'e'];
console.log(arr1.copyWithin(0, -2, -1)); // ["d", "b", "c", "d", "e"]

//默认忽略超出数组范围、零长度、方向相反的索引范围
 const arr2 = ['a', 'b', 'c', 'd', 'e'];
 console.log(arr2.copyWithin(0, -12, -11)); // ["a", "b", "c", "d", "e"]
 console.log(arr2.copyWithin(0, 12, 15)); // ["a", "b", "c", "d", "e"]
 console.log(arr2.copyWithin(2, 4, 2)); // ["a", "b", "c", "d", "e"]

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

arr.fill(value[, start[, end]])
value 用来填充数组元素的值。
start 可选,起始索引,默认值为 0。
end 可选,终止索引,默认值为 this.length。

如果 start 是个负数,则开始索引会被自动计算成为 length+start, 
其中 length 是 this 对象的 length 属性值。
如果 end 是个负数,则结束索引会被自动计算成为 length+end。
const arr = [1, 2, 3, 4];

// 从索引2位置开始到索引4,用0填充 
console.log(arr.fill(0, 2, 4)); //[1,2,0,0]
//用5填充整个数组
console.log(arr.fill(5)); //[5,5,5,5]
//用6填充索引大于等于3的元素
console.log(arr.fill(6,3));  //[5,5,5,6]
//用7填充索引大于等于1且小于3的元素
console.log(arr.fill(7,1,3));  //[5,7,7,6]

//默认忽略超出数组范围、零长度、方向相反的索引范围,同copyWithin方法

6、数组转换方法

toString() 返回一个字符串,表示指定的数组及其元素。

const array1 = [1, 2, 'a', '1a'];

console.log(array1.toString());

toLocaleString() 返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。 

join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。如果缺省该值,数组元素用逗号(,)分隔

arr.toLocaleString([locales[,options]]);

const array1 = [1, 'a', new Date('21 Dec 1997 14:12:00 UTC')];
const localeString = array1.toLocaleString('en', { timeZone: 'UTC' });

console.log(localeString);  // "1,a,12/21/1997, 2:12:00 PM",

const elements = ['Fire', 'Air', 'Water'];
console.log(elements.join('-')); //Fire-Air-Water"

valueOf() 方法 返回数组本身

注:如果数组中某一项是null或undefined,则在join(),toLocalString(),toString()和valueOf()返回的结果中会以空字符串表示。

7、栈方法

数组可以像栈一样,限制插入和删除项。栈是一种后进先出(LIFO)结构,数据项的插入和删除只在栈顶发生,数组提供push()和pop()方法实现类似栈的行为。

push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。

pop() 方法从数组中删除最后一个元素,并返回该元素的值。此方法会更改数组的长度,在一个空数组上调用 pop(),它将返回 undefined。

const arr = ['pigs', 'goats', 'sheep'];

const count = arr.push('cows'); //4

console.log(arr.pop()); //'cows'

补充:数组实现栈

function Stack () {
 
    this.list = [];
    Stack.prototype.push = (item) => {
        this.list.push(item);
    }
 
    Stack.prototype.pop = () => {
        this.list.pop();
    }
 
    Stack.prototype.size = () => {
        return this.list.length;
    }
    
    Stack.prototype.isEmpty = () => {
        return this.list.length === 0;
    }
 
    Stack.prototype.peek = () => {
        return this.list[this.list.length -1];
    }
 
    Stack.prototype.toString = () => {
        let result = '';
        for ( let i of this.list) {
            result = result + i + ' ';
        }
        return result;
    }
}
 
let stack = new Stack();
 
stack.push('2222');
stack.push('33');
stack.push('1');
stack.pop();

8、队列方法

队列以先进先出(FIFO)形式访问。

shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。从数组中删除的元素; 如果数组为空则返回undefined。

unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。

const array1 = [1, 2, 3];

const firstElement = array1.shift(); //1

console.log(array1.unshift(4, 5)); //4 新数组长度

补充:数组实现队列

push()和shift()方法,还可以使用pop()和unshift()方法实现

function Queue () {
 
    this.list = [];
    //enqueue向队列尾部添加一个元素
    Queue.prototype.enqueue = (item) => {
        this.list.push(item);
    }
    //dequeue删除队首的元素
    Queue.prototype.dequeue = () => {
        this.list.shift();
    }
 
    Queue.prototype.size = () => {
        return this.list.length;
    }
    
    Queue.prototype.isEmpty = () => {
        return this.list.length === 0;
    }
    //Front读取队首的元素
    Queue.prototype.Front = () => {
        return this.list[0];
    }
    //back读取队尾的元素
    Queue.prototype.back = () => {
        return this.list[this.list.length-1];
    }
 
    Queue.prototype.toString = () => {
        let result = '';
        for ( let i of this.list) {
            result = result + i + ' ';
        }
        return result;
    }
}
 
let queue= new Queue();
 

9、排序方法

reverse() 方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。

const a = [1, 2, 3];

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

a.reverse();

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

sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的。

sort()方法可以接收一个比较函数,用于判断值的排列顺序。

//升序排列
function compare(v1,v2){
   if(v1<v2){
      return -1;
   }else if(v1>v2){
      return 1;
   }else{
      return 0;
   }
}

let arr = [0,1,5,10,15];
arr.sort();  //[0, 1, 10, 15, 5]
arr.sort(compare); //[0, 1, 5, 10, 15]

//简写
arr.sort((a,b)=> a-b);

10、操作方法

·concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2); //["a", "b", "c", "d", "e", "f"]

打平数组参数的行为可以重写,方法是在参考数组上指定一个特殊的符号:Symbol.isConcatSpreadable,这个参数可以阻止concat()打平参数数组,相反这个值为true可以强制打平类数组对象:

let arr = ["a","b","c"];
let newArr = ["d","e"];
let more = {
    [Symbol.isConcatSpreadable]:true,
    length:2,
    0:'f',
    1:'g'
};
newArr[Symbol.isConcatSpreadable] = false;
//强制不打平数组
let arr1 = arr.concat("h",newArr);  //["a", "b", "c", "h",["d","e"]]
//强制打平类数组对象
let arr2 = arr.concat(more);  //["a", "b", "c", "f", "g"]

·slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
//一个参数:返回从索引位置2开始到数组末尾的所有元素
console.log(animals.slice(2));// ["camel", "duck", "elephant"]
//两个参数:返回从开始索引2到结束索引4(不包括结束)的所有元素
console.log(animals.slice(2, 4));//["camel", "duck"]
//参数有负值:以数组长度加上这个负值确定位置
console.log(animals.slice(-2));//["duck", "elephant"]

·splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

可以以删除、插入、替换三种方式使用该方法。

使用:array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
/*
start​:指定修改的开始位置(从 0 计数)。
       如果超出了数组的长度,则从数组末尾开始添加内容;
       如果是负值,则表示从数组末位开始的第几位(从 -1 计数,这意味着 -n 是倒数第 n 个元素并且 
       等价于 array.length-n);
       如果负数的绝对值大于数组的长度,则表示开始位置为第 0 位。
deleteCount:可选,整数,表示要移除的数组元素的个数。
       如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 
       start 位)。
       如果 deleteCount 被省略了,或者它的值大于等于array.length - start
       (也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
       如果 deleteCount 是 0 或者负数,则不移除元素。
       这种情况下,至少应添加一个新元素。
item1, item2, ... 可选,要添加进数组的元素,从start 位置开始。
       如果不指定,则 splice() 将只删除数组元素。
返回值:由被删除的元素组成的一个数组
*/
var myFish = ["angel", "clown", "mandarin", "sturgeon"];
//从索引 2 的位置开始删除 0 个元素,插入“drum”
var removed = myFish.splice(2, 0, "drum");  //返回[]没有被删除的
//从索引 3 的位置开始删除 1 个元素
var removed = myFish.splice(3, 1); //["drum"]

11、迭代方法

·every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。

·filter() 方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。

·forEach() 方法对数组的每个元素执行一次给定的函数。

·map() 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。

·some() 方法测试数组中是不是至少有 1 个元素通过了被提供的函数测试。它返回的是一个 Boolean 类型的值。

用法汇总:
arr.every(callback(element[, index[, array]])[, thisArg])

var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
 // Return element for new_array 
}[, thisArg])

arr.some(callback(element[, index[, array]])[, thisArg])

/*
每个方法接收两个参数:
  callback:用来测试每个元素的函数,接受三个参数:
            element数组中正在处理的元素。
            index 可选,数组中正在处理的元素的索引值。
            array可选,some()被调用的数组。
  thisArg可选,执行 callback 时使用的 this 值。
*/
let arr = [1,2,3,4,5,4,3,2,1];

//every方法判断每一项是否符合要求
let every = arr.every((item,index,arr)=>item>2); //false

//some方法判断是否至少有一项符合要求
let some = arr.some((item,index,arr)=>item>2): //true

//filter方法返回所有值大于2的数组
let filter = arr.filter((item,index,arr)=>item>2); //[3,4,5,4,3]

//map方法也返回一个数组,这个数组的每一项都是原始数组中同样位置的元素运行传入函数返回的结果
//返回每个数组值乘以2的结果
let map = arr.map((item,index,arr)=>item*2); //[2,4,6,8,10,8,6,4,2]

//没有返回值,只对每一项运行传入的函数
arr.forEach((item,index,arr)=>{
      //执行某些操作
})

·flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。 

用法:var newArray = arr.flat([depth]) //depth默认为1

const arr1 = [0, 1, 2, [3, 4]];

console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]

const arr2 = [0, 1, 2, [[[3, 4]]]];

console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

//flat() 方法会移除数组中的空项:
var arr5 = [1, 2, , 4, 5];
arr5.flat();
// [1, 2, 4, 5]

·flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与map连着深度值为 1 的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。 

用法:
var new_array = arr.flatMap(
    function callback(currentValue[, index[, array]]) {
    // return element for new_array
}[, thisArg])
/*
参数:callback可以生成一个新数组中的元素的函数,
     可以传入三个参数:currentValue-当前正在数组中处理的元素
                     index可选,数组中正在处理的当前元素的索引。
                     array可选,被调用的 map 数组
     thisArg可选,执行 callback 函数时 使用的this 值。
*/

const arr1 = [1, 2, [3], [4, 5], 6, []];

const flattened = arr1.flatMap(num => num);  //  [1, 2, 3, 4, 5, 6]

//map vs flatMap
var arr = [1, 2, 3, 4];

arr.map(x => [x * 2]);  // [[2], [4], [6], [8]]

arr.flatMap(x => [x * 2]);  // [2, 4, 6, 8]

// only one level is flattened
arr.flatMap(x => [[x * 2]]); // [[2], [4], [6], [8]]

12、归并方法

·reduce() 方法从数组的第一项开始遍历到最后一项,对数组中的每个元素按序执行一个自己定义的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

·reduceRight() 方法从最后一项开始遍历至第一项。

这两个方法都接收两个参数:callbackFn归并函数和可选的initialValue 归并起点的初始值。

归并函数包含四个参数:

  • previousValue:上一次调用 callbackFn 时的返回值。在第一次调用时,若指定了初始值 initialValue,其值则为 initialValue,否则为数组索引为 0 的元素 array[0]
  • currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,其值则为数组索引为 0 的元素 array[0],否则为 array[1]
  • currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。
  • array:用于遍历的数组。

这个函数返回的任何值都会作为下一次调用同一函数的第一个参数。

initialValue作为第一次调用 callback 函数时参数 previousValue 的值。若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;否则 previousValue 将使用数组第一个元素,而 currentValue 将使用数组第二个元素。

const arr = [1, 2, 3, 4];

// 计算数组所有元素的总和
const initialValue = 0;
const sumWithInitial = arr.reduce(
  (previousValue, currentValue) => previousValue + currentValue,
  initialValue
); //10

//无初始值,第一次执行归并函数时pre是1,cur是2
let sum = arr.reduce((pre,cur,index,array)=>pre+cur); //10

//reduceRight()方法类似,只是方向相反
//第一次执行归并函数时,pre是4,cur是3
let sum2 = arr.reduceRight(function(pre,cur,index,array){
                            return pre+cur;
}) //10

参考:

         Array - JavaScript | MDN

      《JavaScript高级程序设计》第四版

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值