zoukankan      html  css  js  c++  java
  • 数组的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()成功荣升为最靠谱的检测方法。但话说回来,其实它的的实现方式还是很简单的:

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

    需要特别指出的是,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函数的条件。 举个栗子:

    1.  1 function isBigEnough(element, index, array) {
       2 
       3      return element >= 10;
       4 
       5 }
       6 
       7  
       8 
       9 [12, 5, 8, 130, 44].every(isBigEnough);   // false
      10 
      11 [12, 5, 8, 130, 44].some(isBigEnough); // true

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

    1. 1 var a = [1, 2, 3];
      2 
      3 a.includes(2); // true
      4 
      5 a.includes(2, 1); // true
      6 
      7 a.includes(2, 2); // false
      8 
      9 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返回的是布尔值。 举个栗子:

    1.  1 function isBigEnough(element) {
       2 
       3  return element >= 15;
       4 
       5 }
       6 
       7  
       8 
       9 console.log([12, 5, 8, 130, 5, 44].find(isBigEnough)); // 130
      10 
      11 console.log([12, 5, 8, 130, 5, 44].findIndex(isBigEnough)); // 3
      12 
      13 console.log([12, 5, 8, 130, 5, 44].indexOf(5)); // 1
      14 
      15 console.log([12, 5, 8, 130, 5, 44].lastIndexOf(5)); // 4
      16 
      17 console.log([12, 5, 8, 130, 5, 44].some(isBigEnough)); // true
      18 
      19 console.log([12, 5, 8, 130, 5, 44].every(isBigEnough)); // false
      20 
      21 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()这种方式,将类数组对象转换为数组,如今我们有了更加直接的方法。

    1. 1 function f() {
      2 
      3  return Array.from(arguments);
      4 
      5 }
      6 
      7 f(1, 2, 3);
      8 
      9 // [1, 2, 3]

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

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

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

    1.  1 var arr1 = ['a', 'b'];
       2 
       3 var arr2 = ['c'];
       4 
       5 var arr3 = ['d', 'e'];
       6 
       7  
       8 
       9 // ES5的合并数组
      10 
      11 arr1.concat(arr2, arr3);
      12 
      13 // [ 'a', 'b', 'c', 'd', 'e' ]
      14 
      15  
      16 
      17 // ES6的合并数组
      18 
      19 [...arr1, ...arr2, ...arr3]
      20 
      21 // [ 'a', 'b', 'c', 'd', 'e' ]

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

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

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

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

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

    1. 1 var a = ['zero', 'one', 'two', 'three'];
      2 
      3 var sliced = a.slice(1, 3);
      4 
      5  
      6 
      7 console.log(a);      // ['zero', 'one', 'two', 'three']
      8 
      9 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()则会将指定位置的数组元素全部替换为指定的值

    1.  1 // 将3号位复制到0号位
       2 
       3 [1, 2, 3, 4, 5].copyWithin(0, 3, 4)
       4 
       5 // [4, 2, 3, 4, 5]
       6 
       7  
       8 
       9 //从1号位开始,向原数组填充7,到2号位之前结束
      10 
      11 ['a', 'b', 'c'].fill(7, 1, 2)
      12 
      13 // ['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()方法可以实现数组特定位置元素的插入,删除

    1.  1 var myArr = [1,2,3,4,5];
       2 
       3 // 删除3号位元素
       4 
       5 myArr.splice(2,1) //[ 1, 2, 4, 5 ]
       6 
       7 // 在第3号位元素的位置插入元素3
       8 
       9 myArr.splice(2,0,3) //[ 1, 2, 3, 4, 5 ]
      10 
      11 // 删除第4号位及后面的元素
      12 
      13 myArr.splice(3) //[ 1, 2, 3 ]
      14 
      15 // 第4号位元素位置插入元素4,5
      16 
      17 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()是对键值对的遍历

    1.  1 for (let index of ['a', 'b'].keys()) {
       2 
       3  console.log(index);
       4 
       5 }
       6 
       7 // 0
       8 
       9 // 1
      10 
      11  
      12 
      13 for (let elem of ['a', 'b'].values()) {
      14 
      15  console.log(elem);
      16 
      17 }
      18 
      19 // 'a'
      20 
      21 // 'b'
      22 
      23  
      24 
      25 for (let [index, elem] of ['a', 'b'].entries()) {
      26 
      27  console.log(index, elem);
      28 
      29 }
      30 
      31 // 0 "a"
      32 
      33 // 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()方法则包含四个,多了一个累加值作为第一个参数

    1. 1 var total = [0, 1, 2, 3].reduce(function(sum, value) {
      2 
      3  return sum + value;
      4 
      5 }, 0);
      6 
      7 // 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()方法可以指定数组转换为字符串的分隔符。

    1. 1 var months = ['Jan', 'Feb', 'Mar', 'Apr'];
      2 
      3 months.toString(); // "Jan,Feb,Mar,Apr"
      4 
      5 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方法,猥琐发育不要浪,嘿!不要浪!

    如果你喜欢我们的文章,关注我们的公众号和我们互动吧。

  • 相关阅读:
    第31-35课
    Cisco学习笔记
    ScreenOS地址转换
    Bootstrap3组件--2
    Bootstrap3组件--1
    Bootstrap3全局CSS样式
    MySQL数据库中字段含逗号的数据,分隔成多条数据
    EF Core 关联数据
    ABP 创建 webapi
    Abp ajax The required antiforgery request token was not provided in either form field
  • 原文地址:https://www.cnblogs.com/zhuanzhuanfe/p/7481336.html
Copyright © 2011-2022 走看看