JavaScript数组

JavaScript数组

数组(Array)是属于内置对象,数组和普通对象的功能类似,都可以用来存储一些值。不同的是:

  • 普通对象是使用字符串作为属性名,而数组是使用数字作为索引来操作元素。索引:从 0 开始的整数就是索引。

数组的存储性能比普通对象要好。在实际开发中我们经常使用数组存储一些数据(尤其是列表数据),使用频率非常高。

数组创建

在js中有一下几种方式创建数组

使用字面量创建数组

let arr1 = []; // 创建一个空的数组
let arr2 = [1, 2, 3]; // 创建带初始值的数组

使用构造函数创建数组

let arr = new Array(参数);
let arr = Array(参数);

如果参数为空,表示创建一个空数组;如果参数是一个数值,表示数组的长度;如果有多个参数,表示数组中的元素内容。

let arr1 = [1,2,3]
let arr2 = new Array()
let arr3 = new Array(5)
let arr4 = new Array(1,"hello",{"name":'tom', 'age':12},[3,6])

console.log('arr1 = ' + JSON.stringify(arr1)); // arr1 = [1,2,3]
console.log('arr2 = ' + JSON.stringify(arr2)); // arr2 = []
console.log('arr3 = ' + JSON.stringify(arr3)); // arr3 = [null,null,null,null,null]
console.log('arr4 = ' + JSON.stringify(arr4)); // arr4 = [1,"hello",{"name":"tom","age":12},[3,6]]

以上例子我们可以看出数组中可以存放任意类型的数据,例如字符串、数字、布尔值、对象等。

数组的操作

索引 (下标) :用来访问数组元素的序号,代表的是数组中的元素在数组中的位置(下标从 0 开始算起)。

添加元素

let arr1 = new Array(5)
arr1[1]= 100
arr1[3] = 0
arr1[6] = 2
console.log('arr1 = ' + JSON.stringify(arr1)); // arr1 = [null,100,null,0,null,null,2]

当下标查过定义数组的长度时候, 会把数组的长度扩充

获取元素

如果读取不存在的索引(比如元素没那么多),系统不会报错,而是返回 undefined。

代码举例:

const arr = [21, 22, 23];

console.log(arr[0]); // 打印结果:21
console.log(arr[5]); // 打印结果:undefined

数组长度

可以使用length属性来获取数组的长度(即“元素的个数”)。

数组的长度是元素个数,不要跟索引号混淆。

语法:

数组的长度 = 数组名.length;

代码举例:

const arr = [21, 22, 23];

console.log(arr.length); // 打印结果:3

补充:

对于连续的数组,使用 length 可以获取到数组的长度(元素的个数);对于非连续的数组(即“稀疏数组”,本文稍后会讲),length 的值会大于元素的个数。因此,尽量不要创建非连续的数组。

修改数组长度

可以通过修改length属性修改数组的长度。

  • 如果修改的 length 大于原长度,则多出部分会空出来,置为 null。
  • 如果修改的 length 小于原长度,则多出的元素会被删除,数组将从后面删除元素。
  • (特例:伪数组 arguments 的长度可以修改,但是不能修改里面的元素,以后单独讲。)
const arr1 = [11, 12, 13];
const arr2 = [21, 22, 23];

// 修改数组 arr1 的 length
arr1.length = 1;
console.log(JSON.stringify(arr1)); // [11]

// 修改数组 arr2 的 length
arr2.length = 5;
console.log(JSON.stringify(arr2)); // [21, 22, 23, null, null]

遍历数组

就是把数组中的每个元素从头到尾都访问一次。最简单的做法是通过 for 循环,遍历数组中的每一项。

let arr1 = [1,"dany",12,{"name":"tom","age":12},[33,44]]
for (let index = 0; index < arr1.length; index++) {
    console.log(arr1[index]);
    
}

和其他编程语言相比,JS语言中的数组比较灵活,有许多与众不同的地方。

1、如果访问数组中不存在的索引时,不会报错,会返回undefined。

2、当数组的存储空间不够时,数组会自动扩容。其它编程语言中数组的大小是固定的,不会自动扩容。

3、数组可以存储不同类型数据,其它编程语言中数组只能存储相同类型数据。

4、数组分配的存储空间不一定是连续的。其它语言数组分配的存储空间是连续的。

JS中的数组采用"哈希映射"的方式分配存储空间,我们可以通过索引找到对应空间。各大浏览器也对数组分配的存储空间进行了优化:如果存储的都是相同类型的数据,则会尽量分配连续的存储空间;如果存储的不是相同的数据类型,则不会分配连续的存储空间。

数组解构

解构赋值是ES6中新增的一种赋值方式。

ES5中,如果想把数组中的元素赋值给其他变量,是这样做的:

const arr = [1, 2, [3,4]];
let a = arr[0]; // 1
let b = arr[1]; // 2
let c = arr[2]; // [3, 4]

//我们也可以按照如下方式
let [a, b, c] = [1, 2, [3, 4]];
console.log(a); // 1
console.log(b); // 2
console.log(c); // [3, 4]

注意点:

(1)等号左边的个数和格式,必须和右边的一模一样,才能完全解构。

(2)当然,左边的个数和右边的个数,可以不一样。

解构时,我们也可以给出默认值

let [a, b = 3, c = 4] = [1, 2];
console.log(a); // 1
console.log(b); // 2。默认值被覆盖。
console.log(c); // 4。继续保持默认值。

我们可以使用ES6中新增的扩展运算符打包剩余的数据。如果使用了扩展运算符, 那么扩展运算符只能写在最后。代码举例:

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

数组的方法

数组类型判断

方法描述备注
Array.isArray()判断是否为数组
toString()将数组转换为字符串不会改变原数组
join()将数组转换为字符串,返回结果为转换后的字符串不会改变原数组
字符串的方法:split()将字符串按照指定的分隔符,组装为数组不会改变原字符串
Array.from(arrayLike)伪数组转化为真数组
Array.of(value1, value2, value3)创建数组:将一系列值转换成数组

注意:

(1)获取数组的长度是用length属性,不是方法。关于 length属性,详见上一篇文章。

(2)split()是字符串的方法,不是数组的方法。

isArray() 判断是否为数组
toString()
join()
arr1 = [1,"tom",{"name":"jack","age":12},[22,55]]
console.log(Array.isArray(arr1)) //true 判断是否为数组
console.log(arr1.toString())  // 1,tom,[object Object],22,55 数组转为字符串 也可以用String(arr1)方法
//将数组转换为字符串,返回结果为转换后的字符串(不会改变原来的数组)。 join()方法可以指定一个字符串作为参数,这个参数是元素之间的连接符;如果不指定连接符,则默认使用英文逗号, 作为连接符,此时和 toString()的效果是一致的。
console.log(arr1.join(","))   // 1,tom,[object Object],22,55

伪数组是包含 length 属性的对象或可迭代的对象。伪数组的原型链中没有 Array.prototype,而真数组的原型链中有 Array.prototype。因此伪数组没有数组的一般方法,比如 pop()、join() 等方法。例如我们经常通过DOM获取页面上具有相同属性的一系列元素, 此时得到的数据就是伪数组,我们可以通过

array = Array.from(arrayLike);

伪数组或可遍历对象转换为真数组

数组元素添加与删除

方法描述备注
push()向数组的最后面插入一个或多个元素,返回结果为新数组的长度会改变原数组
pop()删除数组中的最后一个元素,返回结果为被删除的元素会改变原数组
unshift()在数组最前面插入一个或多个元素,返回结果为新数组的长度会改变原数组
shift()删除数组中的第一个元素,返回结果为被删除的元素会改变原数组
splice()从数组中删除指定的一个或多个元素,返回结果为被删除元素组成的新数组会改变原数组
concat()合并数组:连接两个或多个数组,返回结果为新的数组不会改变原数组
fill()填充数组:用固定的值填充数组,返回结果为新的数组会改变原数组
push()

push():向数组的最后面插入一个或多个元素,返回结果为新数组的长度。会改变原数组,因为原数组变成了新数组

pop()

pop():删除数组中的最后一个元素,返回结果为被删除的元素

unshift()

在数组最前面插入一个或多个元素,返回结果为新数组的长度。会改变原数组,将原数组变成了新数组。插入元素后,其他元素的索引会依次调整。

shift()

shift():删除数组中的第一个元素,返回结果为被删除的元素。

arr1 = [1,"tom",{"name":"jack","age":12},[22,55]]
console.log(arr1.push(100)) // 5
console.log(arr1)  //[ 1, 'tom', { name: 'jack', age: 12 }, [ 22, 55 ], 100 ]
// pop():删除数组中的最后一个元素,返回结果为被删除的元素
console.log(arr1.pop()) // 100
console.log(arr1)  // [ 1, 'tom', { name: 'jack', age: 12 }, [ 22, 55 ] ]
//unshift():在数组最前面插入一个或多个元素,返回结果为新数组的长度。会改变原数组,将原数组变成了新数组。插入元素后,其他元素的索引会依次调整。
console.log(arr1.unshift(23,[34,56]))  // 6
console.log(arr1)   // [ 23, [ 34, 56 ], 1, 'tom', { name: 'jack', age: 12 }, [ 22, 55 ] ]
//shift():删除数组中的第一个元素,返回结果为被删除的元素。
console.log(arr1.shift() ) // 23
console.log(arr1)  // [ [ 34, 56 ], 1, 'tom', { name: 'jack', age: 12 }, [ 22, 55 ] ]

splice()

splice():从数组中删除指定的一个或多个元素,返回结果为被删除元素组成的新数组(会改变原来的数组)。该方法会改变原数组,会将指定元素从原数组中删除;被删除的元素会封装到一个新的数组中返回。

新数组 = 原数组.splice(起始索引index);
新数组 = 原数组.splice(起始索引index, 需要删除的个数);
新数组 = 原数组.splice(起始索引index, 需要删除的个数, 新的元素1, 新的元素2...);
上方语法中,第三个及之后的参数,表示:删除元素之后,向原数组中添加新的元素,这些元素将会自动插入到起始位置索引的前面。也可以理解成:删除了哪些元素,就在那些元素的所在位置补充新的内容。slice()方法和splice()方法很容易搞混,请一定要注意区分。
arr1 = [1,"tom",{"name":"jack","age":12},[22,55]]

var res = arr1.splice(1)
console.log(arr1)  // [1]
console.log(res)  //[ 'tom', { name: 'jack', age: 12 }, [ 22, 55 ] ]


arr1 = [1,"tom",{"name":"jack","age":12},[22,55]]

var res = arr1.splice(1,2) // //从第index为1的位置开始删除元素,一共删除三个元素
console.log(arr1)  // [ 1, [ 22, 55 ] ]
console.log(res)  // [ 'tom', { name: 'jack', age: 12 } ]


arr1 = [1,"tom",{"name":"jack","age":12},[22,55]]

var res = arr1.splice(1,2, "replase","replace","replace")
console.log(arr1)  // [ 1, 'replase', 'replace', 'replace', [ 22, 55 ] ]
console.log(res)  // [ 'tom', { name: 'jack', age: 12 } ]
concat()

concat():连接两个或多个数组,返回结果为新的数组。不会改变原数组。concat()方法的作用是数组合并

    新数组 = 数组1.concat(数组2, 数组3 ...);
    //我们可以使用...这种扩展运算符,将两个数组进行合并
    const arr1 = [1, 2, 3];
	const result = ['a', 'b', 'c', ...arr1];
slice()

slice():从数组中提取指定的一个或者多个元素,返回结果为新的数组(不会改变原来的数组)。

备注:该方法不会改变原数组,而是将截取到的元素封装到一个新数组中返回。

新数组 = 原数组.slice(开始位置的索引);
新数组 = 原数组.slice(开始位置的索引, 结束位置的索引);  //注意:提取的元素中,包含开始位置,不包含结束位置
fill()

fill():用一个固定值填充数组,返回结果为新的数组。会改变原数组。

// 用一个固定值填充数组。数组里的每个元素都会被这个固定值填充
新数组 = 数组.fill(固定值);

// 从 startIndex 开始的数组元素,用固定值填充
新数组 = 数组.fill(固定值, startIndex);

// 从 startIndex 到 endIndex 之间的元素(包左不包右),用固定值填充
新数组 = 数组.fill(固定值, startIndex, endIndex);

数组排序

方法描述备注
reverse()反转数组,返回结果为反转后的数组会改变原数组
sort()对数组的元素,默认按照Unicode 编码,从小到大进行排序会改变原数组
reverse()

reverse():反转数组,返回结果为反转后的数组(会改变原来的数组)。

var arr1 = [1,3,2,5,6]
arr1.reverse()
console.log(arr1) //  [ 6, 5, 2, 3, 1 ]
sort()

sort():对数组的元素进行从小到大来排序(会改变原来的数组)。

var arr1 = [1,3,12,5,6]
arr1.sort()
console.log(arr1) //  [ 1, 12, 3, 5, 6 ]

上述排序大家肯定有疑惑, 为什么12 排在3的前面,这是因为sort()方法是按照Unicode 编码进行排序的。要想让数组里面的数据按照我们想的排序 我们需要在sort里面定义参数

如果在 sort()方法中带参,我们就可以自定义排序规则。具体做法如下:

我们可以在 sort()的参数中添加一个回调函数,来指定排序规则。回调函数中需要定义两个形参,JS将会分别使用数组中的元素作为实参去调用回调函数。

JS根据回调函数的返回值来决定元素的排序:(重要)

  • 如果返回一个大于 0 的值,则元素会交换位置
  • 如果返回一个小于 0 的值,则不交换位置
  • 如果返回一个等于 0 的值,则认为两个元素相等,则不交换位置
var arr1 = [1,3,12,5,6]
arr1.sort(function (a, b) {
    return a - b;
    
})
console.log(arr1) //  [ 1, 3, 5, 6, 12 ]
//跟简单写法
arr.sort((a, b) => a - b);

下面看一个复杂的例子

var arr1 = [{'age':2,'score':34},{'age':12,'score':24},{'age':5,'score':63},{'age':21,'score':87}]
arr1.sort(function (a, b) {
    return a.age - b.age;
    
})
console.log(arr1) 
// [
//     { age: 2, score: 34 },
//     { age: 5, score: 63 },
//     { age: 12, score: 24 },
//     { age: 21, score: 87 }
//   ]

查找元素

方法描述备注
indexOf(value)从前往后索引,检索一个数组中是否含有指定的元素
lastIndexOf(value)从后往前索引,检索一个数组中是否含有指定的元素
includes(item)数组中是否包含指定的内容
find(function())找出第一个满足「指定条件返回 true」的元素
findIndex(function())找出第一个满足「指定条件返回 true」的元素的 index
every()确保数组中的每个元素都满足「指定条件返回 true」,则停止遍历,此方法才返回 true全真才为真。要求每一项都返回 true,最终的结果才返回 true
some()数组中只要有一个元素满足「指定条件返回 true」,则停止遍历,此方法就返回 true一真即真。只要有一项返回 true,最终的结果就返回 true
indexOf()/lastIndexOf():获取元素的索引
索引值 = 数组.indexOf(想要查找的元素, [查找的起始位置]);

元素的索引 = 数组.lastIndexOf(想要查询的元素);

indexOf() 是从左往右查找元素的位置。同理,lastIndexOf()是从右往左寻找。

解释:可以检索一个数组中是否含有指定的元素。如果数组中含有该元素,则会返回其第一次出现的索引,并立即停止查找;如果没有找到指定的内容,则返回 -1。

这个方法的作用:

  • 如果找到了指定的元素,就返回元素对应的位置。
  • 如果没有找到指定的元素,就会返回-1。
includes()

判断一个数组中是否包含指定的元素。如果是,则会返回 true;否则返回 false。

布尔值 = arr.includes(想要查找的元素, [position]);

参数中的 position:如果不指定,则默认为0;如果指定,则规定了检索的起始位置。

find()

找出第一个满足「指定条件返回 true」的元素,并立即停止查找;如果没找到,则返回 undefined。

备注:一旦找到符合条件的第一个元素,将不再继续往下遍历。

const itemResult = arr.find((currentItem, currentIndex, currentArray) => {
    return true;
});
var arr1 = [23,"tom",{"name":"jack",'age':12},[23,56], '22']
var res = arr1.find((item, index)=>{
    if (typeof(item) == 'object') { //找到是对象的元素打印出来
        console.log(item)  
    }
    
});

// { name: 'jack', age: 12 }
// [ 23, 56 ]
findIndex()

找出第一个满足「指定条件返回 true」的元素的索引,并立即停止遍历;如果没找到,则返回 -1。

const indexResult = arr.findIndex((currentItem, currentIndex, currentArray) => {
    return true;
});
var arr1 = [23,"tom",{"name":"jack",'age':12},[23,56], '22']
var res = arr1.findIndex((item, index)=>{
    if (typeof(item) == 'object') {
        return 1; 
    }
    
});
console.log(res) // 2
every()

对数组中每一项运行回调函数,如果都返回 true,every 就返回 true;如果有一项返回 false,则停止遍历,此方法返回 false。

注意:every()方法的返回值是 boolean 值,参数是回调函数。

const boolResult = arr.every((currentItem, currentIndex, currentArray) => {
    return true;
});
some()

对数组中每一个元素运行回调函数,只要有一个元素返回 true,则停止遍历,此方法返回 true。

注意:some()方法的返回值是 boolean 值。

var arr1 = [23,"tom",{"name":"jack",'age':12},[23,56], '22']
var res = arr1.every((item, index)=>{
    if (item.length >2) {
        return 0; 
    }
    return 1;
    
});
console.log(res) // false
var arr1 = [23,"tom",{"name":"jack",'age':12},[23,56], '22']
var res = arr1.some((item, index)=>{
    if (item.length >2) {
        return 0; 
    }
    return 1;
    
});
console.log(res) // true

every() 和 some() 这两个方法,初学者很容易搞混。要怎么区分呢?你可以这样记:

  • every():全部真,才为真。当你需要让数组中的每一个元素都满足指定条件时,那就使用 every()。
  • some():一个真,则为真,点到为止。数组中只要有一个元素满足指定条件时,就停止遍历。那就使用 some()。

遍历数组

方法描述备注
for 循环最传统的方式遍历数组,这个大家都懂
forEach()遍历数组,但需要兼容 IE8 以上不会改变原数组。forEach() 没有返回值。也就是说,它的返回值是 undefined
for of遍历数组(ES6语法)不会改变原数组。另外,不要使用 for in 遍历数组
map()对原数组中的每一项进行加工,将组成新的数组不会改变原数组
filter()过滤数组:返回结果是 true 的项,将组成新的数组,返回结果为新的数组不会改变原数组
reduce接收一个函数作为累加器,返回值是回调函数累计处理的结果比较复杂

获取并操作数组中的每一个元素,然后得到想要的返回结果。在实战开发中使用得非常频繁。

for循环遍历
var arr1 = [23,"tom",{"name":"jack",'age':12},[23,56], '22']
for (let index = 0; index < arr1.length; index++) {
    const element = arr1[index];
    console.log(element)
    
}
forEach遍历
// ES5语法
arr.forEach(function (currentItem, currentIndex, currentArray) {
	console.log(currentValue);
});

// ES6语法
arr.forEach((currentItem, currentIndex, currentArray) => {
	console.log(currentValue);
});

forEach()方法需要一个函数作为参数。这种函数,是由我们创建但是不由我们调用的,我们称为回调函数。

数组中有几个元素,该回调函数就会执行几次。

回调函数中传递三个参数:

  • 参数1:当前正在遍历的元素
  • 参数2:当前正在遍历的元素的索引
  • 参数3:正在遍历的数组

注意,forEach() 没有返回值。也可以理解成:forEach() 的返回值是 undefined。如果你尝试 newArray = currentArray.forEach()这种方式来接收,是达不到效果的。

var arr1 = [23,"tom",{"name":"jack",'age':12},[23,56], '22']
arr1.forEach((item,index)=> {
    console.log(item)
})
for of 遍历
for(let value of arr) {
	console.log(value);
}
map()
// ES5语法
const newArr =  arr.map(function (currentItem, currentIndex, currentArray) {
    return newItem;
});

// ES6语法
const newArr = arr.map((currentItem, currentIndex, currentArray) => {
    return newItem;
});

对数组中每一项运行回调函数,返回该函数的结果,组成的新数组(返回的是加工后的新数组)。不会改变原数组。作用:对数组中的每一项进行加工。

const arr1 = [1, 3, 6, 2, 5, 6];
const arr2 = arr1.map(item => {
  return item + 10; //让arr1中的每个元素加10
});
console.log(arr2); // 数组 arr2 的值:[11, 13, 16, 12, 15, 16]
filter()
const newArr = arr.filter((currentItem, currentIndex, currentArray) => {
    return true;
});

对数组中的每一项运行回调函数,该函数返回结果是 true 的项,将组成新的数组(返回值就是这个新数组)。不会改变原数组。作用:对数组进行过滤。

let arr1 = [1, 3, 6, 2, 5, 6];

let arr2 = arr1.filter(item => {
    if (item > 4) {
        return true; // 将arr1中大于4的元素返回,组成新的数组
    }
    return false;
});

console.log(JSON.stringify(arr1)); // 打印结果:[1,3,6,2,5,6]
console.log(JSON.stringify(arr2)); // 打印结果:[6,5,6]
reduce()

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。返回值是回调函数累计处理的结果。

语法

arr.reduce(function (previousValue, currentValue, currentIndex, arr) {}, initialValue);

参数解释:

  • previousValue:必填,上一次调用回调函数时的返回值
  • currentValue:必填,当前正在处理的数组元素
  • currentIndex:选填,当前正在处理的数组元素下标
  • arr:选填,调用 reduce()方法的数组
  • initialValue:选填,可选的初始值(作为第一次调用回调函数时传给 previousValue 的值)

在以往的数组方法中,匿名的回调函数里是传三个参数:item、index、arr。但是在 reduce() 方法中,前面多传了一个参数previousValue,这个参数的意思是上一次调用回调函数时的返回值。第一次执行回调函数时,previousValue 没有值怎么办?可以用 initialValue 参数传给它。

备注:绝大多数人在一开始接触 reduce() 的时候会很懵逼,但是没关系,有事没事多看几遍,自然就掌握了。如果能熟练使用 reduce() 的用法,将能替代很多其他的数组方法,并逐渐走上进阶之路,领先于他人。

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

arr1.reduce((prev, item) => {
    console.log(prev);
    console.log(item);
    console.log('------');
    return 88;
}, 0);

打印结果:

0
1
------
88
2
------
88
3
------
88
4
------
88
5
------
88
6
------

上面的代码中,由于return的是固定值,所以 prev 打印的也是固定值(只有初始值是 0,剩下的遍历中,都是打印 88)。

现在来升级一下,实际开发中,prev 的值往往是动态变化的,这便是 reduce()的精妙之处。我们来看几个例子就明白了。

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值