一直以来都想来总结一下js的数组使用方法,因为有时候时间一长有的方法就记不太清,突然要用的时候还要去查,这里做下总结,自己巩固一下同时也方便以后有缘人一起来看😁
首先我们先来看一下谷歌浏览器里Array内置的方法有多少,如下↓
真是不看不知道,一看吓一跳,在我印象里数组的使用方法加上ES6新语法最多也就十几个吧
这里我数了一下从concat到valueOf总共37个(你敢信,无知啊),下面的“__”开头的就暂时不说了
----------------这里我们先来说一下最常用的几个,然后再一个一个解读剩下的----------------
1.Array.push()
-+-向数组的末尾添加一个或更多元素,并返回新的长度。
let arr = [1,2,3]; console.log(arr.push(6)); // 4 console.log(arr) // [1, 2, 3, 6]
2.Array.pop()
-+-删除数组的最后一个元素,并返回删除的元素。
let arr = [1,2,3]; console.log(arr.pop()); // 3 console.log(arr) // [1, 2]
3.Array.unshift()
-+-向数组的开头添加一个或更多元素,并返回新的长度。
let arr = [1,2,3]; console.log(arr.unshift(6)); // 4 console.log(arr) // [6, 1, 2, 3]
4.Array.shift()
-+-删除并返回数组的第一个元素。
let arr = [1,2,3]; console.log(arr.shift()); // 1 console.log(arr) // [2, 3]
5.Array.splice(开始的位置下标,删除的个数,要插入的元素1,元素2,...)
-+-方法用于添加或删除数组中的元素,并返回删除的数组。PS:这个方法增删改查都可以,上面4个方法都可以用splice实现
let arr1 = ['a', 'b', 'c', 'd']; console.log(arr1.splice(2,0,1)); // [] console.log(arr1) // ["a", "b", 1, "c", "d"] let arr2 = ['a', 'b', 'c', 'd']; console.log(arr2.splice(2,1)); // ['c'] console.log(arr2) // ["a", "b", "d"] let arr3 = ['a', 'b', 'c', 'd']; console.log(arr3.splice(2,1,'e')); // ["c"] console.log(arr3); // ["a", "b", "e", "d"] let arr4 = ['a', 'b', 'c', 'd']; console.log(arr4.splice(2,1,'e',4)); // ["c"] console.log(arr4); // ["a", "b", "e", 4, "d"]
6.Array.slice(开始的位置下标,结束位置的下标)
-+-选取数组的的一部分,并返回一个新数组。(不包括结束位置)。注意:slice()方法不会改变原始数组。
其实slice()同样也可以操作字符串和substring()的功能一样
let arr1 = ['a', 'b', 'c', 'd']; console.log(arr1.slice(1, 3)); // ["b", "c"] console.log(arr1); // ["a", "b", "c", "d"] let arr2 = ['a', 'b', 'c', 'd']; console.log(arr2.slice(1)); // ["b", "c", "d"] console.log(arr2); // ["a", "b", "c", "d"]
7.Array.concat(数组1,数组2,...)
-+-连接 2 个或更多数组,并返回连接后的新数组。注意:concat()方法不会改变原始数组。
let arr1 = [1, 2, 3],arr2 = [4, 5, 6]; let arr = arr1.concat(arr2); console.log(arr); //[1, 2, 3, 4, 5, 6]
8.Array.join(指定字符)
-+-将数组里所有的元素连接成一个字符串,并返回该字符串,元素是通过指定的分隔符进行分隔的。如果省略该参数,则使用逗号作为分隔符。
let arr = ["a", 1, "b", 2]; console.log(arr.join()) // "a,1,b,2" console.log(arr.join("-")) // "a-1-b-2" console.log(arr) // ["a", 1, "b", 2]
9.Array.toString()
-+-将数组作为字符串返回,数组中的元素之间用逗号分隔和arr.join()一个效果
let arr = [1, 2, 3, 4, 5]; console.log(arr.toString())// 1,2,3,4,5
10.Array.forEach(fn, thisValue) thisValue可传可不传,决定在fn用this指向
-+-对数组中的每个元素运行给定函数。这个方法没有返回值。这里fn是可以传3个参数function(currentValue:必传当前元素, index:可选当前元素的索引值, arr:可选当前元素所属的数组对象)
let myArr = [1,5,8] myArr.forEach((v,i,arr)=>{ console.log(v,i,arr) }) //1 0 [1, 5, 8] //5 1 [1, 5, 8] //8 2 [1, 5, 8]
加上thisValue看一下
本以为是应该把 newObj打印出来,没想到居然把window打印出来了,这是为什么呢,原来是ES6里的箭头函数this指向问题:作为方法的箭头函数this指向全局window对象
改成正常的匿名函数看一下
这里要想使用thisValue还不能用箭头函数啊
11.Array.map()
-+-对数组中的每个元素运行给定函数,返回每次函数调用的结果组成的数组。
传参和forEach一样:Array.map(function(currentValue,index,arr), thisValue),唯一区分就是,map会返回每次函数调用的结果组成的数组
let myArr = [1,5,8] myArr.forEach((v,i,arr)=>{ console.log(v,i,arr) }) //1 0 [1, 5, 8] //5 1 [1, 5, 8] //8 2 [1, 5, 8] //[undefined, undefined, undefined] 在循环执行结束,把每次返回的undefined组成个数组返回了
这里我们再来看一个动态图,更形象一点👇
12.Array.filter()
-+-对数组中的每个元素运行给定函数,返回该函数会返回 true 的元素组成的数组,传参和forEach一样:array.filter(function(currentValue,index,arr), thisValue)
let arr = [1, 2, 3, 4, 5] let bigNum = value => value > 3 let newArr = arr.filter(bigNum) console.log(newArr) // [4, 5] 满足条件的元素返回为一个新的数组
13.Array.every()
-+-对数组中的每个元素运行给定函数,如果该函数对每个元素都返回 true ,则返回 true,就是检测数组中的每个元素是否都符合条件。传参和forEach一样:array.every(function(currentValue,index,arr), thisValue)
let arr = [1, 2, 3, 4] let isAllBig3 = value => value > 3 let isAllSmall8 = value => value < 8 console.log(arr.every(isAllBig3)) //false 不是所有都大于3 console.log(arr.every(isAllSmall8)) //true 是所有都小于8
14.Array.some()
-+-对数组中的每个元素运行给定函数,如果任一元素返回 true ,则返回 true,如果返回了true , 循环结束,剩余的元素不会再执行检测。传参和forEach一样:array.some(function(currentValue,index,arr),thisValue)
let arr= [1, 2, 3] let ishave3 = value => value == 3 let ishave6 = value => value == 6 console.log(arr.some(ishave3)) // true arr里有3 console.log(arr.some(ishave6)) // false arr里没有6
15.Array.reduce()
-+-将数组元素计算为一个值(从左到右)。array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
total:初始值是数组第一个值,后面会赋值为每次循环返回的值
currentValue:初始值是数组第二个值,后面依次第三个...到最后一个
注意:该方法只循环arr.length-1次
所以我们通常用它来计算一个数组元素之和
let arr = [1, 2, 3, 4] let add = (a, b) => a + b console.log(arr.reduce(add)) // 10
16.Array.reduceRight()
-+-将数组元素计算为一个值(从右到左)。和上面的方法功能一样,只是循环正好相反从最后一个元素开始
17.Array.sort()
-+-如果不传参数按照字母顺序对数组排序(默认排序顺序是根据字符串UniCode码),支持传入指定排序方法的函数作为参数:arr.sort(fn(secondValue, firstValue))
先看最简单的用法:
let arr = ["dfc", "cf", "lol", "anf"] console.log(arr.sort()); // ["anf", "cf", "dfc", "lol"] console.log(arr) // ["anf", "cf", "dfc", "lol"] 该方法会改变原始数组
其实sort底层是封装了排序算法的,V8 引擎 sort
函数只给出了两种排序 InsertionSort
和 QuickSort
,数量小于10的数组使用 InsertionSort
,比10大的数组则使用 QuickSort
。点击githubV8-Arrray.js源码地址
底层源码有兴趣的童鞋可以去研究研究,下面我们来看一下如何利用sort()的排序来给我们平时项目开发带来便利:
- 方法一:a-b 升序排列
let arr = [4, 2, 3, 6, 9, 1] console.log(arr.sort((a, b)=> a-b)) // [1, 2, 3, 4, 6, 9]
- 方法二:b-a 降序排列
let arr = [4, 2, 3, 6, 9, 1] console.log(arr.sort((a, b)=> b-a)) // [9, 6, 4, 3, 2, 1]
- 方法三:对于复杂的数据数组,我们可以封装属于自己排序方法
let students = [ {name: "tom", age: 18}, {name: "jack", age: 26}, {name: "rose", age: 20} ] let sortByAge = (a, b) => a.age - b.age students.sort(sortByAge) /* 最后输出 [{name: "tom", age: 18}, {name: "rose", age: 20}, {name: "jack", age: 26}] */
- 方法四:其实我们还可以写的再灵活一点,更低耦合点
// 先想一下如果还有学生身高数据,要我们按身高来进行排序,如果按上面那种写法 // 我们得封装两个方法,如果以后还有更多的属性,这样是不是很麻烦 // 看下面↓ let students = [ {name: "tom", age: 18, height: 177}, {name: "jack", age: 26, height: 170}, {name: "rose", age: 20, height: 166} ] let sortBy = (attr) => {return (a, b)=> a[attr] - b[attr]} students.sort(sortBy("height")) /*输出 0: {name: "rose", age: 20, height: 166} 1: {name: "jack", age: 26, height: 170} 2: {name: "tom", age: 18, height: 177} */ students.sort(sortBy("age")) /*输出 0: {name: "tom", age: 18, height: 177} 1: {name: "rose", age: 20, height: 166} 2: {name: "jack", age: 26, height: 170} */
18.Array.reverse()
-+-反转数组的元素顺序。会改变原始数组
let arr = [11, 12, 14, 13] console.log(arr.reverse()) // [13, 14, 12, 11] console.log(arr) // [13, 14, 12, 11]
19.Array.find()
-+-对数组中的每个元素运行给定函数,在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。如果没有符合条件的元素返回 undefined
传参:array.find(function(currentValue, index, arr),thisValue)
let arr = [1, 2, 3, 5, 7] let big3 = a => a>3 console.log(arr.find(big3)) // 5 console.log(arr) // [1, 2, 3, 5, 7]
20.Array.findIndex()
-+-返回符合传入测试(函数)条件的数组元素索引。之后的值不会再调用执行函数。如果没有符合条件的元素返回 -1
let arr = [1, 2, 3, 5, 7] let big3 = a => a>3 console.log(arr.findIndex(big3)) // 3 console.log(arr) // [1, 2, 3, 5, 7]
21.Array.includes()
-+-判断一个数组是否包含一个指定的值。如果是返回 true,否则false。语法:arr.includes(searchElement, fromIndex)
[1, 2, 3].includes(2); // true [1, 2, 3].includes(4); // false [1, 2, 3].includes(3, 3); // false [1, 2, 3].includes(3, -1); // true [1, 2, NaN].includes(NaN); // true
22.Array.indexOf()
-+-返回第一个与给定参数相等的数组元素的索引,没有找到则返回 -1。语法:array.indexOf(item,start),start选填:从下标这(包括该元素)之后的所有元素
let arr = ["aa", "bb", "cc", "dd"] console.log(arr.indexOf("bb")) // 1 console.log(arr.indexOf("bb", 2)) // -1
23.Array.lastIndexOf()
-+-返回在数组中搜索到的与给定参数相等的元素的索引里最大的值,没有找到返回-1。语法:array.lastIndexOf(item,Index),index选填:指下标在这(包括该元素)之前的所有元素
let arr = ["aa", "bb", "cc", "dd", "bb"] console.log(arr.lastIndexOf("bb")) // 4 console.log(arr.lastIndexOf("bb", 2)) // 1
24.Array.isArray()
-+- 判断对象是否为数组。如果对象是数组返回 true,否则返回 false。
let obj = {} let arr = [] Array.isArray(obj) // false Array.isArray(arr) // true
25.Array.valueOf()
-+-返回数组对象的原始值。
let arr = [1,2,3] console.log(arr.valueOf()) // [1, 2, 3]
26.Array.entries()、27.Array.keys()、28.Array.values()
-+-ES6 提供三个新的方法: entries() , keys() 和 values() 用于遍历数组。它们都返回一个遍历器对象,可以用 for...of 循环进行遍历,唯一的区别是 keys() 是对键名的遍历、 values() 是对键值的遍历, entries() 是对键值对的遍历。
let arr = ["a", "b", "c"] let item = arr.entries() console.log(item.next().value) // [0, "a"] console.log(item.next().value) // [1, "b"] console.log(item.next().value) // [2, "c"] console.log(item.next().value) // undefined let ikey = arr.keys() console.log(ikey.next().value) // 0 console.log(ikey.next().value) // 1 console.log(ikey.next().value) // 2 console.log(ikey.next().value) // undefined let ivalue = arr.values() console.log(ivalue.next().value) // a console.log(ivalue.next().value) // b console.log(ivalue.next().value) // c console.log(ivalue.next().value) // undefined
29.Array.flat(num)
-+-用于将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原数组没有影响。num:表示拉几层的嵌套数组,如果不确定可以写Infinity,这样不管多少层都可以
[1, 2, [3, 4]].flat() // [1, 2, 3, 4] [1, 2, [3, [4, 5]]].flat() // [1, 2, 3, [4, 5]] [1, 2, [3, [4, 5]]].flat(2) // [1, 2, 3, 4, 5] [1, [2, [3]]].flat(Infinity) // [1, 2, 3] // 如果原数组有空位,flat()方法会跳过空位。 [1, 2, , 4, 5].flat() // [1, 2, 4, 5]
30.Array.flatMap()
-+-对原数组的每个成员执行一个函数,相当于执行map(),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
[2, 3, 4].flatMap((x) => [x, x * 2]) // [2, 4, 3, 6, 4, 8]
31.Array.fill()
-+-用于将一个固定值替换数组的元素,语法:array.fill(value, start, end)
let arr = ["a", "b", "c", "d", "e"] arr.fill("dd") console.log(arr) // ["dd", "dd", "dd", "dd", "dd"] arr.fill("a", 1, 3) console.log(arr) // ["dd", "a", "a", "dd", "dd"]
32.Array.copyWithin()
-+- 从数组的指定位置拷贝元素到数组的另一个指定位置中。语法:array.copyWithin(target, start, end)
target:必需。复制到指定目标索引位置。
start:可选。元素复制的起始位置。
end:可选。停止复制的索引位置 (默认为 array.length)。如果为负值,表示倒数。
let arr = ["a", "b", "c", "d", "e", "f"]; arr.copyWithin(2, 0, 2); console.log(arr) // ["a", "b", "a", "b", "e", "f"]
33.Array.toLocaleString()
-+-这方法数组基本不用了,主要操作日期对象返回一个日期,该日期使用当前区域设置并已被转换为字符串。
let arr = ["a", "b", "c"] arr.toLocaleString() // 返回空 ["a", "b", "c"].toLocaleString() // "a,b,c" new Date().toLocaleString() // "2020/3/7 上午12:26:31"
34.Array.constructor
-+-返回对象的构造函数。
[1,2,3].constructor // Array() { [native code] }
35.Array.hasOwnProperty()、36.Array.propertyIsEnumerable()、37.Array.isPrototypeOf()
这三个方法都是和原型链相关的,操作数组基本用不到
- hasOwnProperty()
let arr = ["a", "b"] arr.hasOwnProperty("a") // false arr.hasOwnProperty("0") // true
- 其实
hasOwnProperty主要是返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
看下面↓function f(){ this.a = 1; this.b = 2; this.c = function(){} } f.prototype = { d : 3, e : 4, g : function(){} } let o = new f(); o.hasOwnProperty('a'); //true o.hasOwnProperty('b'); //true o.hasOwnProperty('c'); //true o.hasOwnProperty('d'); //false o.hasOwnProperty('e'); //false o.hasOwnProperty('g'); //false o.propertyIsEnumerable('a'); //true o.propertyIsEnumerable('b'); //true o.propertyIsEnumerable('c'); //true o.propertyIsEnumerable('d'); //false o.propertyIsEnumerable('e'); //false o.propertyIsEnumerable('g'); //false
- propertyIsEnumerable()是用来检测属性是否属于某个对象的,如果检测到了,返回true,否则返回false.
-
1.这个属性必须属于实例的,并且不属于原型.
2.这个属性必须是可枚举的,也就是自定义的属性,可以通过for..in循环出来的.
只要符合上面两个要求,就会返回true;
let arr = ["a", "b", "c"] arr.propertyIsEnumerable("a") // false arr.propertyIsEnumerable("0") // true
- isPrototypeOf()用于测试一个对象是否存在于另一个对象的原型链上。数组基本用不到
到这里开始图片里的37个方法我们都试验了一遍
------------------------------good-------------------------------
另外补充ES6 还新增了 Array.of() 与 Array.from() 方法
38.Array.of()
-+-of是帮助开发者在使用 Array 构造器时避开 JS 语言的一个怪异点。调用 new Array() 构造器时,根据传入参数的类型与数量的不同,实际上会导致一些不同的结果
let items = new Array(2); console.log(items.length); // 2 console.log(items[0]); // undefined console.log(items[1]); // undefined items = new Array("2"); console.log(items.length); // 1 console.log(items[0]); // "2" items = new Array(1, 2); console.log(items.length); // 2 console.log(items[0]); // 1 console.log(items[1]); // 2 items = new Array(3, "2"); console.log(items.length); // 2 console.log(items[0]); // 3 console.log(items[1]); // "2"
这时候引入了 Array.of() 方法来解决这个问题。该方法的作用非常类似 Array 构造器,但在使用单个数值参数的时候并不会导致特殊结果。 Array.of() 方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型。
let items = Array.of(1, 2); console.log(items.length); // 2 console.log(items[0]); // 1 console.log(items[1]); // 2 items = Array.of(2); console.log(items.length); // 1 console.log(items[0]); // 2 items = Array.of("2"); console.log(items.length); // 1 console.log(items[0]); // "2"
39Array.form()
-+-form()方法用于通过拥有 length 属性的对象或可迭代的对象来返回一个数组。如果对象是数组返回 true,否则返回 false。
Array.from("abcdef"); // ["a", "b", "c", "d", "e", "f"]
---------------------结尾总结---------------------------
都是些简单方法总结我居然写了一天,如有错误的地方望大家及时指正😂
来源:https://www.cnblogs.com/bobo1/p/12423516.html