目录

1. 数组

1.1 创建数组

  • 创建数组有两种基本方式:使用Array构造函数、使用数组字面量[]
// 通过构造函数
const subjects = new Array("Chinese", "Math", "English");
// 通过字面量
const fruits = ["apple", "banana", "pear"];
  • JS的数组是对象
const subjects = new Array("Chinese", "Math", "English");

const fruits = ["apple", "banana", "pear"];

console.log(typeof subjects);
// object
console.log(typeof fruits);
// object // 对访问不存在的数组索引,会返回undefined
console.log(fruits[4]);
// undefined // 可以写入超出数组索引的数据项
fruits[4] = "orange";
// 但中间项会自动填充为undefined
console.log(fruits[3]);
// undefined // length属性返回数组的大小
console.log(subjects.length);
// 3
// 可以手动修改length的值
subjects.length = 4;
// 将length改为比原有值大的数,数组会被扩展,新扩展的元素均为undefined
console.log(subjects);
// ["Chinese", "Math", "English", empty]
// 将length改为比原有值小的数,数组会被裁剪,多余数据项将被抛弃
subjects.length = 2;
console.log(subjects);
// ["Chinese", "Math"]

使用数组字面量创建数组优于数组构造函数(字面量只需要2个字符)

1.2 在数组两端添加删除元素

方法 作用 返回值
push 末尾添加元素 添加元素后数组的长度
pop 末尾删除元素 被删除(弹出)的元素本身
unshift 开头添加元素 添加元素后数组的长度
shift 开头删除元素 被删除(弹出)的元素本身
const fruits = ["apple", "banana", "pear"];

let len = fruits.push("orange");
console.log(len);
// 4
console.log(fruits);
// ["apple", "banana", "pear", "orange"] let lastFruit = fruits.pop();
console.log(lastFruit);
// orange
console.log(fruits);
// ["apple", "banana", "pear"] len = fruits.unshift("orange");
console.log(len);
// 4
console.log(fruits);
// ["orange", "apple", "banana", "pear"] let firstFruit = fruits.shift();
console.log(lastFruit);
// orange
console.log(fruits);
// ["apple", "banana", "pear"]

性能考虑:pop和push只影响数组最后一个元素,unshift和shift增减第一个元素,之后的每个元素的索引都需要调整。因此pop和push比unshift和shift快得多,非特殊情况下不建议使用unshift和shift。

1.3 在数组任意位置添加、删除元素

delete删除数组元素无效

const fruits = ["apple", "banana", "pear"];

delete fruits[1];

// 使用delete关键字并不能删除元素,只能删除对应索引的值,
console.log(fruits);
// ["apple", empty, "pear"]
// 被删除值的元素的值为undefined
console.log(fruits[1]);
// undefined

使用splice方法增、删、改元素

const fruits = ["apple", "banana", "pear"];

// 删除元素
// 两个参数,表示从索引2开始(索引>= 2),删除1个元素
// 返回值为被删去的元素(以数组的格式)
let elems = fruits.splice(2, 1);
console.log(fruits);
// ["apple", "banana"]
console.log(elems);
// ["pear"] // 新增元素
// 三个以上参数,表示从索引1开始(索引>= 1),删除0个元素,新增后面的剩余参数
// 因为删除的元素个数为0,所以返回值是空数组
elems = fruits.splice(1, 0, "orange", "pear");
console.log(fruits);
// ["apple", "orange", "pear", "banana"]
console.log(elems);
// [] // 两者同时使用
// 三个以上参数,表示表示从索引1开始(索引>= 1),先删除3个元素,新增后面的剩余参数
// 返回值为被删去的元素(以数组的格式)
elems = fruits.splice(1, 3, "peach", "watermelon");
console.log(fruits);
// ["apple", "peach", "watermelon"]
console.log(elems);
// ["orange", "pear", "banana"]

1.4 数组的常用操作

数组遍历(forEach)

const fruits = ["apple", "banana", "pear"];

// for循环
for(let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
} // forEach方法
fruits.forEach(fruit => {
console.log(fruit);
});

映射数组(map方法,对数组成员执行操作,并返回结果组成的新数组)

const students = [
{name: "Wango", age: 24},
{name: "Lily", age: 25},
{name: "Jack", age: 18},
]; // 使用forEach提取
let names = [];
students.forEach(student => {
names.push(student.name);
}); console.log(names);
// ["Wango", "Lily", "Jack"] // 使用map方法提取,自动将返回值装入数组并返回
let age = students.map(student => student.age); console.log(age);
// [24, 25, 18]

测试数组元素(every、some)

const students = [
{name: "Wango", age: 24},
{name: "Lily", age: 25},
{name: "Jack", age: 17},
]; // 使用every验证数组内是否每个元素都满足条件
// 回调函数对每个参数执行操作,当所有元素的回调结果都为true,every方法返回true
// 只要有一个为false,则every方法不再执行并返回false
let allStudentsAreAdult = students.every(student => student.age >= 18); console.log(allStudentsAreAdult);
// fasle // 使用some验证数组内是否有部分元素都满足条件
// 回调函数对每个参数执行操作,当所有元素的回调结果都为false,some方法返回false
// 只要有一个为true,则some方法不再执行并返回true
let someStudentsAreAdult = students.some(student => student.age >= 18); console.log(someStudentsAreAdult);
// true

查找元素(find、filter、indexOf、lastIndexOf、findIndex)

const students = [
{name: "Wango", age: 24},
{name: "Lily", age: 25},
{name: "Jack", age: 17},
]; // 使用find查找单一元素,返回满足条件的第一个元素
// 没找到就返回undefined
let seventeen = students.find(student => student.age === 17);
console.log(seventeen.name);
// Jack // 使用filter查找(过滤其他)元素,返回满足条件的所有元素(数组形式)
// 没找到就返回空数组
let adults = students.filter(student => student.age >= 18);
console.log(adults.map(adult => adult.name));
// ["Wango", "Lily"] const apple = ["a", "p", "p", "l", "e"] // indexOf接收一个元素值,返回顺序查找的特定元素的索引
// 没找到返回-1
let firstIndex = apple.indexOf("p");
console.log(firstIndex);
// 1 // lastIndexOf接收一个元素值,返回逆序查找的特定元素的索引
// 没找到返回-1
let lastIndex = apple.lastIndexOf("p");
console.log(lastIndex);
// 2 // 返回顺序查找的特定元素的索
// 接收回调函数作为参数,所以可以查找对象数组的索引
// 没找到返回-1
let idx = apple.findIndex(a => a === "l");
console.log(idx);
// 3

数组排序(sort)

// 如果回调函数的返回值小于0,第一个元素应该出现在第二个元素之前
// 如果回调函数返回0,两个元素的先后顺序保持不变
// 如果回调函数的返回值大于0,第一个元素应该出现在第二个元素之后 // 如果是纯数字数组,像下面这样写就行了
const nums = [5, 6, 7, 8, 1, 3, 5, 9, 6, 2,];
nums.sort((a, b) => a - b);
console.log(nums);
// [1, 2, 3, 5, 5, 6, 6, 7, 8, 9] // 字符串没办法加减,只能比较大小,用if判断或者三元操作符判断一下然后返回
let chars = ["f", "a", "c", "u", "p"];
chars.sort((a, b) => {
return a > b ? 1 : a < b ? -1 : 0;
});
console.log(chars);
// ["a", "c", "f", "p", "u"] // 如果需要从大到小排序就换一下返回值

合计数组元素(reduce)

const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// reduce方法接收一个回调函数
// 回调函数有两个必需参数, 第一个为累加器,用于存储计算结果,
// 第二个为当前正在处理的元素
let sum = nums.reduce((acc, cur) => acc + cur);
console.log(sum);
// 45

1.5 复用内置的数组函数(复用已经编写的代码)

<input type="text" id="first">
<input type="button" id="second"> <script>
// 创建一个可以复用数组方法的对象
const elems = {
length: 0, // 模拟数组长度
add: function(elem) {
// 复用数组代码
// 注意:原代码有返回值的,本代码也要有返回值
// 避免造成混乱
return Array.prototype.push.call(this, elem);
},
gather: function(id) {
return this.add(document.getElementById(id));
},
find: function(callback) {
return Array.prototype.find.call(this, callback);
}
}
elems.gather("first");
elems.gather("second");
// 数组代码会对length属性进行操作,
// 所以不需要再对length进行手动操作
console.log(elems.length);
// 2 const first = elems.find(elem => elem.id === "first");
console.log(first.type);
// text
</script>

2. Map

2.1 对象不是Map

访问对象未显式定义的属性,返回非预期

// 从字面看,对象符合字典的要求:键值对
// 但作为对象,其具有很多隐式属性
const student = {
wango: { id: 578, age: 24 },
lily: { id: 629, age: 25 },
jack: { id: 634, age: 22 }
} // 对于未定义的属性,期望返回undefined,但
console.log(student.constructor);
// Object() { [native code] }

将对象的key映射为HTML节点造成key重复

const elems = {};

const first = document.getElementById("first");
const second = document.getElementById("second"); // HTML元素对象作为key,加入对象
elems[first] = "First Element";
elems[second] = "Second Element"; // 对象的key必须是字符串,非字符串类型会在后台静默调用toString方法
// 而相同类型元素的toString方法返回值相同,导致key重复
console.log(first.toString() === second.toString());
// true // 前一个数据被后者替换
console.log(elems[first]);
// Second Element
console.log(elems[second]);
// Second Element

对象的原型有额外的继承属性、key仅支持字符串,所以通常不能使用对象作为map

2.2 创建map

<input type="text" id="first">
<input type="text" id="second">
<input type="text" id="third"> <script>
// 使用Map构造函数创建空map
const elemsMap = new Map(); const first = document.getElementById("first");
const second = document.getElementById("second");
const third = document.getElementById("third"); // 使用set方法创建映射,参数分别是:key, value
elemsMap.set(first, "First Element");
elemsMap.set(second, "Second Element"); // size属性为映射数量
console.log(elemsMap.size);
// 2 // get方法通过key获取value
console.log(elemsMap.get(first));
// First Element
console.log(elemsMap.get(second));
// Second Element // has方法判断指定key是否存在
console.log(elemsMap.has(third));
// false elemsMap.set(third, "Third Element"); // delete方法通过key删除映射
// 有这个key并删除成功返回true,没有这个key返回false
let a = elemsMap.delete(first);
console.log(a);
// true console.log(elemsMap.size);
// 2 // clear方法清空map
elemsMap.clear(); console.log(elemsMap.size);
// 0
</script>

JS中两个对象的内容相同,但两个对象仍然不相等,所以可以作为map的key

const map = new Map();

let currentLocation = location.href;

// 创建两个相同内容的对象
const firstURL = new URL(currentLocation);
const secondURL = new URL(currentLocation); map.set(firstURL, { "description": "First" });
map.set(secondURL, { "description": "Second" }); // 两个相同内容的对象都可以称为map的key
console.log(map.get(firstURL).description);
// First
console.log(map.get(secondURL).description);
// Second

2.3 遍历map(for-of)

const students = new Map();

students.set("Wango", 578);
students.set("Lily", 649);
students.set("Jack", 312); // 遍历所有的students,没有元素有两个值:key和value
for(let student of students) {
console.log(student[0] + ": " + student[1]);
}
// Wango: 578
// Lily: 649
// Jack: 312 // 遍历所有的key
for(let name of students.keys()) {
console.log(name);
}
// Wango
// Lily
// Jack // 遍历所有的value
for(let id of students.values()) {
console.log(id);
}
// 578
// 649
// 312

3. Set

3.1 使用对象模拟集合

// 用对象模拟集合
// 同样的问题,对象的key只能是字符串,这大大限制了模拟集合的能力 // 可以提供参数预填充集合
function Set(arr) {
this.data = {};
this.size = 0;
if (Array.isArray(arr)) {
// 数组去重
for (var i = 0; i < arr.length; i++) {
if (!this.has([arr[i]])) {
this.data[arr[i]] = arr[i];
this.size++;
}
}
}
} Set.prototype.has = function (item) {
return typeof this.data[item] !== "undefined";
} Set.prototype.add = function (item) {
if (!this.has(item)) {
this.data[item] = item;
this.size++;
}
return this.values();
} Set.prototype.delete = function (item) {
if (this.has(item)) {
delete this.data[item];
this.size--;
return true;
}
return false;
} Set.prototype.clear = function() {
var keys = this.keys();
this.size = 0;
for(var i = 0; i < keys.length; i++) {
delete this.data[keys[i]];
}
} Set.prototype.keys = Set.prototype.values = function() {
return Object.getOwnPropertyNames(this.data);
} Set.prototype.forEach = function(callback) {
var props = this.values();
for(var i = 0; i < props.length; i++) {
callback(props[i], props[i]);
}
}

3.2 创建Set

const students = new Set(["Wango", "Lily", "Jack"]);

console.log(students.has("Wango"));
// true
console.log(students.add("Jack"));
// Set(3) {"Wango", "Lily", "Jack"}
console.log(students.add("Tom"));
// Set(4) {"Wango", "Lily", "Jack", "Tom"}
console.log(students.delete("Wango"));
// true
console.log(students);
// Set(3) {"Lily", "Jack", "Tom"} // 为了与map API保持一致,每个key和value的值相同
students.forEach((key, val) => {
console.log(key + ": " + val);
});
// Lily: Lily
// Jack: Jack
// Tom: Tom for(let student of students) {
console.log(student);
}
// Lily
// Jack
// Tom // 清空集合
students.clear();

3.2 并集、交集、差集

const firstGroup = new Set(["Wango", "Lily", "Tom"]);
const secondGroup = new Set(["Wango", "Lily", "Jack", "Mike"]); // 并集,使用延展运算符打散两个集合,再合并成一个新的数组作为参数
// Set构造函数自动去重
const allStudents = new Set([...firstGroup, ...secondGroup]); console.log(allStudents);
// {"Wango", "Lily", "Tom", "Jack", "Mike"} // 交集,打散成数组后使用filter方法过滤掉secondGroup没有的元素
const sameStudents = new Set([...firstGroup].filter(stu => secondGroup.has(stu))); console.log(sameStudents);
// {"Wango", "Lily"} // 差集,只包含于集合A,不包含于集合B的元素,从A中过滤掉B中有的元素
const onlyInFirstGroup = new Set([...firstGroup].filter(stu => !secondGroup.has(stu))); console.log(onlyInFirstGroup);
// {"Tom"}

第9章 集合处理(数组、Map、Set)的更多相关文章

  1. 第19章 集合框架(3)-Map接口

    第19章 集合框架(3)-Map接口 1.Map接口概述 Map是一种映射关系,那么什么是映射关系呢? 映射的数学解释 设A,B是两个非空集合,如果存在一个法则,使得对A中的每一个元素a,按法则f,在 ...

  2. MyBatis传入集合 list 数组 map参数的写法

    foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合.foreach元素的属性主要有item,index,collection,open,separator,close.ite ...

  3. MyBatis传入参数为集合 list 数组 map写法

    foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合.foreach元素的属性主要有item,index,collection,open,separator,close.ite ...

  4. JAVA基础第五章-集合框架Map篇

    业内经常说的一句话是不要重复造轮子,但是有时候,只有自己造一个轮子了,才会深刻明白什么样的轮子适合山路,什么样的轮子适合平地! 我将会持续更新java基础知识,欢迎关注. 往期章节: JAVA基础第一 ...

  5. 5、数组和集合--Collection、Map

    一.数组:同一个类型数据的集合,其实他也是一个容器 1.数组的好处:可以自动给数组中的元素从0开始编号,方便操作这些数据 2.数组的定义: 在Java中常见: 格式1:  类型 [] 数组名 = ne ...

  6. 数组,集合,字符串,bean,map

    //[字符串]转成[数组] String[] arr = "1,2,3,4,5,6".split(","); //[String数组]转成[Long数组] Lo ...

  7. JAVASE(十四) 集合: 数组和集合、Collection、Iterator、List、Set、Map

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.数组和集合 1.1 内存中对数据进行存储和管理的“容器”:数组,集合 1.2 数组存储的特点和缺点 ...

  8. 集合遍历数组三种常用方式(Collecton和Map)

    Collection集合遍历数组的三种方式: 迭代器 foreach(增强for循环) JDK1.8之后的新技术Lambda 迭代器: 方法:public Iterator inerator():获取 ...

  9. Java核心技术卷一基础技术-第13章-集合-读书笔记

    第13章 集合 本章内容: * 集合接口 * 具体的集合 * 集合框架 * 算法 * 遗留的集合 13.1 集合接口 Enumeration接口提供了一种用于访问任意容器中各个元素的抽象机制. 13. ...

  10. 20190825 On Java8 第十二章 集合

    第十二章 集合 java.util 库提供了一套相当完整的集合类(collection classes)来解决这个问题,其中基本的类型有 List . Set . Queue 和 Map. 不要在新代 ...

随机推荐

  1. 凌乱的与ctf无关的小知识点

    (1)在网页中一般不要用记住密码.否则想要知道你的密码很简单. 例子:看样子很安全,别人无法通过这些来获得你的其他密码(尤其是想我这样密码强度不高的人),但是知道要修改前端的选项,你的密码就会被暴露. ...

  2. Android10_原理机制系列_事件传递机制

    前言和概述 Android的输入设备,最常用的就是 触摸屏和按键 了.当然还有其他方式,比如游戏手柄,比如支持OTG设备,则可以链接鼠标.键盘等. 那么这些设备的操作 是如何传递到系统 并 控制界面的 ...

  3. 团队作业4-Day5

    团队作业4-Day5 项目git地址 1. 站立式会议 2. 项目燃尽图 3. 适当的项目截图 4. 代码/文档签入记录(部分) 5. 每人每日总结 吴梓华:补充了样式代码以方便调试. 白军强:顺利完 ...

  4. v-clickoutsides

    //点击目标元素外侧触发特定事件 使用 v-clickoutsides="clickHandler" import Vue from 'vue' Vue.directive('cl ...

  5. git相关操作

    git相关命令 基本操作 git init git add xxx git commit -m "first commit" git tag -a V1.0 -m '我的标签' g ...

  6. Object not found! The requested URL was not found on this server.... 报错解决方案

    服务器(centos6.5) lnmp 报错如下 Object not found! The requested URL was not found on this server. The link ...

  7. centos 7系统安装mysql 8.0

    一.关闭防火墙 [root@node01 ~]# systemctl disable firewalld [root@node01 ~]# systemctl stop firewalld [root ...

  8. svn提交时提示 Aborting commit: remains in conflict 解决办法,更改svn服务地址

    TortoiseSVN客户端如何更改新的URL 问题: 我们的服务器换了新的URL地址,这时候我们本地的SVN访问帐号和地址就要重新定义了. 解决步骤: 1:重新定义SVN的URL,右键(Tortoi ...

  9. beautiful soup 遇到class标签的值中含有空格的处理

    用Python写一个爬虫,用BeautifulSoup解析html.其中一个地方需要抓取下面两类标签:<dd class="ab " >blabla1</dd&g ...

  10. Promise 之初探

    陈旧的知识应该更新一下了,先尝试一下 Promise ,主要参考 https://www.cnblogs.com/whybxy/p/7645578.html 定义一个函数 直接上干货,定义一个函数: ...