JS数组知多少

版权声明:文章首发于本人简书账号人生还有多少个二十年
欢迎转载,转载请注明出处

前言

数组是编程语言中最为常见的数据类型之一,跟对象相比,它的突出特点是"有序"。JS的数组还有这些特点:数组成员类型可以不一致,数组长度可以动态调整,数组下标越界不报错。

// 一个数组,可以同时包含多种数据类型的数据,而且,数组之中还可以嵌套数组
var arr = [1, "2", true, null, undefined, [{a:1,b:2,c:3}]];
arr.length; // 6
// 不会越界报错,而是在指定索引处创建新元素,并自动更新数组的length属性值。
arr[100] = 100; 
arr.length; // 101
// 数组的length属性是可读可写
// length值调低,则会删除部分元素;调高,则生成稀疏数组
arr.length = 6;
arr; // [1, "2", true, null, undefined, [{a:1,b:2,c:3}]]
arr.length = 10;
arr[7]; // undefined

数组的常用方法

接下来,以例子为主,解释为辅,简述相关知识

1. 增删元素(push()、pop()、unshift()、shift())

var arr = [];
arr.push("a", "b"); // 2
arr // ["a", "b"]
arr.pop(); // "b"
arr // ["a"]
arr.unshift("x", "y"); // 3
arr // ["x", "y", "a"]
arr.shift(); // "x"
arr // ["y", "a"]
  • push()和unshift()都是向数组添加元素,可以同时添加多个元素,它们的返回值都是更新后的数组的长度;
  • pop()和shift()都是从数组中移除元素,只移除一项,它们的返回值都是被移除的那个元素;
  • push()和pop()的操作发生在数组尾部,unshift()和shift()的操作发生在数组头部;
  • 栈数据结构的访问规则是LIFO(后进先出),插入和删除的操作发生在同一端;而队列的访问规则为FIFO(先进先出),插入和删除的操作不在同一端;
  • push()配合pop()可以模拟栈的行为;shift()和push()、unshift()和pop()都可以实现类似队列的行为。

2. 排序(reverse()、sort())

var arr1 = [1, 2, 3];
arr1.reverse(); // [3, 2, 1]
arr1; // [3, 2, 1]

var arr2 = [1, 3, 2];
arr2.sort(); // [1, 2, 3]
arr2; // [1, 2, 3]
  • 从上面可以看出,reverse()和sort()都会改变原数组,并且它们的返回值都是排序之后的数组。
  • reverse()用于反转数组。
  • sort()用于以升序或者降序的方式排列数组项。

为了实现排序,sort()方法会调用每个数组项的toString()方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串。

var arr3 = [1, 2, 10];
arr3.sort(); // [1, 10, 2]
var arr4 = ["a", "c", "b", "B"];
arr4.sort(); // ["B", "a", "b", "c"]

sort()可以接收一个函数,用于提供更实用的排序功能。
格式如下:sort(fn(arg1, arg2))

var arr5 = [1, 3, 2];
// 升序排列
arr5.sort(function(a, b){
    return a - b;
}); // [1, 2, 3]
arr5 //  [1, 2, 3]
// 降序排列
arr5.sort(function(a, b){
    return b - a;
}); // [3, 2, 1]

3. 操作方法(concat()、slice()、splice())

// concat():用于合并多个数组,生成新数组,对原数组没有影响
// 数组合并过程中,各数组只拆除最外层的“[]”,合并操作并不是递归的
// 这表明,生成的新数组仍然可以含有数组
var arr1 = [];
arr1.concat([1], [2], [[3,4], [5, 6]]); // [1, 2, [3, 4], [5, 6]];
arr1; // []
// slice(): 用于截取子数组,且操作并不影响原数组
// 可以给定两个参数,一个是起始索引,一个是结束索引
var arr2 = ["a", "b", "c", "d"];
// 没给定参数,相当于复制数组
arr2.slice(); // ["a", "b", "c", "d"]
arr2 // ["a", "b", "c", "d"]
// 只给定起始索引,默认从该索引处一直截取到末尾
arr2.slice(2); //  ["c", "d"]
arr2 // ["a", "b", "c", "d"]
// 记清楚了!从起始索引截取到结束索引之前,并不包含结束索引处的元素
arr2.slice(1, 3); // ["b", "c"]
arr2 //  ["a", "b", "c", "d"] 
// splice(): 增、删、替换数组元素,直接修改原数组
// 该操作的返回值是被删除的元素组成的数组
var arr3 = ["1", "2", "3", "a", "b", "c"];
// 从索引为4处开始删除元素,一直到数组末尾
arr3.splice(4); // ["b", "c"]
arr3 // ["1", "2", "3", "a"]
// 从索引为0处开始,删除2个元素
arr3.splice(0, 2); // ["1", "2"]
arr3 // ["3", "a"]
// 从索引为0处开始,删除0个元素,并在该处插入1个元素"x"
arr3.splice(0, 0, "x"); // []
arr3 // ["x", "3", "a"]
// 删除几个元素,就插入几个元素,可以实现splice()替换元素功能
arr3.splice(0, 1, "y"); // ["x"]
arr3 // ["y", "3", "a"]

4. 位置方法

// indexOf()和lastIndexOf()都可以用于查询指定元素在数组中的位置,
// 返回第一个匹配的元素的索引。
// 两者的区别在于,前者是从数组头部开始查找,后者则从尾部开始查找
[1,2,4,-1,2].indexOf(2) // 1
[1,2,4,-1,2].lastIndexOf(2) // 4

5. 迭代方法(every()、some()、filter()、map()、forEach())

[1,2,3].every(function(item, index, array){return item > 0;});
// true
[1,2,3].every(function(item, index, array){return item > 2;});
// false
[1,2,3].some(function(item, index, array){return item > 2;});
// true
[1,2,3].filter(function(item, index, array){return item > 2;});
// [3]
[1,2,3].map(function(item, index, array){   return item * 2;});
// [2, 4, 6]
var sum = 0;
[1,2,3].forEach(function(item, index, array){sum += item;});
sum // 6

这五个迭代方法都接收一个函数,并且对数组中的每一项都运行给定函数,这些迭代方法都不会改变原数组。它们的返回值如下:

  • every():给定函数对每一项都返回true,则返回true。
  • some():给定函数对任一项返回true,则返回true。
  • filter():返回该函数会返回true的项组成的数组。
  • map():返回每次函数调用的结果组成的数组。
  • forEach():没有返回值。

6. 归并方法(reduce()、reduceRight())

[1,2,3].reduce(function(prev, cur){return prev + cur});
// 6
[1,2,3].reduceRight(function(prev, cur){return prev + cur});
// 6

reduce()和reduceRight()这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。前者的迭代顺序是从前往后,后者则相反

7. 转换方法(join())

join()可以将数组转换为字符串,相反,split()可以将字符串转换为数组。
可以给它们指定分隔符,若未指定,则默认使用逗号。

var arr = [1,2,3];
arr.join(); // "1,2,3"
arr.join(""); // "123"
arr.join("-"); // "1-2-3"
arr.join().split(); // ["1,2,3"]

var str = "abc";
str.split(); // ["abc"]
str.split(""); // ["a", "b", "c"]
str.split("-"); // ["abc"]
str.split().join(); // "abc"

技巧与提示

  • 了解各个数组方法的功能,接收哪些参数,有没有返回值,返回值是什么,会不会改变原数组,浏览器兼容性如何。
  • 位置方法、迭代方法和归并方法都是ES5的标准。IE兼容性:IE9+。

参考资源

  • 《JavaScript高级程序设计(第3版)》
  • 《JavaScript权威指南》
  • MDN
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容

  • 前言 Array是js中引用的数据类型,我感觉不光除了Object外,Array也是平常开发中尤为重要的一种数据类...
    Ziksang阅读 1,090评论 4 16
  • 说点啥 数组是程序员的法宝之一,善用数组方法可以使数据处理变的简单(优雅)。每次重新看数组的知识都有新收获。 什么...
    石菖蒲_xl阅读 923评论 0 11
  • 由于最近都在freecodecamp上刷代码,运用了很多JavaScript数组的方法,因此做了一份关于JavaS...
    2bc5f46e925b阅读 1,971评论 0 16
  • 检测数组 对于一个网页,或者一个全局作用域而言,使用 instanceof 操作符就能得到满意的结果: 支持 Ar...
    林深鹿影阅读 451评论 0 0
  • 数组 知识汇总 前置知识: 数组是一个有序的数据集合,可使用数组名称和索引进行访问。 在JavaScript中数组...
    Daeeman阅读 664评论 1 7