关于JS里的数组和对象的日常使用

关于数组

一些关于js数组的基础知识点,只是日常使用,不攻坚。如有什么错误,欢迎大家指正😄

Array.prototype.map()

返回一个新的Array,每个元素为调用func的结果。新数组的长度和原来的是一样的,他只不过是逐一对原来数据里的每个元素进行操作,并且返回函数处理后的结果。
语法: var newArray = arr.map(function callback(currentValue, index, array){ //对每个元素的处理 })
参数 callback:用来生成新数组用的函数。 callback的参数: currentValue:当然正在处理的元素 index:正在处理元素的索引 array:调用map方法的数组(就是.map()前面的也就是arr)

var a = [1,2,3,4];
var newa = a.map(function(x){
 return x > 1;
});
console.log(newa,a); 
//newa : [false, true, true, true]    //a: 1 2 3 4

var b = [1,2,3,4];
var newb = a.map((item)=>{
    return item+1
});
console.log(newb,b); //newb : [2, 3, 4, 5] //b: [1, 2, 3, 4]

var b = [1,2,3,4];
b.map((item)=>{

    return item+1
});
console.log(b); //b: [1, 2, 3, 4]

var b = [1,2,3,4];
var c= []
b.map((item)=>{
    c.push(item)
});
console.log(c); //c: [1, 2, 3, 4]  此方法可以多个数组 修改 但是会生成数组[undefined, undefined, undefined, undefined]

Array.prototype.filter()

创建一个新数组,其结果是调用一个函数过滤后的所有符合条件的元素。 筛选条件,把数组符合条件的放在新的数组里面返回。新数组和原来的数组长度不一定一样。注意当对象数组使用filter时找到的是所有符合条件的item的数组
语法 var newArray = arr.filter(function callback(curValue, index , array){ //函数代码 });
参数 callback: 调用的过滤函数 curValue: 当前元素 index: 当前元素的索引 array:调用filter的数组

var a = [1,2,3,4];
var newa = a.filter(function(x){
 return x > 1;
});
console.log(newa,a); 
//newa : 2 3 4    //a: 1 2 3 4

基本用法就是以上那些 因为都是对元素的遍历,所以我猜想 如果把map中调用的函数换成filter里面的过滤函数是否能得到相同的结果呢。 于是

var a = [1,2,3,4];
var newa = a.map(function(x){
 return x > 1;
});
console.log(newa,a); 
//newa :false true true true     //a: 1 2 3 4

可以看出来newa 的到的并不是数字,它们只是对当前元素调用函数后(x是否大于1)的结果。而filter 会将结果为true的数组存到新的数组里面。

Array.prototype.find()

find 查找 返回第一个符合条件的结果,注意返回的是符合条件的item对象。

var data= [{name:"Jackie",id: "122"}, 
           {name:"Tony2",id: "121"}, 
           {name:"Tony",id: "121"}];
console.log(data.find(user=>user.id==='121')) //{name: "Tony2", id: "121"}

Array.prototype.findIndex()

findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。

如果没有符合条件的元素返回 -1
findIndex() 对于空数组,函数是不会执行的
findIndex() 并没有改变数组的原始值

var data= [{name:"Jackie",id: "122"}, 
           {name:"Tony2",id: "121"}, 
           {name:"Tony",id: "121"}];
console.log(data.findIndex(user=>user.id==='121')) //1

Array.prototype.from()

from() 方法用于通过拥有 length 属性的对象或可迭代的对象来返回一个数组。
如果对象是数组返回 true,否则返回 false。

var myArr = Array.from("RUNOOB");//通过字符串创建一个数组:
console.log(myArr)// ["R", "U", "N", "O", "O", "B"]

var setObj = new Set(["a", "b", "c"]);
var objArr = Array.from(setObj);
console.log(objArr)//["a", "b", "c"]

Array.prototype.includes()

includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

let site = ['runoob', 'google', 'taobao']; 
site.includes('runoob');  // true  
site.includes('baidu');  // false

Array.prototype.indexOf()

indexOf() 方法可返回数组中某个指定的元素位置。
该方法将从头到尾地检索数组,看它是否含有对应的元素。开始检索的位置在数组 start 处或数组的开头(没有指定 start 参数时)。如果找到一个 item,则返回 item 的第一次出现的位置。开始位置的索引为 0。
如果在数组中没找到指定元素则返回 -1。
提示如果你想查找字符串最后出现的位置,请使用 lastIndexOf() 方法。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");//2

Array.prototype.join()

join() 方法用于把数组中的所有元素转换一个字符串。
元素是通过指定的分隔符进行分隔的。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var energy = fruits.join();//Banana,Orange,Apple,Mango

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var energy = fruits.join(" and ");//Banana and Orange and Apple and Mango

Array.prototype.pop()

pop() 方法用于删除数组的最后一个元素并返回删除的元素。
**注意:**此方法改变数组的长度!

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.pop();//Banana,Orange,Apple

Array.prototype.shift()

shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
注意: 此方法改变数组的长度!

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.shift()//Orange,Apple,Mango

Array.prototype.push()

push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
注意: 新元素将添加在数组的末尾。
注意: 此方法改变数组的长度。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi")//Banana,Orange,Apple,Mango,Kiwi

Array.prototype.unshift()

unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
注意: 新元素将添加在数组的开头
注意: 该方法将改变数组的数目

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Kiwi")//Kiwi,Banana,Orange,Apple,Mango

Array.prototype.slice()

slice() 方法可从已有的数组中返回选定的元素。
slice()方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
注意: slice() 方法不会改变原始数组。

var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(1,3);//Orange,Lemon

Array.prototype.splice()

splice() 方法用于添加或删除数组中的元素。
**注意:**这种方法会改变原始数组。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(0,1);//Orange,Apple,Mango
fruits.splice(2,0,"Lemon","Kiwi");//Banana,Orange,Lemon,Kiwi,Apple,Mango

Array.prototype.toString()

toString() 方法可把数组转换为字符串,并返回结果。
注意: 数组中的元素之间用逗号分隔。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.toString();//Banana,Orange,Apple,Mango

Array.prototype.sort()

sort 按指定条件排序
排序顺序可以是字母或数字,并按升序或降序。
默认排序顺序为按字母升序。

var a = [1,2,3,4];
console.log(a.sort((a,b)=> a - b))//1234正向排序
console.log(a.sort((a,b)=> b - a))//4321从大到小排序

var points = [40,100,1,5,25,10];
points.sort(function(a,b){return a-b});//1,5,10,25,40,100

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();//Apple,Banana,Mango,Orange
fruits.reverse();//Orange,Mango,Banana,Apple

var data= [{name:"Jackie",id: "122"}, 
           {name:"Tony2",id: "121"}, 
           {name:"Tony",id: "120"}];
var sums = data.sort((a, b) => (a.id > b.id) ? 1 : ((b.id > a.id) ? -1 : 0))
console.log(sums)
//根据id从小到大排序:排序结果
(3) [{}, {}, {}]
0: {name: "Tony", id: "120"}
1: {name: "Tony2", id: "121"}
2: {name: "Jackie", id: "122"}
length: 3
__proto__: Array(0)

Array.prototype.reverse()

reverse() 方法反转数组中元素的顺序。
**注释:**reverse() 方法将改变原始数组。可用JSON.parse(JSON.stringify(fruits))深拷贝一份数据

var fruits = ["Banana", "Orange", "Apple", "Mango"];
console.log(fruits.reverse())//["Mango", "Apple", "Orange", "Banana"]
console.log(fruits)//["Mango", "Apple", "Orange", "Banana"]原数组被改变

Array.prototype.concat()

concat() 方法用于连接两个或多个数组。
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

var a = ["Cecilie", "Lone"]; 
var b = ["Emil", "Tobias", "Linus"]; 
var c = ["Robin"]; 
var children = a.concat(b,c);
console.log(children)//Cecilie,Lone,Emil,Tobias,Linus,Robin
var ES6children = [...a,...b,...c]//推荐使用ES6扩展字符串更好的处理合并数组

Array.prototype.forEach()

数组的每一个元素执行一次提供的函数。

var a = [1,2,3,4];
var newa = a.forEach(function(x){
 return x > 1;
});
console.log(newa,a);  //undifined  //1 2 3 4 
var a = [1,2,3,4];
var newa = a.forEach(function(x){
 console.log(x);
});
console.log(newa,a);  
//1
//2
//3
//4
//undifined  //1 2 3 4 

从上面可以看出forEach 只是让数组里面的元素执行一次函数,并不会对原数组产生影响,也不会获得新的数组

Array.prototype.reduce()

接受一个函数作为累加器,依次加上数组的当前元素。
语法 arr.reduce(callback(previousValue, currentValue, currentIndex,array),initialValue);
参数 callback:累加器函数 previousValue: 上一次调用函数后的返回值,或者是提供的初始值(initialValue) currentValue:当前数组的元素 currentIndex:当前数组元素的索引 array:调用reduce的数组 initialValue:初始值,作为第一次调用callback的第一个参数,也可不写,默认为0;

var a = [1,2,3,4];
var new = a.reduce(function(total, current){
 return total + current;
},100);
console.log(new,a);
//10   //1 2 3 4

关于reduce的作用
我们可以用reduce方法做些什么呢?
1.数组求和
reduce方法本意就是用来记录循环的累积结果,用于数组求和是最合适不过了。比如我们要求数组 [1,2,3,4] 的元素之和,用forEach你得这样写:

let total = 0;
[1, 2, 3, 4].forEach(item => total += item);
console.log(total); //10

但通过reduce方法就简单的多,我们可以这么写:

let total = [1, 2, 3, 4].reduce((accumulator, current) => accumulator += current); // 10

假设我们希望求数字90与数组 [ 1,2,3,4] 元素的和呢,那就这么写:

let total = [1, 2, 3, 4].reduce((accumulator, current) => accumulator += current, 90); // 100

2.数组去重
比如我们要将数组 [1,2,2,4,null,null] 去除掉重复项,用filter可以这样做:

let arr = [1, 2, 2, 4, null, null].filter((item, index, arr) => arr.indexOf(item) === index); // [1,2,4,null]

当然单说实现使用 new Set 更简单:

let arr = [...new Set([1, 2, 2, 4, null, null])]; // [1,2,4,null]

现在我们知道了reduce方法,其实也可以通过reduce去重,像这样:

let arr = [1, 2, 2, 4, null, null].reduce((accumulator, current) => {
    return accumulator.includes(current) ? accumulator : accumulator.concat(current);
}, []);

3.数组降维
比如我们要将二维数组 [[1,2],[3,4],[5,6]] 降维成一维数组,最简单的做法是通过flat方法,像这样:

let arr = [[1,2],[3,4],[5,6]].flat();//[1, 2, 3, 4, 5, 6]

通过reduce也挺简单,我们可以结合concat方法,像这样:

let arr = [[1,2],[3,4],[5,6]].reduce((accumulator, current)=>accumulator.concat(current),[]);//[1, 2, 3, 4, 5, 6]

那如果是个多维数组呢,reduce可以这样做:

let arr = [0,[1],[2, 3],[4, [5, 6, 7]]];
let dimensionReduction = function (arr) {
    return arr.reduce((accumulator, current) => {
        return accumulator.concat(
            Array.isArray(current) ? 
            dimensionReduction(current) : 
            current
            );
    }, []);
}
dimensionReduction(arr); //[0, 1, 2, 3, 4, 5, 6, 7]

相对而言,多维数组降维flat会更简单,当然flat存在兼容问题:

let arr = [0,[1],[2, 3],[4, [5, 6, 7]]].flat(Infinity);// [0, 1, 2, 3, 4, 5, 6, 7]

使用注意
在使用reduce方法有一点需要注意,若有初始值但数组为空,或无初始值但数组只有一项时,reduce方法都不会执行。

[].reduce(() => console.log(1), 1); //不会执行
[1].reduce(() => console.log(1)); //不执行

若数组为空且没有初始值,reduce方法报错。

[].reduce(() => console.log(1)); //报错

所以如果没有初始值,你至少得保证数组有2项才能执行;如果给了初始值,你至少得保证数组有一项才能执行。

[1, 2].reduce(() => console.log(1)); //1
[1].reduce(() => console.log(1), 1); //1

Array.prototype.some()

返回一个boolean,判断是否有元素是否符合func条件。数组里面所有的元素有一个符合条件就返回true。

const array = [1, 2, 3, 4, 5];

// checks whether an element is even
const even = (element) => element % 2 === 0;

console.log(array.some(even));
// expected output: true

Array.prototype.every()

返回一个boolean,判断每个元素是否符合func条件。数组里面所有的元素都符合才返回true。

let list = [
    {name:"aaa",age:3},
    {name:"bbb",age:4},
    {name:"ccc",age:5},
];
 var eve= list.every(function(item){
   return item.age > 4
})
console.log(eve)//false;
var some = list.some(function(item){
   return item.age > 4
})
console.log(some)//true

原始for循环

var arr = [1,2,3,4]
for(var i = 0 ; i< arr.length ; i++){
	console.log(arr[i])
}
1234

for循环中可以使用return、break等来中断循环
for…in
循环遍历的值是数据结构的键名

let obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o in obj) {
    console.log(o)    //遍历的实际上是对象的属性名称 a,b,c,d
    console.log(obj[o])  //这个才是属性对应的值1,2,3,4
}

总结一句: for in也可以循环数组但是特别适合遍历对象
for…of
它是ES6中新增加的语法,用来循环获取一对键值对中的值
循环一个数组

let arr = ['China', 'America', 'Korea']
for (let o of arr) {
    console.log(o) //China, America, Korea
}
 
循环一个普通对象(报错)
let obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o of obj) {
    console.log(o)   //Uncaught TypeError: obj[Symbol.iterator] is not a function
}

一个数据结构只有部署了 Symbol.iterator 属性, 才具有 iterator接口可以使用 for of循环。例子中的obj对象没有Symbol.iterator属性 所以会报错。
哪些数据结构部署了 Symbol.iteratoer属性了呢?
数组 Array

Map
Set
String
arguments对象
Nodelist对象, 就是获取的dom列表集合
如果想让对象可以使用 for of循环怎么办?使用 Object.keys() 获取对象的 key值集合后,再使用 for of
let obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o of Object.keys(obj)) {
    console.log(o) // a,b,c,d
}

或者使用内置的Object.values()方法获取对象的value值集合再使用for of

let obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o of Object.values(obj)) {
    console.log(o) // 1,2,3,4
}

循环一个字符串

let str = 'love'
for (let o of str) {
    console.log(o) // l,o,v,e
}

循环一个Map

let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);

for (let [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3
for (let entry of iterable) {
  console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]

循环一个Set

let iterable = new Set([1, 1, 2, 2, 3, 3]);

for (let value of iterable) {
  console.log(value);
}
// 1
// 2
// 3

关于对象Object

1. Object.assign()

Object.assign() 用于将所有可枚举属性的值从一个或多个源对象,复制到目标对象。
语法:Object.assign(obj, …sources)

obj:目标对象
sources:源对象,可以是多个
返回目标对象

复制一个对象
const obj = { a: 1 }
const copy = Object.assign({}, obj)
console.log(copy); // { a: 1 }

合并对象
const obj1 = { a: 1, b: 2 }
const obj2 = { b: 3, c: 4 }
const obj3 = { c: 5, d: 6 }

const obj = Object.assign(obj1, obj2, obj3)
console.log(obj)  // {a: 1, b: 3, c: 5, d: 6}

注:如果目标对象与源对象有同名属性,则后面的属性会覆盖前面的属性;如果多个源对象有同名的属性,则后面的源对象会覆盖前面的。
对象的深拷贝
通过 Object.assign() 我们可以很快的实现对象的复制,然而这只是一个浅拷贝,因为 Object.assign() 方法拷贝的是可枚举属性值,如果源对象的属性值是一个对象的引用,那么该方法也只会复制其引用。
// 浅拷贝

let o1 = {
    a: 0,
    b: { c: 0 }
}
const o2 = Object.assign({}, o1)
o1.b.c = 1
console.log(o2.c) // 1

那么,我们怎么实现一个对象的深拷贝呢?
如果不考虑保留内置类型,最快速的方法是通过JSON.stringify() 将该对象转换为 json 字符串表现形式,然后再将其解析回对象。
// 深拷贝:方法一

let obj1 = { a: 0 , b: { c: 0}}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj1.a = 4
obj1.b.c = 4
console.log(obj1) // { a: 4, b: { c: 4}} 
console.log(obj2) // { a: 0, b: { c: 0}}

还可以通过递归的方法实现深拷贝
// 深拷贝:方法二

const obj = {
    name: 'andy',
    age: 18,
    info: {
        gender: 'male',
        schoole: 'NEWS'
    },
    color: ['pink', 'yellow']
}
function deepCopy(obj){
    let o = {}
    for(let k in obj) {  //  此处的for...in方法可以使用Object.keys(obj).map(k =>{....}) 替换
        // 1.获取属性值
        var item = obj[k];
        // 2.判断属性值属于哪种数据类型
        if(item instanceof Array) { // 是否是数组
            o[k] = []
            deepCopy(o[k], item)
        } else if(item instanceof Object) { // 是否是对象
            o[k] = {}
            deepCopy(o[k], item)
        } else { // 简单数据类型
            o[k] = item
        }
    }
    return o
}
const newObj = deepCopy(obj)
console.log(newObj)

其实还可以用lodash.cloneDeep来实现

import _ from 'lodash'
var obj = {id:1,name:{a:'xx'},fn:function(){}};
var obj2 = _.cloneDeep(obj);
obj2.name.a = 'obj2';
console.log(obj,obj2)


var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);//此处为深拷贝
console.log(deep[0] === objects[0]);
// => false
var objects = [{ 'a': 1 }, { 'b': 2 }];
var shallow = _.clone(objects);//此处为浅拷贝
console.log(shallow[0] === objects[0]);
// => true

2. Object.create()

Object.create() 创建一个新对象
语法:Object.create(proto)
proto:新创建对象的原型对象
返回一个新对象

使用:

const person = {
    isHuman: false,
    printIntroduction: function() {
        console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
    }
}
const me = Object.create(person)
console.log(me) // {}
me.name = 'Matthew' // "name" is a property set on "me", but not on "person"
me.isHuman = true // inherited properties can be overwritten
me.printIntroduction() // My name is Matthew. Am I human? true
console.log(me.__proto__ === person) //true
// 通过new Object()方式创建对象
const me = new Object(person)
console.log(me) // {isHuman: false, printIntroduction: ƒ}
me.name = 'Matthew'
me.isHuman = true
console.log(me) // {isHuman: true, name: "Matthew", printIntroduction: ƒ}

Object.create() 可以实现对象的继承,可以通过对象实例的 proto 属性访问原型链上的属性。
new Object() 方法创建的对象,给对象原型添加属性和方法则需要通过构造函数或者类。

function Person(name, age){
    this.name=name
    this.age=age
}
Person.prototype.sayHi = function(){
    console.log(this.name)
}
let p = new Person('jack', 20)
console.log(p.sayHi()) // jack
console.log(p.__proto__ === Person.prototype) // true

3. Object.defineProperty()

Object.defineProperty() 添加或修改现有属性,并返回该对象。
语法:Object.defineProperty(obj, prop, description)

obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性,以对象形式{}书写。

value:设置属性的值,默认为 undefined
writable:值是否可以重写,true | false,默认为 false
enumerable:目标属性是否可以被枚举,true | false,默认为 false
configurable:目标属性是否可以被删除或是否可以再次修改特性,true | false,默认为 false

const obj = {
    id: 1,
    name: 'phone',
    price: '$599'
}
Object.defineProperty(obj, 'num', {
    value: 100,
    enumerable: false
})
console.log(obj) // {id: 1, name: "phone", price: "$599", num: 100}
console.log(Object.keys(obj)) // ["id", "name", "price"]

4. Object.entires()

Object.entires() 遍历并返回该对象可枚举属性的键值对数组
具体可参考:blog.csdn.net/qq_42628504…
语法:Object.entires(obj)

返回对象可枚举属性的键值对数组

const obj = {
    a: 'apple',
    b: 'bar'
}
console.log(Object.entries(obj)) // [ ['a', 'apple'], ['b', 'bar'] ]
for (const [key, value] of Object.entries(obj)) {
    console.log(`${key}: ${value}`) //"a: somestring"  "b: 42"
}
Object.entries(obj).forEach(([key, value]) => {
    console.log(`${key}: ${value}`) // "a: somestring", "b: 42"
})
  1. Object.keys()
    Object.keys() 用于获取对象自身所有可枚举的属性
    语法:Object.keys(obj)
    效果类似于 for…in
    返回一个由属性名组成的数组
const obj = {
    id: 1,
    name: 'phone',
    price: '$599',
    num: 100
}
const objKeys = Object.keys(obj);
console.log(objKeys); //['id', 'name', 'price', 'num']

const arr = ['a', 'b', 'c']
const arrKeys = Object.keys(arr)
console.log(arrKeys) //['0', '1', '2']

补充:如果只要获取对象的可枚举属性,可用Object.keys或用for…in循环(for…in循环会得到对象自身的和继承的可枚举属性,可以使用 hasOwnProperty()方法过滤掉)
6. Object.values()
Object.values() 获取对象自身所有可枚举的属性值
语法:Object.values(obj)
返回一个由属性值组成的数组

const obj = {
    id: 1,
    name: 'phone',
    price: '$599',
    num: 100
}
const objValues = Object.values(obj);
console.log(objValues); //[1, 'phone', '$599', '100']

附图:对象的所有属性和方法

关于new Set
Set 对象存储的值总是唯一的
Set 对象方法

在这里插入图片描述

方法描述add添加某个值,返回Set对象本身。clear删除所有的键/值对,没有返回值。delete删除某个键,返回true。如果删除失败,返回false。forEach对每个元素执行指定操作。has返回一个布尔值,表示某个键是否在当前 Set 对象之中。
Set 对象作用
注意* Set 对象不会改变原数组 属于Set类型

数组去重

var arr = [1,2,3,3,1,4];
[...new Set(arr)]; // [1, 2, 3, 4]
Array.from(new Set(arr)); // [1, 2, 3, 4]
[...new Set('ababbc')].join(''); // "abc" 字符串去重
new Set('ice doughnut'); //Set(11) {"i", "c", "e", " ", "d", …}

   
 arr.map( (item,index)=> {
if(newArr.indexOf(item) == -1){
   newArr.push(item);
   }
  })
let arr = [1, 2, 2, 4, null, null].filter((item, index, arr) => arr.indexOf(item) === index); // [1,2,4,null]

合并数组

arr=[1,2,3] arr1=[4,5,6]
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}
union=[...arr,...arr1]    //(6) [1, 2, 3, 4, 5, 6]
union=arr.concat(arr1)

交集 数组去掉相同

arr=[1,2,3] arr1=[1,5,3]
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}

intersect = arr.filter((item) => {
return arr1.includes( item);     //{1 3}
})
 intersect = arr.filter((item) => {
return arr1.some(ele => ele=== item);     //{1 3}
})

差集

var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var difference = new Set([...a].filter(x => !b.has(x))); // {1}

单数组去掉相同的属性 或者对象

var a=[{id:1,name:2},{id:1,name:3},{id:3,name:3}]
const concat = new Map();
a.filter((a) => !concat.has(a.id) && concat.set(a.id, 1))
 const c= new Set(); 
 a.filter((a) => !c.has(a.id) && c.add(a.id))
  //0: {id: 1, name: 2}1: {id: 3, name: 3}

遍历问题

遍历方法

map filter 都可以
注意:for in得到对象的key或数组,字符串的下标,而for of和forEach一样,是直接得到值

for…in 可遍历数组对象

以原始插入顺序访问对象的可枚举属性,包括从原型继承而来的可枚举属性。 (不遍历非枚举属性)

let obj = {
    a:123,
    b:"abc"
}
for(let pro in obj){
    console.log(pro+':' + obj[pro])
}
//a:123
//b:abc
Object.defineProperty(obj, 'num', {
    value: 100,
    enumerable: false
})
for(let pro in obj){
    console.log(pro+':' + obj[pro])
}


for…in用于遍历数组时,可以将数组看作对象,数组下标看作属性名。但用for…in遍历数组时不一定会按照数组的索引顺序。

let obj = {
    a:123,
    b:"abc"
}
let arr = [123,'abc']
for(let pro in arr){
    console.log(pro+':' + arr[pro])
}
//0:123
//1:abc

Object.prototype.protoPer2 = 2;  (obj 可以被遍历到)

for of不能遍历对象 可遍历 Set Map

for(let v of [1,2,3,4]) {
console.log(v);
};

var set = new Set();  
set.add("a").add("b").add("c").add("d");  
var map = new Map();  
map.set("a",1).set("b",2).set("c",3);  
for (let v of set) {  
    console.log(v);  
}  
console.log("--------------------");  
for(let [k,v] of map) {  
    console.log(k,v);  
} 

forEach 不遍历对象 可遍历数组 可遍历迭代

forEach方法对数组/Map/Set中的每个元素执行一次提供的函数。该函数接受三个参数:

正在处理的当前元素,对于Map元素,代表其值;
正在处理的当前元素的索引,对于Map元素,代表其键,对于Set而言,索引与值一样。
forEach()方法正在操作的数组对象。

let arr = [1,2,3,4]
arr.forEach(function(value,index,currentArr){
    currentArr[index]=value + 1
})
console.log(arr)//[ 2, 3, 4, 5 ]

map 遍历数组 不可遍历迭代

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。该函数接受的三个参数为:
当前元素
当前索引
当前被调用的数组
有返回值,可以return 出来,也可以不返回
区别:map的回调函数中支持return返回值;return的是一个新数组,并不影响原来传入的数组(只是把原数组克隆一份,把克隆的数组中对应项改变了当成新数组返回);


let ary = [2, 30, 4, 42, 1];
let ans = ary.map(function (item, index, array) {
    return item * 10;
})
console.log('map:',ans); // [20, 300, 40, 420, 10];  返回的新数组把原数组拷贝了一份进行了修改
console.log('map:',ary); // [2, 30, 4, 42, 1];  原数组并未发生变化

filter()过滤循环

filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。filter循环有返回值

let res = [1, 2, 3, 4, 5].filter(function (elem) {
    return (elem > 3);
}) 
console.log('filter:',res); // [4, 5] 
// 上面代码将大于3的数组成员,作为一个新数组返回。
 
var arr = [0, 1, 2, 'a', true, false];
let rey = arr.filter(Boolean)
console.log('filter:',arr); // [0, 1, 2, "a", true, false]

一些数组处理方法

将数组对象相同属性名属性值抽离数组

  let arr1=[];
  let arr2=[];
[{name:"1",value:1},{name:"2",value:1}].map((a) => { 
arr1.push(a.value);arr2.push(a.name);
})
//arr1
//(2) [1, 1]
//arr2
//(2) ["1", "2"]


objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];
function getFields(input, field) {
    var output = [];
    for (var i=0; i < input.length ; ++i)
        output.push(input[i][field]);
    return output;
}
 
var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]



根据数组中对象的某个属性值进行排序

var arr = [
    { id: 1, message: "我是1" },
    { id: 3, message: "我是3" },
    { id: 2, message: "我是2" },
    { id: 6, message: "我是6" },
    { id: 4, message: "我是4" },
    { id: 5, message: "我是5" }
]
function setArray(arr) {
    arr.sort(compare('id'));
    console.log(arr);
    return arr;
}
function compare(property) {
    return function (a, b) {
        return a[property] - b[property];
    }
}
setArray(arr);
//或者
arr1.sort((a,b)=>a["id"] - b["id"])

数组对象 根据某个对象属性名的属性值 拆分数组

formateData = (initialArr: any[], name: string, newArr: any[] = []): any => {
    // newArr是承接分类的新数组,整个initialArr处理完成之后,会根据不同的name生成一个二维数组
    // 判定传参是否符合规则
    if (!(initialArr instanceof Array) || !(newArr instanceof Array)) {
        return '请传入正确格式的数组'
    }
    if (!name) {
        return '请传入对象属性'
    }
    // 每一个类型的单独数组,注意此处不能return出每个alikeArr,
    // 因为递归的返回值只返回最后一次的值
    const alikeArr: any[] = [];
    let propertyName = ''
    if (initialArr.length > 0) {
        propertyName = initialArr[0][`${name}`]
        const tempArr: any[] = []
        // 将拥有共同propertyName属性的对象放到此次遍历的alikeArr中,
        // 将其他的对象放入到tempArr中,等待下次遍历
        initialArr.forEach((val) => {
            if (val[`${name}`] === propertyName) {
                alikeArr.push(val)
            } else {
                tempArr.push(val)
            }
        })
        newArr.push(alikeArr)
        // eslint-disable-next-line no-param-reassign
        initialArr = tempArr
        return formateData(initialArr, name, newArr)
    } else {
        return newArr
    }
}

数组反向去重

let arr = [0, 2, 3, 2, 4, 5, 3]
let data = []
let b = arr.reduce((pre, cur, index) => {
    data.push(cur); if (data.indexOf(cur) !== (data.length - 1)) { data.splice(data.indexOf(cur), 1) }
    return pre
}, {})

请添加图片描述
请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值