Array的方法简单整理
[[toc]]
快速生成一个数组
Array.from(Array(100), (key, index) => index);
[...new Array(100).keys()]
Array(3).fill('');
new Array(10).fill({}).map((item)=>{ return { title:"掘金会员", createtime:"2020-05-03", state:1, price:19.8, timeNum:12, userName:"虎克小哥哥", age:18, city:"上海" } })
let arr = []; (function dfs(i) { if (i < 100) { arr.push(i); dfs(++i); } }(0));
Array(100).join(",").split(",").map((key,index)=> index)
Array.apply(null,Array(100)).map((key,index)=>index)
|
some() & every()
every()与some()方法都是JS中数组的迭代方法。
some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true;some一直在找符合条件的值,一旦找到,则不会继续迭代下去。
every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true;every从迭代开始,一旦有一个不符合条件,则不会继续迭代下去。
reduce()
arr.reduce(function(Accumulator,CurrentValue,CurrentIndex,SourceArray){ ... }, init);
|
var arr = [3,9,4,3,6,0,9];
var sum = arr.reduce(function (prev, cur) { return prev + cur; },0);
var max = arr.reduce(function (prev, cur) { return Math.max(prev,cur); });
Math.max(...arr);
var newArr = arr.reduce(function (prev, cur) { prev.indexOf(cur) === -1 && prev.push(cur); return prev; },[]);
|
isArray()
Array.isArray() 用于确定传递的值是否是一个 Array。
Array.isArray([1, 2, 3]);
Array.isArray({foo: 123});
let dom1 = document.getElementsByClassName('token') Array.isArray(dom1); Array.isArray([...dom1]); Array.isArray(Array.from(dom1));
|
Array.isArray 实现
Array.myIsArray = function(o) { return Object.prototype.toString.call(Object(o)) === '[object Array]'; };
console.log(Array.myIsArray([]));
|
slice()
请注意: 该方法并不会修改数组
,而是返回一个子数组。如果想删除数组中的一段元素,应该使用方法 Array.splice()。
- arr.slice(begin ,end?)
- (包含 begin,但不包含 end)。
- slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
console.log(animals.slice(2, 4));
console.log(animals.slice(1, 5));
|
Array.prototype.slice = function(start,end){ var result = new Array(); start = start || 0; end = end || this.length; for(var i = start; i < end; i++){ result.push(this[i]); } return result; }
|
splice()
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。
此方法会改变原数组
删除
第二个参数为删除的个数
var ary =[1,2,3,4,5,6]
ary.splice(1,1); ary
|
插入
var ary =[1,2,3,4,5,6] ary.splice(2, 0, "7"); ary
ary.splice(2, 0, "9",'10',11,12) ary
|
删除 & 插入
var myFish = ['angel', 'clown', 'trumpet', 'sturgeon']; myFish.splice(0, 2, 'parrot', 'anemone', 'blue'); myFish
|
filter() 实现
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
注意: filter() 不会改变原始数组
。
注意: filter() 不会对空数组进行检测。
语法
array.filter(function(currentValue,index,arr), thisValue)
Array.prototype.selfFilter = function(callback, context) { if (this === null) { throw new TypeError( "Array.prototype.reduce" + "called on null or undefined" ); } if (typeof callback !== "function") { throw new TypeError(callback + " is not a function"); } let aArr = Array.prototype.slice.call(this); let _len = aArr.length; let aFArr = []; for (let i = 0; i < _len; i++) { if (!aArr.hasOwnProperty(i)) { continue; } callback.call(context, aArr[i], i, this) && aFArr.push(aArr[i]); } return aFArr; };
|
所有的数组方法集合
改变原数组的方法:
pop():移除数组末尾的最后一个元素,并返回该元素的值。 push():向数组末尾添加一个或多个元素,并返回新数组的长度。 shift():移除数组的第一个元素,并返回该元素的值。 unshift():在数组的开头添加一个或多个元素,并返回新数组的长度。 splice():向/从数组中添加/删除项目,然后返回被删除的项目。 reverse():颠倒数组中元素的顺序。 sort():对数组的元素进行排序,并返回排序后的数组。 fill():使用一个固定值填充数组的所有元素。 copyWithin():从数组的指定位置拷贝元素到数组的另一个指定位置。 set() (TypedArray):用于通过拷贝数组或者数值来填充 TypedArray。
|
不改变原数组的方法:
concat():连接两个或多个数组,并返回一个新数组。 slice():从已有的数组中返回选定的元素。 join():把数组中的所有元素放入一个字符串。 indexOf():搜索数组中的元素,并返回它所在的位置索引,如果没有找到则返回 -1。 lastIndexOf():从数组的末尾开始搜索元素,并返回它所在的位置索引,如果没有找到则返回 -1。 includes():判断数组是否包含一个指定的值,如果是返回 true,否则返回 false。 every():检查数组中的所有元素是否都符合指定条件。 some():检查数组中是否至少有一个元素符合指定条件。 filter():创建一个新数组,其中包含所有通过所提供函数实现的测试的元素。 map():创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。 forEach():对数组中的每个元素执行提供的函数。 reduce():对数组中的每个元素执行一个累积器函数(从左到右),将其结果汇总为单个返回值。 reduceRight():对数组中的每个元素执行一个累积器函数(从右到左),将其结果汇总为单个返回值。 find():返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。 findIndex():返回数组中满足提供的测试函数的第一个元素的索引,否则返回 -1。
|
Map + Set + WeakMap + WeakSet
const set = new Set();
// 添加值 set.add(1); set.add(2); set.add(3); set.add(3); // 重复值不会被添加
// 检查是否存在某个值 console.log(set.has(1)); // true console.log(set.has(4)); // false
// 获取 Set 的大小 console.log(set.size); // 3
// 删除值 set.delete(2); console.log(set.has(2)); // false
// 遍历 Set 的值 for (const value of set.values()) { console.log(`Value: ${value}`); }
for (const key of set.keys()) { console.log(`Key: ${key}`); }
for (const [key, value] of set.entries()) { console.log(`Entry: ${key} = ${value}`); }
set.forEach((value) => { console.log(`ForEach Value: ${value}`); });
set.clear(); console.log(set.size); // 0
// WeakSet // WeakSet 是 JavaScript 中的一种集合类型,它与 Set 类似,但有一些关键区别和限制。WeakSet 只能存储对象类型的值,并且对这些对象持有弱引用,这意味着如果没有其他引用指向这些对象,它们可以被垃圾回收机制回收。 const weakSet = new WeakSet(); const obj1 = {}; const obj2 = {}; const obj3 = {};
weakSet.add(obj1); weakSet.add(obj2);
console.log(weakSet.has(obj1)); console.log(weakSet.has(obj3));
weakSet.delete(obj2); console.log(weakSet.has(obj2));
obj1 = null; obj3 = null;
const map = new Map();
map.set('key1', 'value1'); map.set('key2', 'value2'); map.set('key3', 'value3');
console.log(map.get('key1'));
console.log(map.has('key2'));
map.delete('key2'); console.log(map.has('key2'));
console.log(map.size);
for (const key of map.keys()) { console.log(`Key: ${key}`); }
for (const value of map.values()) { console.log(`Value: ${value}`); }
for (const [key, value] of map.entries()) { console.log(`Entry: ${key} = ${value}`); }
map.forEach((value, key) => { console.log(`${key}: ${value}`); });
map.clear(); console.log(map.size);
const weakMap = new WeakMap(); const obj1 = {}; const obj2 = {}; const obj3 = {};
weakMap.set(obj1, 'value1'); weakMap.set(obj2, 'value2'); weakMap.set(obj3, 'value3');
console.log(weakMap.get(obj1));
console.log(weakMap.has(obj2));
weakMap.delete(obj2); console.log(weakMap.has(obj2));
console.log(weakMap.get(obj2));
obj1 = null; obj3 = null;
|
Set
和 Map
区别
Set
和 Map
在 JavaScript 中确实有许多相似之处,但它们在用途和行为上有显著的区别。下面是对两者的详细比较:
相似之处
- 集合类型:
Set
和 Map
都是集合类型,用于存储唯一的元素。
- 内置方法:两者都有类似的方法来操作其元素,例如添加、删除、查找、清空等。
- 迭代器:都提供了迭代器方法(如
keys
、values
、entries
)用于遍历集合中的元素。
- 迭代顺序:两者都保持插入元素的顺序,因此迭代时按照插入顺序进行。
不同之处
- 存储的元素:
- Set:存储的是一组唯一的值。值可以是任何类型,包括原始值和对象。
- Map:存储的是一组键值对。键和值都可以是任何类型。
- 键和值:
- Set:每个元素即是值,没有键的概念。
- Map:每个元素是一个
[key, value]
对,键和值都可以是任意类型。
- 方法:
- Set:
add(value)
:添加一个值到集合中。
has(value)
:检查集合中是否存在某个值。
delete(value)
:从集合中删除一个值。
clear()
:清空集合。
values()
、keys()
、entries()
、forEach()
:用于迭代集合中的值。
- Map:
set(key, value)
:添加或更新一个键值对。
get(key)
:获取与键关联的值。
has(key)
:检查集合中是否存在某个键。
delete(key)
:从集合中删除一个键值对。
clear()
:清空集合。
values()
、keys()
、entries()
、forEach()
:用于迭代集合中的键值对。
用途和使用场景
Set:
- 用于存储唯一值的集合,可以用于数组去重。
- 适用于需要快速查找唯一值的场景。
示例:
const set = new Set(); set.add(1); set.add(2); set.add(2); // 不会添加重复值 console.log(set.has(1)); // true console.log(set.size); // 2
|
Map:
- 用于存储键值对,特别适合需要基于键进行快速查找、添加和删除操作的场景。
- 适用于需要关联数据对的场景,比如字典、缓存等。
示例:
const map = new Map(); map.set('key1', 'value1'); map.set('key2', 'value2'); console.log(map.get('key1')); console.log(map.has('key2')); console.log(map.size);
|
Object
和 Map
区别
Map 和普通的对象(Object)在存储键值对的基本功能上有些类似,但它们在设计目的和使用场景上有一些重要的区别和优势:
区别和优势
键的类型:
Object:键必须是字符串或者 Symbol 类型。如果键不是字符串或者 Symbol,则会被转换为字符串。
Map:键可以是任意类型,包括基本类型(如字符串、数字、布尔值)、对象和函数等。这使得 Map 在处理复杂的键值关系时更加灵活。
插入顺序:
Object:对象的属性在添加时不保证任何顺序,遍历时的顺序可能不同于添加时的顺序。
Map:保持键值对的插入顺序,迭代时按照插入顺序进行,这点与 Array 类似。
性能:
Object:对象适合于存储简单的键值对,并且在属性较少、直接量赋值的情况下性能很好。
Map:Map 在处理大量数据、频繁增删键值对、需要快速查找特定键等方面通常比对象更高效。
可迭代性:
Object:需要额外处理才能进行迭代,比如使用 Object.keys(obj)、Object.values(obj) 或者 Object.entries(obj)。
Map:直接支持迭代器接口,可以通过 for…of、forEach 等方式遍历键值对。
内存管理:
Object:作为引用类型,对象属性被引用时会增加对象的引用计数,可能导致对象不被及时回收。
Map:对键的引用是弱引用,这意味着即使 Map 持有对象的引用,该对象也可以被垃圾回收。
数组去重
function unique(arr, fn) { return arr.reduce(fn, []); } unique([1,2,3,3,2,1,15,6], function(arr, item) { !arr.includes(item) && arr.push(item); return arr; });
|
forEach中return有效果吗?如何中断forEach循环?
在forEach中用return不会返回,函数会继续执行。
let nums = [1, 2, 3]; nums.forEach((item, index) => { return; })
|
中断方法:
(1). 使用try监视代码块,在需要中断的地方抛出异常。
(2). 官方推荐方法(替换方法):用every和some替代forEach函数。every在碰到return false的时候,中止循环。some在碰到return true的时候,中止循环
js将多维数组转换为一维数组
let arr = [1, 2, 3, 4, 5, [6, 7, 8, [9, 10, 11, 12, [13, 14, 15, 16]]]] console.log(arr.join())
let newArr = arr.join().split(',') let newArr = arr.toString().split(',') let newArr = (arr + '').split(',')
console.log(newArr)
|
递归
let arr = [1, 2, 3, 4, 5, [6, 7, 8, [9, 10, 11, 12, [13, 14, 15, 16]]]] let newArr = [] function arrConversion (arr) { for (let i = 0; i < arr.length; i++) { if (Array.isArray(arr[i])) { arrConversion(arr[i]) } else { newArr.push(arr[i]) } } } arrConversion(arr) console.log(newArr)
|
循环
function flatArray(ary) { let result = []; while (ary.length) { let item = ary.shift(); if (Array.isArray(item)) { ary.unshift(...item); } else { result.push(item); } } return result; }
|
flat
console.log([1 ,[2, 3]].flat());
console.log([1, [2, [3, [4, 5]]]].flat(2));
console.log([1, [2, [3, [4, 5]]]].flat(Infinity));
|
正则
let ary = [1, [2, [3, [4, 5]]], 6]; let str = JSON.stringify(ary); let result = str.replace(/(\[|\])/g, '').split(','); console.log( result )
|
数组快速随机排序
let arr =[1,2,3,4];
let t; for(let i = 0;i < arr.length; i++){ let rand = parseInt(Math.random()*arr.length); t = arr[rand]; arr[rand] =arr[i]; arr[i] = t; }
arr.sort(()=>{ return Math.random() - 0.5; })
|
数组排序
function selectSort(arr) { var len = arr.length; for(let i = 0 ;i < len - 1; i++) { for(let j = i ; j<len; j++) { if(arr[j] < arr[i]) { [arr[i],arr[j]] = [arr[j],arr[i]]; } } } return arr }
function quickSort(arr) { if(arr.length <= 1) { return arr; } var left = [], right = [], current = arr.splice(0,1); for(let i = 0; i < arr.length; i++) { if(arr[i] < current) { left.push(arr[i]) } else { right.push(arr[i]) } } return quickSort(left).concat(current,quickSort(right)); }
|
判断数组中是否有重复元素
let arr = [1,2,3,4,4]
function isRepeat(arr) { let flag = false; for(var i = 0; i < arr.length; i++) { for(var j = i + 1; j < arr.length; j++) { if (arr[i] === arr[j]) { flag = true; break; } } } return flag }
function isRepeat(arr) { let obj = {} for(var i = 0; i < arr.length; i++) { obj[arr[i]] = arr[i] } return Object.keys(obj).length !== arr.length }
|
求第一个数组中没有第二个数组中部分的值
差集
function differenceSecond(ary1,ary2){ let arr = [] ary1.filter((item)=>{ !ary2.includes(item)&&arr.push(item) }) return arr }
function differenceSecond(m, n) { let a = [...m, ...n]; let b = n; let aHasNaN = m.some(function(v) { return isNaN(v); }); let bHasNaN = n.some(function(v) { return isNaN(v); }); let difference = a .filter(function(v) { return b.indexOf(v) == -1 && !isNaN(v); }) .concat( b.filter(function(v) { return a.indexOf(v) == -1 && !isNaN(v); }) ) .concat(aHasNaN ^ bHasNaN ? [NaN] : []); return difference; }
|
简单实现判断两个数组是不是相同
在 JavaScript 中,可以通过以下步骤来实现这一点:
检查数组的长度是否相同。
如果长度相同,逐个比较对应位置上的元素。
下面是一个示例函数,用于判断两个数组是否相同:
function arraysAreEqual(arr1, arr2) { if (arr1.length !== arr2.length) { return false; }
for (let i = 0; i < arr1.length; i++) { if (arr1[i] !== arr2[i]) { return false; } }
return true; }
const array1 = [1, 2, 3, 4]; const array2 = [1, 2, 3, 4]; const array3 = [1, 2, 3, 5];
console.log(arraysAreEqual(array1, array2)); console.log(arraysAreEqual(array1, array3));
|
判断两个对象是否相同
要判断两个对象是否相同,需要进行深度比较,因为直接比较对象的引用(使用 === 或 ==)只会检查它们是否引用同一个内存地址,而不是检查它们的内容是否相同。
function deepEqual(obj1, obj2) { if (obj1 === obj2) { return true; }
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) { return false; }
const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) { return false; }
for (let key of keys1) { if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) { return false; } }
return true; }
const obj1 = { a: 1, b: { c: 2 } }; const obj2 = { a: 1, b: { c: 2 } }; const obj3 = { a: 1, b: { c: 3 } };
console.log(deepEqual(obj1, obj2)); console.log(deepEqual(obj1, obj3));
|
参考文档
MDN ARRAY