数组的32场演唱会

你有没有遇到过如下的场景。coding中当你要处理一个数组的时候,脑海里只浮现出了forEach;面试中,当面试官让你说说数组的方法的时候,脑海里只浮现出了forEach;做梦时当一个数组追杀你,你能想到的只有用forEach来抵抗。如果是,那么你一定要听一听今年数组举办的32场演唱会。只要听完了这32场演唱会,保证下次当你遇到数组的时候,闭着眼睛都能想出32种方法对付他们。另外,友情提示,结尾有彩蛋。

书归正传,数组 是javascript中最常用的引用对象类型之一,在javascript的各种常用的数据结构中,诸如队列、栈,他们的基本实现方式用的就是数组,因此掌握数组的各项操作也就成为能否自如操控数据结构的要点。截止到ES8,数组目前共有32种方法,可大体分为如下几种:

  • 数组的判断 1个方法

  • 数组内容的判断 3个方法

  • 数组内容的获取 4个方法

  • 数组的构造 6个方法

  • 数组的改造 9个方法

  • 数组的循环遍历 4个方法

  • 数组的累加 2个方法

  • 数组转字符串 3个方法

数组的判断 1个方法

Array.isArray()

  • 语法:Array.isArray(obj)

  • 参数:需要检查的对象

  • 返回:true,false

开唱:

判断数据类型的方法有几个比如使用typeof,instanceof,那么为什么还要有isArray方法呢?

首先说说typeof。众所周知,javascript有五个基本数据类型undefined,null,number,string,boolean,还有引用数据类型Object,Array,Function,Data,Date,RegExp等typeof 运算符返回一个用来表示表达式数据类型的字符串,可能的字符串有:"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。这里面是没有Array的,无论引用的是什么类型的对象,它都返回 "object",因此typeOf是不能用来判断数组的。那么instanceof呢?通常来讲,使用instanceof就是判断一个实例是否属于某种类型,这是基于javascript的原型继承机制的,然而在浏览器的环境中如果使用iframe,则可能出现多个不同的全局变量,从而无法发挥instanceof的作用,因此,Array.isArray()成功荣升为最靠谱的检测方法。但话说回来,其实它的的实现方式还是很简单的:

Array.isArray = function(arg) {	
    return Object.prototype.toString.call(arg) === '[object Array]';	
};

需要特别指出的是,Array.isArray()方法是一个静态方法,只能通过Array对象来调用

数组内容的判断 3个方法

Array.prototype.every()

  • 语法:arr.every(callback[, thisArg])

  • 参数:

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 断言数组内每个元素的callback函数

    • thisArg 可选 执行callback时作为this的值

  • 返回:t断言数组的所有元素是否满足callback函数,是则返回true,否则返回false

Array.prototype.some()

  • 语法:arr.some(callback[, thisArg])

  • 参数:

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 断言数组内每个元素的callback函数

    • thisArg 可选 执行callback时作为this的值

  • 返回:断言数组内是否有元素满足callback函数,是则返回true,否则返回false

Array.prototype.includes() ECMA7

  • 语法:

    • arr.includes(searchElement)

    • arr.includes(searchElement, fromIndex)

  • 参数:

    • searchElement 需要查找的元素

    • fromIndex 可选 指定开始查询位置

  • 返回:true,false

开唱:

如果你要对数组内容进行一些判断,可以先不要想着用forEach,优先思考一下上面三个是否可以满足你的需求。其中,every可以判断数组内的内容是否全部满足callback函数的条件,而some则可以判断数组内是否有内容满足callback函数的条件。 举个栗子:

function isBigEnough(element, index, array) { 	
      return element >= 10; 	
} 	
	
[12, 5, 8, 130, 44].every(isBigEnough);   // false 	
[12, 5, 8, 130, 44].some(isBigEnough); // true

includes方法则可以查找是否具体存在某一个元素,或者从某个具体的位置开始是否存在某个元素。但值得注意的是,includes方法是ECMA7中的标准,在使用之前需要确定运行环境是否支持此项方法。

var a = [1, 2, 3];	
a.includes(2); // true	
a.includes(2, 1); // true 	
a.includes(2, 2); // false	
a.includes(4); // false

数组内容的获取 4个方法

Array.prototype.find() ECMA6

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

  • 参数:

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 对数组内每个值执行的方法

    • thisArg 可选 执行callback时作为this的值

  • 返回:第一个满足callback条件的值

Array.prototype.findIndex() ECMA6

  • 语法:arr.findIndex(callback[, thisArg])

  • 参数:

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 对数组内每个值执行的方法

    • thisArg 可选 执行callback时作为this的值

  • 返回:满足callback条件的位置,没有则返回-1

Array.prototype.indexOf()

  • 语法:arr.indexOf(searchElement[, fromIndex])

  • 参数:

    • searchElement 需要查找的元素

    • fromIndex 可选 指定查询位置

  • 返回:查到的第一个元素在数组内的位置,没有返回-1

Array.prototype.lastIndexOf()

  • 语法:arr.lastIndexOf(searchElement[, fromIndex])

  • 参数:

    • searchElement 需要查找的元素

    • fromIndex 可选 指定查询位置

  • 返回:查到的最后一个元素在数组内的位置,没有返回-1

开唱:

这一组方法和数组内容判断的一组有些相似,只不过,数组内容判断的方法返回的都是true或者false,而这一组方法都会返回具体的值。 find方法会返回满足你条件的第一个元素,而findIndex会返回满足你条件的第一个元素的位置。而indexOf、lastIndexOf方法则和includes方法很相似,只不过前两个返回的是具体的位置,includes返回的是布尔值。 举个栗子:

function isBigEnough(element) {	
  return element >= 15;	
}	
	
console.log([12, 5, 8, 130, 5, 44].find(isBigEnough)); // 130	
console.log([12, 5, 8, 130, 5, 44].findIndex(isBigEnough)); // 3	
console.log([12, 5, 8, 130, 5, 44].indexOf(5)); // 1	
console.log([12, 5, 8, 130, 5, 44].lastIndexOf(5)); // 4	
console.log([12, 5, 8, 130, 5, 44].some(isBigEnough)); // true	
console.log([12, 5, 8, 130, 5, 44].every(isBigEnough)); // false	
console.log([12, 5, 8, 130, 5, 44].includes(5,4)); // true

数组的构造 6个方法

Array.from() ECMA6

  • 语法:Array.from(arrayLike[, mapFn[, thisArg]])

  • 参数:

    • arrayLike 具有长度属性和有序元素的对象

    • mapFn 可选 对参数arrayLike执行的map函数

    • thisArg 可选 执行mapFn时作为this的值

  • 返回:一个新的数组实例

Array.of() ECMA6

  • 语法:Array.of(element0[, element1[, ...[, elementN]]])

  • 参数:elementN 生成数组的元素

  • 返回:一个新的数组实例

Array.prototype.concat()

  • 语法:ar newarray = oldarray.concat(value1[, value2[, ...[, valueN]]])

  • 参数:valueN 搭伙到原数组中的元素或数组

  • 返回:一个新的数组实例

Array.prototype.filter()

  • 语法:var newArray = arr.filter(callback[, thisArg])

  • 参数:

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 断言数组的每个元素是否满足callback函数,返回true则保留元素,返回false则删除元素

    • thisArg 可选 执行callback时作为this的值

  • 返回:一个新的数组实例

Array.prototype.map()

  • 语法:var newArray = arr.filter(callback[, thisArg])

  • 参数:

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 遍历原数组元素生成新数组元素的函数

    • thisArg 可选 执行callback时作为this的值

  • 返回:一个新的数组实例

Array.prototype.slice()

  • 语法:

    • arr.slice()

    • arr.slice(begin)

    • arr.slice(begin, end)

  • 参数:

    • begin 可选 浅拷贝的初始位置

    • end 可选 浅拷贝的结束位置

  • 返回:一个新的数组实例

开唱:

在这一组中都是可以返回一个新数组,同时不会改变原数组的方法,因此把它们归为数组的构造这一类,它们都可以构造出一个新的数组。

Array.from()Array.of()ES6中新增的方法。需要特别指出的是,Array.from()Array.of()方法是静态方法,只能通过Array对象来调用

Array.from方法用于将两类对象转为真正的数组:类似数组的对象( array-like object )和可遍历( iterable )的对象(包括 ES6 新增的数据结构 Set 和Map )。在此之前,我们习惯于使用Array.prototype.slice.call()这种方式,将类数组对象转换为数组,如今我们有了更加直接的方法。

function f() {	
  return Array.from(arguments);	
}	
f(1, 2, 3);	
// [1, 2, 3]

Array.of()方法则更加简单,将若干参数元素组成一个新的数组

Array.of(1);       // [1] 	
Array.of(1, 2, 3); // [1, 2, 3]

Array.prototype.concat()方法,既可以用于将目标数组和参数数组连接成为一个新数组,也可以实现类似于将参数元素按顺序push进数组的效果。除了使用concat,也可以使用ES6中新增的扩展运算符(spread,也就是三个点...),实现合并数组的功能。

var arr1 = ['a', 'b'];	
var arr2 = ['c'];	
var arr3 = ['d', 'e'];	
	
// ES5的合并数组	
arr1.concat(arr2, arr3);	
// [ 'a', 'b', 'c', 'd', 'e' ]	
	
// ES6的合并数组	
[...arr1, ...arr2, ...arr3]	
// [ 'a', 'b', 'c', 'd', 'e' ]

通过Array.prototype.filter()方法的命名就可以看出,它实现了一个类似于过滤器的效果。满足参数函数条件的元素将被过滤出来组成一个新的数组返回。

var myArr = [1,2,3,4,5];	
var result = myArr.filter(v=>v<3)	
console.log(result) //[ 1, 2 ]

Array.prototype.map()方法有些类似于forEach方法。不同的是,forEach方法只是单纯的循环遍历数组,而map可以将循环遍历后的结果组成一个新的数组返回

var numbers = [1, 5, 10, 15];	
var doubles = numbers.map(x => x * 2);	
console.log(doubles) //[ 2, 10, 20, 30 ]

Array.prototype.slice()方法实现数组的截取功能,可以指定开始结束位置,截取相应位置内的元素组成新的数组。

var a = ['zero', 'one', 'two', 'three'];	
var sliced = a.slice(1, 3);	
	
console.log(a);      // ['zero', 'one', 'two', 'three']	
console.log(sliced); // ['one', 'two']

数组的改造

Array.prototype.copyWithin() ECMA6

  • 语法:

    • arr.copyWithin(target)

    • arr.copyWithin(target, start)

    • arr.copyWithin(target, start, end)

  • 参数:

    • target 拷贝到的目标位置

    • start 可选 拷贝内容起始位置

    • end 可选 拷贝内容结束位置

Array.prototype.fill() ECMA6

  • 语法:

    • arr.fill(value)

    • arr.fill(value, start)

    • arr.fill(value, start, end)

  • 参数:

    • value 填充数组的值

    • start 可选 填充起始位置

    • end 可选 填充结束位置

Array.prototype.pop()

  • 语法:arr.pop()

  • 返回:移除的元素

Array.prototype.push()

  • 语法:arr.push([element1[, ...[, elementN]]])

  • 参数:elementN 压如数组尾部的元素

  • 返回:数组的长度

Array.prototype.shift()

  • 语法:arr.shift()

  • 返回:移除的元素

Array.prototype.unshift()

  • 语法:arr.unshift([element1[, ...[, elementN]]])

  • 参数:elementN 压如数组头部的元素

  • 返回:数组的长度

Array.prototype.reverse()

  • 语法:arr.reverse()

  • 返回:相反的数组

Array.prototype.sort()

  • 语法:

    • array.sort()

    • arr.sort(compareFunction)

  • 参数:

    • compareFunction 可选 定义排序规则的函数

  • 返回:一个新的数组实例

Array.prototype.splice()

  • 语法:

    • arr.splice(start)

    • arr.splice(start, deleteCount)

    • arr.splice(start, deleteCount, item1, item2, ...)

  • 参数:

    • start 开始改变数组的位置

    • deleteCount 可选 删除数组的数量

    • itemN 可选 插入数组的元素

  • 返回:包含删除元素的数组

开唱:

Array.prototype.copyWithin()Array.prototype.fill()ES6中新增的方法。Array.prototype.copyWithin()实现了数组内的拷贝,可以选定拷贝数据来源的开始结束位置,以及替换目标开始位置。Array.prototype.fill()则会将指定位置的数组元素全部替换为指定的值

// 将3号位复制到0号位	
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)	
// [4, 2, 3, 4, 5]	
	
//从1号位开始,向原数组填充7,到2号位之前结束	
['a', 'b', 'c'].fill(7, 1, 2)	
// ['a', 7, 'c']

这一组方法中,我们最熟悉的莫过于pop,push,shift,unshift这四个方法。其中pop,push是控制数组尾部元素进出的方法,而shift,unshift是控制数组头部元素进出的方法。通过上面的方法我们可以通过数组模拟实现栈和队列的效果。栈是先进后出,进栈使用push方法,出栈使用pop方法。队列是先进先出,进队列使用push方法,出队列使用shift方法

Array.prototype.reverse()方法可得到一个反转的队列,但它在返回反转数组的同时,也改变的原数组的排列顺序,这一点是需要注意的,因此将它归入了数组的改造这一组当中。同样Array.prototype.sort()也是用于数组排序的一个方法,不传参数将根据元素的unicode进行排序,同样会改变原数组的排列顺序。

Array.prototype.splice()方法可以实现数组特定位置元素的插入,删除

var myArr = [1,2,3,4,5];	
// 删除3号位元素	
myArr.splice(2,1) //[ 1, 2, 4, 5 ]	
// 在第3号位元素的位置插入元素3	
myArr.splice(2,0,3) //[ 1, 2, 3, 4, 5 ]	
// 删除第4号位及后面的元素	
myArr.splice(3) //[ 1, 2, 3 ]	
// 第4号位元素位置插入元素4,5	
myArr.splice(3,0,4,5) //[ 1, 2, 3, 4, 5 ]

数组的遍历

Array.prototype.forEach()

  • 语法:arr.forEach(function callback(currentValue, index, array) { //your iterator }[, thisArg]);

  • 参数:

    • currentValue 当前处理的元素

    • index 当前元素的位置

    • array 当前处理的数组

    • callback 对每个元素遍历执行的方法

    • thisArg 执行callback时的this值

  • 返回:undefined

Array.prototype.keys() ECMA6

  • 语法:arr.keys()

  • 返回:数组迭代器对象

Array.prototype.values() ECMA6

  • 语法:arr.values()

  • 返回:数组迭代器对象

Array.prototype.entries() ECMA6

  • 语法:arr.entries()

  • 返回:数组迭代器对象

开唱:

相信大部分人对Array.prototype.forEach()这个数组方法并不陌生,它对数组元素遍历执行回调方法,这里不做过多介绍。Array.prototype.entries()Array.prototype.keys()Array.prototype.values()ES6中新增的三个数组方法,用于遍历数组。它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历

for (let index of ['a', 'b'].keys()) {	
  console.log(index);	
}	
// 0	
// 1	
	
for (let elem of ['a', 'b'].values()) {	
  console.log(elem);	
}	
// 'a'	
// 'b'	
	
for (let [index, elem] of ['a', 'b'].entries()) {	
  console.log(index, elem);	
}	
// 0 "a"	
// 1 "b"

数组的累加

Array.prototype.reduce()

  • 语法:arr.reduce(callback[, initialValue])

  • 参数:

    • accumulator 累加值

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 累加器

    • initialValue 可选 初始值

  • 返回:累加器最终计算结果

Array.prototype.reduceRight()

  • 语法:arr.reduceRight(callback[, initialValue])

  • 参数:

    • accumulator 累加值

    • currentValue 当前值

    • currentIndex 当前值的位置

    • array 所操作的数组

    • callback 累加器

    • initialValue 可选 初始值

  • 返回:累加器最终计算结果

开唱:

Array.prototype.reduce()Array.prototype.reduceRight()方法都接收一个函数作为累加器,数组中的每个值(reduce从左到右,reduceRight从右到左)开始缩减,最终为一个值。相比与forEach、map等数组方法,reduce不必再另外定义一个变量存储最终计算结果,更加方便。另外,通过观察,不难发现一个规律,除了Array.prototype.reduce()Array.prototype.reduceRight()方法,其他有callback回调参数的方法中,其callback回调函数中的参数都是包含三个参数的:当前值currentValue,当前值的位置currentIndex,所操作的数组array;而Array.prototype.reduce()Array.prototype.reduceRight()方法则包含四个,多了一个累加值作为第一个参数

var total = [0, 1, 2, 3].reduce(function(sum, value) {	
  return sum + value;	
}, 0);	
// total is 6

数组转字符串

Array.prototype.toString()

  • 语法:arr.toString()

  • 返回:数组的字符串表示

Array.prototype.toLocaleString()

  • 语法:

    • arr.toLocaleString();

    • arr.toLocaleString(locales);

    • arr.toLocaleString(locales, options);

  • 参数:

    • locales BCP 47语言标签字符串

    • options 可选 配置参数对象

  • 返回:数组的字符串表示

Array.prototype.join()

  • 语法:

    • arr.join()

    • arr.join(separator)

  • 参数:separator 可选 分割符

  • 返回:数组的字符串表示

开唱:

我们时常会遇到数组与字符串之间的转换。根据上面学到的知识,将字符串转换为数组,除了字符串的方法,我们还可以使用数组的Array.from()方法。而将数组转换为字符串,则可以使用上面的三个方法。其中Array.prototype.toString()方法可以将数组直接转换为字符串的表示形式。Array.prototype.toLocaleString()方法可以根据参数将数组的字符串表示本地化,但支持的情况并不是很好,因此不用过多考虑。Array.prototype.join()方法可以指定数组转换为字符串的分隔符。

var months = ['Jan', 'Feb', 'Mar', 'Apr'];	
months.toString(); // "Jan,Feb,Mar,Apr"	
months.join('-'); // "Jan-Feb-Mar-Apr"

那位说,听你说了这么多,也没见什么演唱会啊,那下面就让我们真正的唱一段。

判断是不是数组,isArray最靠谱。

按照条件来判断,every/some给答案

是否包含此元素,includes最快速。

find/findIndex很相似,按条件给第一个值。

indexOf/lastIndexOf也很强,有没有来在哪忙。

from和of,都能用来生数组。

concat当红娘,数组结婚她帮忙。

filter瘦身有一套,不想要的都不要。

map整容有实力,改头换面出新意。

slice就像买切糕,想切哪来就下刀。

自力更生很重要,copyWithin自己搞。

fill就像填大坑,想往哪扔往哪扔。

搬山摸金四兄弟,pop、push、shift、unshift不难记。

造反其实很容易,reverse一下看好戏。

sort排序有技巧,能小大来能大小。

splice要认识,能插能删有本事。

forEach最熟悉,有人说它是万能滴。

keys、values、entries,遍历数组新方式。

算总账,不要慌,reduce、reduceRight帮你忙。

toString,join变字符,toLocaleString不常用。

当里个当,当里个当,数组32方法,猥琐发育不要浪,嘿!不要浪!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值