JavaScript-Array数据类型学习

JavaScript-Array数据类型学习

上一篇我们学习了JavaScript的对象数据类型,对象是一组键-值对,很多时候我们需要一组连续的数据集合,比如从后台获取博客列表,这个时候存储这个列表用数组是最合适的。

数组在JavaScript中是很常用的数据类型,数组有很多操作方法,包括添加删除,查找索引,排序,遍历等等,掌握了这些方法,才能玩转数组,本篇我们来一起学一学JavaScript中的Array数据类型及一些常用的数组方法。

创建数组

中括号语法

const skills = [];//定义一个空数组
skills[0] = 'html';//添加元素
skills[1] = 'css';//添加元素
skills[2] = 'javascript';//添加元素

也可以在定义时就初始化一些元素:

const skills = ['html', 'css', 'javascript'];

当我们定义一个数组,JavaScript引擎会在内存中分配一段连续的内存空间,因此数组元素是按顺序存储的,这样我们访问数组元素就可以通过索引来访问,索引从0开始

console.log(skills[0], skills[1], skills[2]);//html css javascript

给数组添加一个元素也很简单:

skills[3] = 'jquery';

修改数组元素:

skills[3] = 'lodash';

查看数组大小

skills.length;//4

new Array()

通过Array构造函数来创建:

const skills = new Array();//定义一个空数组
skills[0] = 'html';//添加元素
skills[1] = 'css';//添加元素
skills[2] = 'javascript';//添加元素

skills[3] = 'jquery';//添加元素

skills[3] = 'lodash';//修改元素

console.log(skills.length);//4
console.log(skills);//['html', 'css', 'javascript', 'lodash']

Array()构造函数可以接收参数

const skills = new Array(3); //定义一个长度为3的数组
console.log(skills.length);//3

如果构造函数的参数大于1个,那么相当于是创建了一个以这些参数为元素的数组

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

数组方法

添加删除元素

上面我们通过索引的方式添加元素,其实JavaScript有内置的数组方法供我们在头/尾直接添加/取出元素:

push()

在数组末尾添加元素

const skills = [];
skills.push('html');
skills.push('css');
skills.push('javascript');
console.log(skills);//['html', 'css', 'javascript']

pop()

取数组末尾元素

console.log(skills.pop());//javascript
console.log(skills.pop());//css
console.log(skills.pop());//html
console.log(skills);//[],数组元素已经全部取走,现在是空数组

unshift和shift

这组方法和push/pop相反,unshift/shift是在数组首位添加/删除元素

const skills = [];

skills.unshift('html');
skills.unshift('css');
skills.unshift('javascript');

console.log(skills);//['javascript', 'css', 'html']

console.log(skills.shift());//javascript
console.log(skills.shift());//css
console.log(skills.shift());//html

console.log(skills);//[],数组元素已经全部取走,现在是空数组

注意这里数组元素添加/删除的顺序

数组的拷贝

Object一样,数组也是引用类型,将一个数组赋值给另一个变量,二者引用的是同一个地址

const skills = ['html', 'css', 'javascript'];

const myskills = skills;
myskills[2] = 'jquery';//修改myskills的元素

console.log(skills);//[ 'html', 'css', 'jquery' ]
console.log(myskills);//[ 'html', 'css', 'jquery' ]

可以看到,二者是相互影响的,下面看看数组的拷贝方法

slice

slice():将一个数组拷贝至另一个数组

const skills = ['html', 'css', 'javascript'];
const myskills = skills.slice();
myskills[2] = 'jquery';
console.log(skills);//[ 'html', 'css', 'javascript' ]
console.log(myskills);//[ 'html', 'css', 'jquery' ]

可以看到此时skillsmyskills数组相互独立

slice可以添加参数,拷贝部分数组元素

slice(start, end):注意这里拷贝时不包含end,即拷贝从start至(end - 1)的元素

const skills = ['html', 'css', 'javascript'];
const myskills = skills.slice(0, 2);//拷贝索引0-1的元素
console.log(skills);//[ 'html', 'css', 'javascript' ]
console.log(myskills);//[ 'html', 'css']

slice(start):拷贝从start开始至数组最后的所有元素

startend都可以为负数,数组最后一个元素索引为-1

const skills = ['html', 'css', 'javascript'];
const myskills = skills.slice(-3);//拷贝-3至-1位的元素,第一位索引就是-3,相当于拷贝了整个数组
console.log(myskills);//[ 'html', 'css', 'javascript' ]

splice

咋一看和slice有点相像,但这个方法用起来比slice要复杂,功能很强大,接收的参数也比较多,这里来看看常用的场景

splice(start):删除从start开始至数组末尾的所有元素

const skills = ['html', 'css', 'javascript'];
const removed = skills.splice(1);
console.log(skills); //[ 'html' ]
console.log(removed); //[ 'css', 'javascript' ]

splice(start, count):删除数组从start开始count个元素

const skills = ['html', 'css', 'javascript'];
const removed = skills.splice(1, 2); //删除从索引1开始的2个元素
console.log(skills); //[ 'html' ]
console.log(removed); //[ 'css', 'javascript' ]

splice(start, count, elem1, elem2,...):删除数组从start开始count个元素,并在start位置插入提供的元素,可以插入多个元素,下例,我们删除了索引从1开始的2个元素,并插入了两个新元素jquerylodash

const skills = ['html', 'css', 'javascript'];
const removed = skills.splice(1, 2, 'jquery', 'lodash');
console.log(skills); //[ 'html', 'jquery', 'lodash' ]
console.log(removed); //[ 'css', 'javascript' ]

start也可以为负数,最后一位元素索引为-1,下例,我们删除了最后一个元素,并插入了两个新元素jquerylodash

const skills = ['html', 'css', 'javascript'];
const removed = skills.splice(-1, 1, 'jquery', 'lodash');
console.log(skills); //[ 'html', 'css', 'jquery', 'lodash' ]
console.log(removed); //[ 'javascript' ]

查找数组元素

indexOf和lastIndexOf

indexOf(searchElem, startIndex): 从startIndex开始,顺序(从左向右)查找某个元素的索引,如果没有找到返回-1,startIndex可选,如果不提供,相当于是从第一位索引即0开始

lastIndexOf(searchElem, startIndex): 和indexOf类似,但是是逆序(从右向左)查找,startIndex可选,如果不提供,相当于是从最后一位索引即-1开始

const skills = ['html', 'css', 'javascript', 'html'];

console.log(skills.indexOf('html')); //0
console.log(skills.indexOf('html', 1)); //3
console.log(skills.indexOf('html5')); //-1

console.log(skills.lastIndexOf('html')); //3
console.log(skills.lastIndexOf('html', -1)); //3
console.log(skills.lastIndexOf('html', -2)); //0
console.log(skills.lastIndexOf('html5')); //-1

find和findIndex

这一组方法是查找满足某个特定条件的元素,该条件通过回调函数传递,当数组中的元素是对象时,可以发挥很大作用

find():查找 第一个 满足条件的元素
findIndex():查找 第一个 满足条件的元素的索引

const blogs = [
    { title: 'Array学习', author: '李雷' },
    { title: 'Object学习', author: '韩梅梅' },
    { title: 'Array学习', author: 'Jack' },
];//blogs数组的元素是三个对象

const blog = blogs.find(blog => blog.title === 'Array学习');//查找数组元素中title为“Array学习”的对象
console.log(blog);//{ title: 'Array学习', author: '李雷' }

const blogIndex = blogs.findIndex(blog => blog.title === 'Array学习');
console.log(blogIndex);//0

以上我们用箭头函数,也可以用普通的函数,返回值为bool,如:

function compare(blog){
	return blog.title === 'Array学习';
}
blogs.find(compare);
blogs.findIndex(compare);

判断某个元素是否在数组中

includes

includes(elem):判断某个值是否属于某个数组,返回值为bool类型

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(1)); //true
console.log(numbers.includes(0)); //false
console.log(numbers.includes('1')); //false

includes(elem, startIndex):从startIndex开始判断某个值是否属于某个数组,返回值为bool类型,startIndex可选,不提供则默认为0,
如果startIndex>=数组长度,返回false

console.log(numbers.includes(1, 0)); //true
console.log(numbers.includes(1, 1)); //false
console.log(numbers.includes(5, 4)); //true
console.log(numbers.includes(5, 5)); //false

some

includes作用一样,some用来判断某个值是否属于某个数组,但此方法用的是条件判断函数,如果判断函数返回true则some方法返回true,否则some方法返回false

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.some(number => number > 1)); //true
console.log(numbers.some(number => number > 5)); //false

遍历数组

通过for循环即可遍历数组

for(let index = 0; index < arr.length; index++){...}

这里我们看数组方法forEach的使用方法

forEach

forEach()接收一个回调函数,遍历数组中的每一个元素,对每个元素调用回调函数,回调函数只用提供一个参数即可正常使用,如:

const numbers = [1, 2, 3, 4, 5];
numbers.forEach(number => console.log(number));//1,2,3,4,5

回调函数多个参数情形:
forEach(callback(currentValue [, index [, array]]))

const numbers = [1, 2, 3, 4, 5];
numbers.forEach((number, index, array) =>
    console.log(`当前元素:${number},index:${index},当前数组${array}`)
);
//当前元素:1,index:0,当前数组1,2,3,4,5
//当前元素:2,index:1,当前数组1,2,3,4,5
//当前元素:3,index:2,当前数组1,2,3,4,5
//当前元素:4,index:3,当前数组1,2,3,4,5
//当前元素:5,index:4,当前数组1,2,3,4,5

数组计算,转换,过滤

map

当你想转换你的数组时,map很有用,map不会修改原数组,会返回一个新数组
例如:

const arrs = ['Array', 'Object', 'Function'];
const finalarrs = arrs.map(arr => `${arr}学习`);

console.log(finalarrs);//[ 'Array学习', 'Object学习', 'Function学习' ]

原素组没有发生变化

console.log(arrs);//['Array', 'Object', 'Function']

filter

当你想筛选数组的元素时,可以用filter,同样,filter也不会修改原数组,会返回一个满足筛选条件的所有元素的新数组
例如:

const numbers = [1, 2, 3, 4, 5];
const filtered = numbers.filter(number => number > 3);
console.log(filtered);//[ 4, 5 ]
console.log(numbers);//[1, 2, 3, 4, 5]

reduce

reduce用起来稍显复杂,非常适合用来做计算,统计等

reduce接收一个回调函数,这个函数可以有四个参数

arr.reduce(callback(accumulator, currentValue[, index[, array]] )[, initialValue])

如果没有提供初始值(initialValue)时,accumulator为数组第一个元素的值,index为1,currentValue即为第一个元素的值,例如:

const numbers = [0, 1, 2, 3, 4];
const result = numbers.reduce(function(accumulator, currentValue, currentIndex, array) {
    const result = accumulator + currentValue;
    console.log(accumulator, currentValue, currentIndex, array, result);
    return result;
});

上面我们将每一步的四个参数都输出,即可看的非常清楚这个过程了,结果如下

accumulator currentValue currentIndex array result
0 1 1 [ 0, 1, 2, 3, 4 ] 1
1 2 2 [ 0, 1, 2, 3, 4 ] 3
3 3 3 [ 0, 1, 2, 3, 4 ] 6
6 4 4 [ 0, 1, 2, 3, 4 ] 10

本例没有提供初始值
故,第一次迭代时

accumulator = numbers[0] = 0
currentValue = numbers[1] = 1
currentIndex = 1

最后一次迭代的结果即为最终reduce返回的结果10

console.log(result);//10

如果提供了初始值(initialValue),accumulator为初始值(initialValue),index为0,currentValue即为第一个元素的值,例如:

const result = numbers.reduce(function(accumulator, currentValue, currentIndex, array) {
    const result = accumulator + currentValue;
    console.log(accumulator, currentValue, currentIndex, array, result);
    return result;
}, 10);
accumulator currentValue currentIndex array result
10 0 0 [ 0, 1, 2, 3, 4 ] 10
10 1 1 [ 0, 1, 2, 3, 4 ] 11
11 2 2 [ 0, 1, 2, 3, 4 ] 13
13 3 3 [ 0, 1, 2, 3, 4 ] 16
16 4 4 [ 0, 1, 2, 3, 4 ] 20

本例没有提供初始值
故,第一次迭代时

accumulator = 初始值 = 10
currentValue = numbers[0] = 0
currentIndex = 0

这里参数array在每次迭代时,输出都一样,它其实代表的就是当前被reduce的数组,实际使用中可以不要

同样如果不需要知道当前迭代的次数index参数也可以不要

初始值还可以是其它数据类型如对象,例如我们有一组博客数组,我们需要按category字段来分组,这时可以用reduce来实现此需求:

const blogs = [{
    title: 'Array学习',
    category: 'javascript'
}, {
    title: 'Object学习',
    category: 'javascript'
}, {
    title: 'Animation学习',
    category: 'css'
}, {
    title: '语义化标签学习',
    category: 'html'
}];

const groupByCategory = blogs.reduce((accumulator, currentValue) => {
    console.log(accumulator, currentValue);
    const key = currentValue["category"];//当前的category值
    if (!accumulator[key]) {//如果accumulator对象还没有该key,则初始化为空数组
        accumulator[key] = [];
    }
    accumulator[key].push(currentValue);//将当前对象插入数组中
    return accumulator;
}, {});

console.log(groupByCategory);
//最终得到的结果如下:
// {
//   javascript: [
//     { title: 'Array学习', category: 'javascript' },
//     { title: 'Object学习', category: 'javascript' }
//   ],
//   css: [ { title: 'Animation学习', category: 'css' } ],
//   html: [ { title: '语义化标签学习', category: 'html' } ]
// }

sort

sort()方法给数组元素排序,会改变原数组
例如:

const numbers = [1, 2, 12, 3, 4];
numbers.sort();
console.log(numbers);//[ 1, 12, 2, 3, 4 ]

可以看到,排序后数组与原来的数组已不一样,但结果似乎不是我们想要的,因为sort()方法默认将数组元素按string类型来排序

console.log('12' < '2'); //true

怎样让数字按我们想要的排序方式来呢?

可以给sort()传一个函数,如果这个函数返回正数代表大于,返回负数代表小于,返回0代表等于

function compareNumber(a, b){
    return a - b;
}
const numbers = [1, 12, 2, 3, 4];
numbers.sort(compareNumber);
console.log(numbers); //[ 1, 2, 3, 4, 12 ]

当然用ES6箭头函数会更简洁

numbers.sort((a, b) => a - b);

reverse

将数组逆序返回,会改变原数组

const numbers = [1, 2, 12, 3, 4];
numbers.reverse();
console.log(numbers);//[ 4, 3, 12, 2, 1 ]

join

join()将数组元素合并成一个字符串,如果不提供参数,则以逗号分隔,否则按提供的参数分隔

const elements = ['Fire', 'Air', 'Water'];

console.log(elements.join());//Fire,Air,Water
console.log(elements.join(''));//FireAirWater
console.log(elements.join('-'));//Fire-Air-Water

join常和split结合使用,split是将字符串拆成数组,

const str = "Fire,Air,Water"
const elements = str.split(',');//['Fire', 'Air', 'Water']

Array.isArray

判断某个给定值值是否为数组,返回值为bool类型

Array.isArray([1, 2, 3]);  // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar');   // false
Array.isArray(undefined);  // false

不用数组方法,也可以判断是否为数组,下面提供两种方法参考:

const numbers = [1,2,3];
numbers.constructor === Array;//true

Object.prototype.toString.call(numbers) === '[object Array]';//true

如果用typeof判断数组,返回的是object,无法知道是否为数组

console.log(typeof []);//object

数组方法真的很多,这里就不一一列举了,有需要的时候可以再去查文档 MDN Array

总结

  • 数组定义:

    • 中括号语法:let arr = []
    • 构造函数创建:let arr = new Array()
  • 添加删除元素

    • push(…args):在数组末尾添加元素
    • pop():取数组末尾元素
    • unshift(…args):在数组首位添加元素
    • shift():取数组首位元素
  • 数组拷贝

    • slice(start, end):拷贝数组从start位开始至end-1位的元素,不包含end
    • splice(start, count, …args):从start位开始删除count个元素,并在start位插入元素
  • 查找数组元素

    • indexOf(elem, start):从start位开始顺序查找elem在数组中的索引,没有找到返回-1
    • lastIndexOf(elem, start):与indexOf类似,但逆序查找
    • find(callback):返回第一个满足callback函数的元素,返回值为bool
    • findIndex(callback):返回第一个满足callback函数的元素的索引,返回值为元素的索引
  • 判断元素是否存在

    • includes(elem, start):从start位开始判断数组是否包含元素elem,返回值为bool
    • some(callback):判断数组是否有满足callback条件的元素,返回值为bool
  • 遍历

    • forEach(callback):遍历数组元素,对每个元素调用callback函数
  • 数组计算,转换,过滤

    • map(callback):转换数组元素,返回一个新数组,不改变原素组
    • filter(callback):筛选数组元素,返回一个新数组,不改变原素组
    • reduce(callback,initvalue):主要用于计算,注意提供initvalue和不提供initvalue的区别,不改变原素组
    • sort():给数组元素排序,默认将数组元素当成string类型排序,会改变原数组
    • reverse():将数组元素逆序,会改变原数组
    • join():合并数组元素,返回一个合并的字符串
  • 判断是否为数组

    • Array.isArray(arr):判断arr是否为一个数组

你可能感兴趣的:(javascript)