详解JavaScript的数组,JS数组方法大全

什么是数组

  • 数组是值得有序集合,每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。
  • js的数组是无类型的,数组元素可以是任意类型,同一个数组中的不同元素可能是对象或数组。
  • 数组元素的索引不一定要连续,元素之间可以有空隙,叫做稀疏数组
  • 每个数组都具有一个length属性。
  • 针对非稀疏数组,length属性就是数组元素的个数,针对稀疏数组,元素的length属性比所有元素的索引要大。

数组的方法详解

使用数组直接量创建数组,推荐使用这种方式,性能更高

var arr1 = [] 
var arr2 = [1, 3, 45]
var arr3 = [1, 'aa', true,] // 有三个不同数据类型的数组,最后一个逗号为结尾的逗号

调用构造函数Array()创建数组 不推荐使用这种方式

var a = new Array() // [] 调用时没有参数
var b = new Array(10) // 调用时有一个数值参数,它指定长度
var c = new Array(1, 2, 3) // [1, 2, 3] 显式指定两个或多个数组元素或者数组的一个非数值元素
var d = new Array('22') // ['22'] 如果传入一个非数值的参数或者参数个数大于1,则表示创建一个包含指定元素的数组

数组元素的读和写

使用[]操作符来访问数组中的一个元素

var c = [0, , 2]
console.log(c[0]) // 0 
console.log(c[1]) // undefined 
console.log(c[2]) // 2 
console.log(c[3]) // undefined
c[1] = 3
console.log(c) // [0, 3, 2]
c[5] = 6
console.log(c) // [0, 3, 2, empty × 2, 6]

数组的长度

每个数组都有一个 length 属性,针对非稀疏数组,length 属性值代表数组中元素的个数,其值比数组中最大的索引大一。当数组是稀疏时,length 属性值会大于元素个数。数组的长度会大于每一个元素的索引值。

var c = [0, , 2]
c.length // =>3 稀疏数组,最大索引值为2,数组长度为3

设置 length 属性为一个小于当前数组长度的非负整数 时,当前数组中的那些索引值大于等于 的元素将从数组中删除。同时可以将 length 属性设置为大于当前长度的值,实际不会像数组中添加元素,它只是在数组尾部创建一个空的区域。

详解JavaScript的数组,JS数组方法大全_第1张图片

数组也是对象

数组通过数字进行索引,但有趣的是它们也是对象,所以也可以包含字符串键值和属性 (但这些并不计算在数组长度内)

var a = []
a[0] = 1
a['foobar'] = 2
console.log(a) // [1, foobar: 2]
console.log(a.length) // 1
console.log(a['foobar']) // 2
console.log(a[0]) // 1
console.log(a[1]) // undefined

这里有个问题需要特别注意,如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理。

var a = []
a['13'] = 42
a.length // 14

shift

 删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 

var a = [1, 2, 3, 4, 5];
var b = a.shift(); 
// a:[2, 3, 4, 5]  b:1

unshift

将参数添加到原数组开头,并返回数组的长度

var a = [1, 2, 3, 4, 5];
var b = a.unshift(-2, -1); 
//a:[-2, -1, 1, 2, 3, 4, 5] b:7

pop

删除原数组最后一项,并返回删除元素的值;如果数组为空则返回undefined

var a = [1, 2, 3, 4, 5];
var b = a.pop();
// a:[1, 2, 3, 4] b:5

push

将参数添加到原数组末尾,并返回数组的长度

var a = [1, 2, 3, 4, 5];
var b = a.push(6, 7);
// a:[1, 2, 3, 4, 5, 6, 7] b:7

concat

将多个数组拼接成一个数组 拼接后数组的元素将按照传入参数的顺序排序 ,不改变原数组,返回拼接后的数组

var array = [1, 2];
var newArray = array.concat([3, 4], "a", true);
console.log(array); // [1, 2]
console.log(newArray); // [1, 2, 3, 4, "a", true]

splice(start, deleteCount, val1, val2, ...)

start位置开始删除deleteCount项,并从该位置起插入val1, val2,...
splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组

var a = [1, 2, 3, 4, 5];
var b = a.splice(2, 2, 7, 8, 9); //a:[1, 2, 7, 8, 9, 5] b:[3, 4]
var b = a.splice(0, 1); // 同shift
a.splice(0, 0, -2, -1); var b = a.length; // 同unshift
var b = a.splice(a.length-1, 1); // 同pop
a.splice(a.length, 0, 6, 7); var b = a.length; // 同push

reverse

将数组反序

var a = [1, 2, 3, 4, 5];
var b = a.reverse();
// a:[5, 4, 3, 2, 1] b:[5, 4, 3, 2, 1]

slice(start,end)

返回从原数组中指定开始下标到结束下标之间的项组成的新数组。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。当出现负数时,将负数加上数组长度的值来替换该位置的数(原数组中的倒数第几个元素开始提取),slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。

var a = [1, 2, 3, 4, 5];    
var b = a.slice(2, 5); 
// a:[1, 2, 3, 4, 5];  b:[3, 4, 5]

slice 方法可以用来将一个类数组(Array-like)对象/集合转换成一个新数组。你只需将该方法绑定到这个对象上。 一个函数中的arguments就是一个类数组对象的例子

function zxxFn () {
    return Array.prototype.slice.call(arguments);
}
var zxx = zxxFn(1, 2, 3); 
console.log(zxx) // [1, 2, 3]

除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用 [].slice.call(arguments) 来代替。另外,你可以使用 bind 来简化该过程。

var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
function zxxFn() {
    return slice(arguments);
}
var zxx = zxxFn(1, 2, 3); 
console.log(zxx) // [1, 2, 3]

join(separator)

 将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符 

var a = [1, 2, 3, 4, 5];
var b = a.join("|");
// a:[1, 2, 3, 4, 5] b:"1|2|3|4|5"

sort()

 按升序排列数组项——即最小的值位于最前面,最大的值排在最后面

 在排序时,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值, sort()方法比较的也是字符串,因此会出现以下的这种情况

var arr1 = ["a", "d", "c", "b"];
console.log(arr1.sort()); // ["a", "b", "c", "d"]
arr2 = [13, 24, 51, 3];
console.log(arr2.sort()); // [13, 24, 3, 51]
console.log(arr2); // [13, 24, 3, 51](元数组被改变)

为了解决上述问题,sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数。以下就是一个简单的比较函数:

function compare(value1, value2) {
    if (value1 < value2) {
        return -1;
    } else if (value1 > value2) {
        return 1;
    } else {
        return 0;
    }
}
arr2 = [13, 24, 51, 3];
console.log(arr2.sort(compare)); // [3, 13, 24, 51]

如果需要通过比较函数产生降序排序的结果,只要交换比较函数返回的值即可:

function compare(value1, value2) {
    if (value1 < value2) {
        return 1;
    } else if (value1 > value2) {
        return -1;
    } else {
        return 0;
    }
}
arr2 = [13, 24, 51, 3];
console.log(arr2.sort(compare)); // [51, 24, 13, 3]

indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。 
lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。

这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。在比较第一个参数与数组中的每一项时,会使用全等操作符。

var array = [1, 2, 3, 4, 5];
var ret = array.indexOf(4);
console.log(array); // [1, 2, 3, 4, 5]
console.log(ret); // 3
console.log(array.indexOf(6)); // -1
console.log(array.lastIndexOf(8)); // -1
console.log(array.lastIndexOf(5)); // 4

copyWithin(target,staart, end)

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

  • target:0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算。
    如果 target 大于等于 arr.length,将会不发生拷贝。如果 target 在 start 之后,复制的序列将被修改以符合 arr.length
  • start:0 为基底的索引,开始复制元素的起始位置。
    如果 start 被忽略,copyWithin 将会从0开始复制。
  • end:0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。
    如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)。
  • 如果 start 为负,则其指定的索引位置等同于 length+start,length 为数组的长度。end 也是如此。
let numbers = [1, 2, 3, 4, 5];

numbers.copyWithin(-2);
// [1, 2, 3, 1, 2]

numbers.copyWithin(0, 3);
// [4, 5, 3, 4, 5]

numbers.copyWithin(0, 3, 4);
// [4, 2, 3, 4, 5]

numbers.copyWithin(-2, -3, -1);
// [1, 2, 3, 3, 4]

[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// {0: 1, 3: 1, length: 5}

// ES2015 Typed Arrays are subclasses of Array
var i32a = new Int32Array([1, 2, 3, 4, 5]);

i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]

// On platforms that are not yet ES2015 compliant: 
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]

fill(value,start,end)

  • 用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
  • value:用来填充数组元素的值。
  • start :可选,起始索引,默认值为0。
  • end :可选,终止索引,默认值为 this.length
  • 返回值:修改后的数组
  • 如果 start 是个负数, 则开始索引会被自动计算成为 length+start, 其中 length 是 this 对象的 length 属性值。如果 end 是个负数, 则结束索引会被自动计算成为 length+end
[1, 2, 3].fill(4);               // [4, 4, 4]
[1, 2, 3].fill(4, 1);            // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3);         // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2);       // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5);         // [1, 2, 3]
Array(3).fill(4);                // [4, 4, 4]
[].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}

// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

includes(valueToFind,fromIndex) 

  • 判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。
  • valueToFind:需要查找的元素值。
  • fromIndex:可选,从fromIndex 索引处开始查找 valueToFind。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜 (即使从末尾开始往前跳 fromIndex 的绝对值个索引,然后往后搜寻)。默认为 0。
  • 如果 fromIndex 为负值,计算出的索引将作为开始搜索searchElement的位置。如果计算出的索引小于 0,则整个数组都会被搜索。
[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true

var arr = ['a', 'b', 'c'];

arr.includes('a', -100); // true
arr.includes('b', -100); // true
arr.includes('c', -100); // true
arr.includes('a', -2); // false

作为通用方法的 includes()

(function() {
  console.log([].includes.call(arguments, 'a')); // true
  console.log([].includes.call(arguments, 'd')); // false
})('a','b','c');

keys() / values() / entries()

返回一个包含数组中每个索引键的Array Iterator对象。索引迭代器会包含那些没有对应元素的索引

var arr = ["a", , "c"];
var sparseKeys = Object.keys(arr);
console.log(sparseKeys); // ['0', '2']
[...arr1.entries()] // [[0, "a"][1, undefined][2, "c"]]
[...arr1.keys()] // [0, 1, 2]
[...arr1.values()] // ["a", undefined, "c"]

filter()

  • 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 
  • 返回值:一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr2 = arr.filter(function(x, index) {
    return index % 3 === 0 || x >= 8;
}); 
console.log(arr2); //[1, 4, 7, 8, 9, 10]
var arr = [1 , 3, 4, 7, 12]
var arrTest = arr.filter((item, index, array) => {
    console.log('当前值:' + item, '当前值的索引' + index, '当前数组' + array)
    return item >= 4
})
console.log(arrTest)

 详解JavaScript的数组,JS数组方法大全_第2张图片

every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true

var arr = [1, 2, 3, 4, 5];
var arr2 = arr.every(function(x) {
    return x < 10;
}); 
console.log(arr2); //true
var arr3 = arr.every(function(x) {
    return x < 3;
}); 
console.log(arr3); // false
var arr = [1 , 3, 4, 7, 12]
var arrTest = arr.every((item, index, array) => {
    console.log('当前值:' + item, '当前值的索引' + index, '当前数组' + array)
    return item > 0
})
console.log(arrTest)

详解JavaScript的数组,JS数组方法大全_第3张图片

 some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true

var arr = [1, 2, 3, 4, 5];
var arr2 = arr.some(function(x) {
    return x < 3;
}); 
console.log(arr2); //true
var arr3 = arr.some(function(x) {
    return x < 1;
}); 
console.log(arr3); // false

Array.from()

将伪数组对象(拥有一个 length 属性和若干索引属性的任意对象)或迭代对象(可以获取对象中的元素,如 Map和 Set 等)转化成真数组,返回值:一个新的数组

Array.from(arrayLike, mapFn, thisArg)
  • arrayLike 想要转换成数组的伪数组对象或可迭代对象。
  • mapFn (可选参数) 如果指定了该参数,新数组中的每个元素会执行该回调函数。
  • thisArg (可选参数) 可选参数,执行回调函数 mapFn 时 this 对象。
Array.from('foo'); 
// ["f", "o", "o"]

=====

let s = new Set(['foo', window]); 
Array.from(s); 
// ["foo", window]

=====

let m = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(m); 
// [[1, 2], [2, 4], [4, 8]]

const mapper = new Map([['1', 'a'], ['2', 'b']]);
Array.from(mapper.values());
// ['a', 'b'];

Array.from(mapper.keys());
// ['1', '2'];

=====

function f() {
  return Array.from(arguments);
}

f(1, 2, 3); // [1, 2, 3]

=====

Array.from([1, 2, 3], x => x + x);  
// x => x + x代表这是一个函数,只是省略了其他的定义,这是一种Lambda表达式的写法
// 箭头的意思表示从当前数组中取出一个值,然后自加,并将返回的结果添加到新数组中    
// [2, 4, 6]
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]

数组去重合并

function combine(){ 
    let arr = [].concat.apply([], arguments);  //没有去重复的新数组 
    return Array.from(new Set(arr));
} 

var m = [1, 2, 2], n = [2,3,3]; 
console.log(combine(m,n));                     // [1, 2, 3]

Array.of() 

  • 创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型
  • Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为7的空数组(注意:这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)
Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(undefined); // [undefined]
Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

Array.isArray() 

用于确定传递的值是否是一个 Array。

// 下面的函数调用都返回 true
Array.isArray([]);
Array.isArray([1]);
Array.isArray(new Array());
Array.isArray(new Array('a', 'b', 'c', 'd'))
// 鲜为人知的事实:其实 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(new Uint8Array(32))
Array.isArray({ __proto__: Array.prototype });

当检测Array实例时, Array.isArray 优于 instanceof,因为Array.isArray能检测iframes.

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]

// Correctly checking for Array
Array.isArray(arr);  // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false

 

你可能感兴趣的:(javaScript,数组相关,数组,方法,es6,面试)