目录

1. 数组

1.1 创建数组

  • 创建数组有两种基本方式:使用Array构造函数、使用数组字面量[]
  1. // 通过构造函数
  2. const subjects = new Array("Chinese", "Math", "English");
  3. // 通过字面量
  4. const fruits = ["apple", "banana", "pear"];
  • JS的数组是对象
  1. const subjects = new Array("Chinese", "Math", "English");
  2. const fruits = ["apple", "banana", "pear"];
  3. console.log(typeof subjects);
  4. // object
  5. console.log(typeof fruits);
  6. // object
  7. // 对访问不存在的数组索引,会返回undefined
  8. console.log(fruits[4]);
  9. // undefined
  10. // 可以写入超出数组索引的数据项
  11. fruits[4] = "orange";
  12. // 但中间项会自动填充为undefined
  13. console.log(fruits[3]);
  14. // undefined
  15. // length属性返回数组的大小
  16. console.log(subjects.length);
  17. // 3
  18. // 可以手动修改length的值
  19. subjects.length = 4;
  20. // 将length改为比原有值大的数,数组会被扩展,新扩展的元素均为undefined
  21. console.log(subjects);
  22. // ["Chinese", "Math", "English", empty]
  23. // 将length改为比原有值小的数,数组会被裁剪,多余数据项将被抛弃
  24. subjects.length = 2;
  25. console.log(subjects);
  26. // ["Chinese", "Math"]

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

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

方法 作用 返回值
push 末尾添加元素 添加元素后数组的长度
pop 末尾删除元素 被删除(弹出)的元素本身
unshift 开头添加元素 添加元素后数组的长度
shift 开头删除元素 被删除(弹出)的元素本身
  1. const fruits = ["apple", "banana", "pear"];
  2. let len = fruits.push("orange");
  3. console.log(len);
  4. // 4
  5. console.log(fruits);
  6. // ["apple", "banana", "pear", "orange"]
  7. let lastFruit = fruits.pop();
  8. console.log(lastFruit);
  9. // orange
  10. console.log(fruits);
  11. // ["apple", "banana", "pear"]
  12. len = fruits.unshift("orange");
  13. console.log(len);
  14. // 4
  15. console.log(fruits);
  16. // ["orange", "apple", "banana", "pear"]
  17. let firstFruit = fruits.shift();
  18. console.log(lastFruit);
  19. // orange
  20. console.log(fruits);
  21. // ["apple", "banana", "pear"]

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

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

delete删除数组元素无效

  1. const fruits = ["apple", "banana", "pear"];
  2. delete fruits[1];
  3. // 使用delete关键字并不能删除元素,只能删除对应索引的值,
  4. console.log(fruits);
  5. // ["apple", empty, "pear"]
  6. // 被删除值的元素的值为undefined
  7. console.log(fruits[1]);
  8. // undefined

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

  1. const fruits = ["apple", "banana", "pear"];
  2. // 删除元素
  3. // 两个参数,表示从索引2开始(索引>= 2),删除1个元素
  4. // 返回值为被删去的元素(以数组的格式)
  5. let elems = fruits.splice(2, 1);
  6. console.log(fruits);
  7. // ["apple", "banana"]
  8. console.log(elems);
  9. // ["pear"]
  10. // 新增元素
  11. // 三个以上参数,表示从索引1开始(索引>= 1),删除0个元素,新增后面的剩余参数
  12. // 因为删除的元素个数为0,所以返回值是空数组
  13. elems = fruits.splice(1, 0, "orange", "pear");
  14. console.log(fruits);
  15. // ["apple", "orange", "pear", "banana"]
  16. console.log(elems);
  17. // []
  18. // 两者同时使用
  19. // 三个以上参数,表示表示从索引1开始(索引>= 1),先删除3个元素,新增后面的剩余参数
  20. // 返回值为被删去的元素(以数组的格式)
  21. elems = fruits.splice(1, 3, "peach", "watermelon");
  22. console.log(fruits);
  23. // ["apple", "peach", "watermelon"]
  24. console.log(elems);
  25. // ["orange", "pear", "banana"]

1.4 数组的常用操作

数组遍历(forEach)

  1. const fruits = ["apple", "banana", "pear"];
  2. // for循环
  3. for(let i = 0; i < fruits.length; i++) {
  4. console.log(fruits[i]);
  5. }
  6. // forEach方法
  7. fruits.forEach(fruit => {
  8. console.log(fruit);
  9. });

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

  1. const students = [
  2. {name: "Wango", age: 24},
  3. {name: "Lily", age: 25},
  4. {name: "Jack", age: 18},
  5. ];
  6. // 使用forEach提取
  7. let names = [];
  8. students.forEach(student => {
  9. names.push(student.name);
  10. });
  11. console.log(names);
  12. // ["Wango", "Lily", "Jack"]
  13. // 使用map方法提取,自动将返回值装入数组并返回
  14. let age = students.map(student => student.age);
  15. console.log(age);
  16. // [24, 25, 18]

测试数组元素(every、some)

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

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

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

数组排序(sort)

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

合计数组元素(reduce)

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

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

  1. <input type="text" id="first">
  2. <input type="button" id="second">
  3. <script>
  4. // 创建一个可以复用数组方法的对象
  5. const elems = {
  6. length: 0, // 模拟数组长度
  7. add: function(elem) {
  8. // 复用数组代码
  9. // 注意:原代码有返回值的,本代码也要有返回值
  10. // 避免造成混乱
  11. return Array.prototype.push.call(this, elem);
  12. },
  13. gather: function(id) {
  14. return this.add(document.getElementById(id));
  15. },
  16. find: function(callback) {
  17. return Array.prototype.find.call(this, callback);
  18. }
  19. }
  20. elems.gather("first");
  21. elems.gather("second");
  22. // 数组代码会对length属性进行操作,
  23. // 所以不需要再对length进行手动操作
  24. console.log(elems.length);
  25. // 2
  26. const first = elems.find(elem => elem.id === "first");
  27. console.log(first.type);
  28. // text
  29. </script>

2. Map

2.1 对象不是Map

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

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

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

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

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

2.2 创建map

  1. <input type="text" id="first">
  2. <input type="text" id="second">
  3. <input type="text" id="third">
  4. <script>
  5. // 使用Map构造函数创建空map
  6. const elemsMap = new Map();
  7. const first = document.getElementById("first");
  8. const second = document.getElementById("second");
  9. const third = document.getElementById("third");
  10. // 使用set方法创建映射,参数分别是:key, value
  11. elemsMap.set(first, "First Element");
  12. elemsMap.set(second, "Second Element");
  13. // size属性为映射数量
  14. console.log(elemsMap.size);
  15. // 2
  16. // get方法通过key获取value
  17. console.log(elemsMap.get(first));
  18. // First Element
  19. console.log(elemsMap.get(second));
  20. // Second Element
  21. // has方法判断指定key是否存在
  22. console.log(elemsMap.has(third));
  23. // false
  24. elemsMap.set(third, "Third Element");
  25. // delete方法通过key删除映射
  26. // 有这个key并删除成功返回true,没有这个key返回false
  27. let a = elemsMap.delete(first);
  28. console.log(a);
  29. // true
  30. console.log(elemsMap.size);
  31. // 2
  32. // clear方法清空map
  33. elemsMap.clear();
  34. console.log(elemsMap.size);
  35. // 0
  36. </script>

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

  1. const map = new Map();
  2. let currentLocation = location.href;
  3. // 创建两个相同内容的对象
  4. const firstURL = new URL(currentLocation);
  5. const secondURL = new URL(currentLocation);
  6. map.set(firstURL, { "description": "First" });
  7. map.set(secondURL, { "description": "Second" });
  8. // 两个相同内容的对象都可以称为map的key
  9. console.log(map.get(firstURL).description);
  10. // First
  11. console.log(map.get(secondURL).description);
  12. // Second

2.3 遍历map(for-of)

  1. const students = new Map();
  2. students.set("Wango", 578);
  3. students.set("Lily", 649);
  4. students.set("Jack", 312);
  5. // 遍历所有的students,没有元素有两个值:key和value
  6. for(let student of students) {
  7. console.log(student[0] + ": " + student[1]);
  8. }
  9. // Wango: 578
  10. // Lily: 649
  11. // Jack: 312
  12. // 遍历所有的key
  13. for(let name of students.keys()) {
  14. console.log(name);
  15. }
  16. // Wango
  17. // Lily
  18. // Jack
  19. // 遍历所有的value
  20. for(let id of students.values()) {
  21. console.log(id);
  22. }
  23. // 578
  24. // 649
  25. // 312

3. Set

3.1 使用对象模拟集合

  1. // 用对象模拟集合
  2. // 同样的问题,对象的key只能是字符串,这大大限制了模拟集合的能力
  3. // 可以提供参数预填充集合
  4. function Set(arr) {
  5. this.data = {};
  6. this.size = 0;
  7. if (Array.isArray(arr)) {
  8. // 数组去重
  9. for (var i = 0; i < arr.length; i++) {
  10. if (!this.has([arr[i]])) {
  11. this.data[arr[i]] = arr[i];
  12. this.size++;
  13. }
  14. }
  15. }
  16. }
  17. Set.prototype.has = function (item) {
  18. return typeof this.data[item] !== "undefined";
  19. }
  20. Set.prototype.add = function (item) {
  21. if (!this.has(item)) {
  22. this.data[item] = item;
  23. this.size++;
  24. }
  25. return this.values();
  26. }
  27. Set.prototype.delete = function (item) {
  28. if (this.has(item)) {
  29. delete this.data[item];
  30. this.size--;
  31. return true;
  32. }
  33. return false;
  34. }
  35. Set.prototype.clear = function() {
  36. var keys = this.keys();
  37. this.size = 0;
  38. for(var i = 0; i < keys.length; i++) {
  39. delete this.data[keys[i]];
  40. }
  41. }
  42. Set.prototype.keys = Set.prototype.values = function() {
  43. return Object.getOwnPropertyNames(this.data);
  44. }
  45. Set.prototype.forEach = function(callback) {
  46. var props = this.values();
  47. for(var i = 0; i < props.length; i++) {
  48. callback(props[i], props[i]);
  49. }
  50. }

3.2 创建Set

  1. const students = new Set(["Wango", "Lily", "Jack"]);
  2. console.log(students.has("Wango"));
  3. // true
  4. console.log(students.add("Jack"));
  5. // Set(3) {"Wango", "Lily", "Jack"}
  6. console.log(students.add("Tom"));
  7. // Set(4) {"Wango", "Lily", "Jack", "Tom"}
  8. console.log(students.delete("Wango"));
  9. // true
  10. console.log(students);
  11. // Set(3) {"Lily", "Jack", "Tom"}
  12. // 为了与map API保持一致,每个key和value的值相同
  13. students.forEach((key, val) => {
  14. console.log(key + ": " + val);
  15. });
  16. // Lily: Lily
  17. // Jack: Jack
  18. // Tom: Tom
  19. for(let student of students) {
  20. console.log(student);
  21. }
  22. // Lily
  23. // Jack
  24. // Tom
  25. // 清空集合
  26. students.clear();

3.2 并集、交集、差集

  1. const firstGroup = new Set(["Wango", "Lily", "Tom"]);
  2. const secondGroup = new Set(["Wango", "Lily", "Jack", "Mike"]);
  3. // 并集,使用延展运算符打散两个集合,再合并成一个新的数组作为参数
  4. // Set构造函数自动去重
  5. const allStudents = new Set([...firstGroup, ...secondGroup]);
  6. console.log(allStudents);
  7. // {"Wango", "Lily", "Tom", "Jack", "Mike"}
  8. // 交集,打散成数组后使用filter方法过滤掉secondGroup没有的元素
  9. const sameStudents = new Set([...firstGroup].filter(stu => secondGroup.has(stu)));
  10. console.log(sameStudents);
  11. // {"Wango", "Lily"}
  12. // 差集,只包含于集合A,不包含于集合B的元素,从A中过滤掉B中有的元素
  13. const onlyInFirstGroup = new Set([...firstGroup].filter(stu => !secondGroup.has(stu)));
  14. console.log(onlyInFirstGroup);
  15. // {"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. 堆叠注入tips

    漏洞成因 使用mysqli_multi_query()这种支持多语句执行的函数 使用PDO的方式进行数据查询,创建PDO实例时PDO::MYSQL_ATTR_MULTI_STATEMENTS设置为tr ...

  2. 深入理解.NET/WPF内存泄漏

    众所周知,内存管理和如何避免内存泄漏(memory leak)一直是软件开发的难题.不要说C.C++等非托管(unmanaged)语言,即使是Java..NET等托管(managed)语言,尽管有着完 ...

  3. 落谷P3041 [USACO12JAN]Video Game G

    题目链接 多模式匹配问题,先建 AC 自动机. 套路性的搞个 DP: \(f[i][j]\) 表示前 \(i\) 个字符,当前在 \(AC\) 自动机上的节点是 \(j\) 能匹配到的最多分. 初始化 ...

  4. 廖雪峰官网学习js 字符串

    操作字符串: length()           长度 totoLowerCase() 小写 toUpperCase()      大写 trim()            移除空白 charAt( ...

  5. Angular:组件之间的通信@Input、@Output和ViewChild

    ①父组件给子组件传值 1.父组件: ts: export class HomeComponent implements OnInit { public hxTitle = '我是首页的头部'; con ...

  6. 封装事件订阅来进行非父子组件的传值(React)

    const list={} // 将事件名和事件函数装进事件池里 function $on(name,func) { if(!name || !func) return; if(!Object.key ...

  7. 【操作系统】页面置换算法(最佳置换算法)(C语言实现)

    [操作系统]页面置换算法(最佳置换算法)(C语言实现) (编码水平较菜,写博客也只是为了个人知识的总结和督促自己学习,如果有错误,希望可以指出) 1.页面置换算法: 在地址映射过程中,若在页面中发现所 ...

  8. gnuplot名词缩写

    http://blog.163.com/yucheng_xiao/blog/static/7660019220141017114630822/ with 缩写成 w  lt 是 linetype 的缩 ...

  9. 学Python编程能做什么工作?从事什么岗位?——这些问题你知道吗?

    前言 学Python编程能做什么工作?随着人工智能发展,学习python语言的人员有更多的岗位机会,python从事的职业广泛,从游戏到AI人工智能能都可以用Python实现.除了编程,各种岗位的人都 ...

  10. ⑦SpringCloud 实战:引入Sleuth组件,完善服务链路跟踪

    这是SpringCloud实战系列中第7篇文章,了解前面第两篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 ②SpringCloud 实战:引入F ...