22day-相关知识2

Set

  • 是一种新的数据结构 Set
  • 类似于数组,但是成员的值都是唯一的,没有重复的值。
  • Set 本身是一个构造函数,用来生成 Set 数据结构
// 通过new关键字创建一个Set结构
let s = new Set();
console.log(s);

// 添加数据
// 通过add方法
s.add(10);
console.log(s);

// 也可以
[1, 2, 3, 4, 1, 2, 3, 4].forEach(item => s.add(item));
// Set结构不允许添加重复的值
console.log(s);

// 在初始化时接受一个数组作为参数来创建Set
let s2 = new Set([1, 2, 3, 4, 5, 2, 3, 1, 4, 5, 5, 5]);
console.log(s2);
Set 去重判断
let s = new Set([5, "5"]);
console.log(s); // {5, '5'}
let a = NaN;
let b = NaN;
console.log(a === b);
s.add(a);
s.add(b);
console.log(s);
s.add({});
s.add({});
console.log(s);
  • 向 Set 加入值时,不会发生类型转换,所以 5 和’5’是两个不同的值
  • Set 内部判断两个值是否不同,使用的算法类似于全等运算符
  • 主要区别在于,Set 加入值时认为 NaN 等于自身,但是全等运算符认为 NaN 不等于自身
  • 再向 Set 添加对象时,总是不等的。
set 实例的属性和方法
  • 属性

    • size:返回的是 Set 实例的成员总数
  • 方法:分为两类

    • 操作方法
    • 遍历方法
  • 操作方法

    • add(value):添加某个值
      • 返回值:Set 结构本身
    • delete(value):删除某个值
      • 返回值:返回一个布尔值,表示删除是否成功
    • has(value):查询该值是否为 Set 成员
      • 返回值:一个布尔值
    • clear:清除所有成员
      • 返回值:空
let s = new Set([1, 2, 3, 4]);

let flag = s.delete(1);
console.log(flag); // true 删除成功
console.log(s);

let flag2 = s.has(4);
console.log(flag2); // true
let flag3 = s.has(1);
console.log(flag3); // false
s.clear();
console.log(s); // Set(0) {size: 0}
  • 遍历方法
    • keys
      • 语法:set.keys()
      • 返回值:返回键名的遍历器
    • values
      • 语法:set.values()
      • 返回值:返回键值的遍历器
      • 注意:有 Set 结构没有键名,只有键值(或者说键名和键值是听一个值),所以 keys 和 values 方法的行为完全一致。
    • entries
      • 语法:set.entries()
      • 返回值:返回键值对的遍历器
let s = new Set([10, 20, 30, 40, 50]);
let sKeys = s.keys();
console.log(sKeys);
for (let item of sKeys) {
  console.log(item);
}
let sValues = s.values();
for (let item of sValues) {
  console.log(item);
}
let sEntries = s.entries();
for (let item of sEntries) {
  // 由于set结构中键名与键值相同,
  // entries方法返回的遍历器同时包含键名和键值,所以输出时是一个数组,他的两个成员,值相等
  console.log(item);
}
  • forEach
  • set 结构实例和数组一样,拥有 forEach 方法,用于对每个成员执行某种操作,没有返回值
s.forEach((item, key, arr) => {
  console.log(item, key, arr);
  // 10 10 Set(5) {10, 20, 30, 40, 50}
  // 20 20 Set(5) {10, 20, 30, 40, 50}
  // ...
});
set 的应用
  • 数组去重
    利用扩展运算符和 set 结构,对数组中的数据进行去重;
let arr = [3, 4, 5, 6, 1, 2, 4, 2, 4, 6, 2, 7];
let newArr = [...new Set(arr)];
// ...扩展运算符之所以可以将Set结构展开,原因在于,扩展运算符内部使用的是for of循环,所以可以用于set结构
console.log(newArr);
  • 数组方法间接用于 Set
// 间接使用数组方法
// let set = new Set([1,2,3]);
// set = new Set([...set].map(item=> item*2));
// console.log(set);

// // filter
// set = new Set([...set].filter(item => item % 2))
// console.log(set);
// 并集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 合并
let ab = new Set([...a, ...b]);
console.log(ab);

// 交集
let intersect = new Set([...a].filter(item => b.has(item)));
console.log(intersect);

// 差集
// a相对于b的差集
let difference = new Set([...a].filter(item => !b.has(item)));
let differenceB = new Set([...b].filter(item => !a.has(item)));
console.log(difference);
console.log(differenceB);
  • Array.from 方法
  • 语法:Array.from(你要转换为数组的数据,fn)
  • 返回值:一个数组
  • 作用:将一个类数组对象或可遍历对象转换为一个真正的数组
    • 什么叫做类数组对象?
      • 最基本的要求就是具有 length 属性的对象
// let arrayLike = {
//   0:"tom",
//   1:"65",
//   2:"男",
//   3:["zd","jh","rb"],
//   length:4,
// }
// console.log(arrayLike);
// let arr = Array.from(arrayLike);
// console.log(arr);

// delete arrayLike.length;
// let arr2 = Array.from(arrayLike);
// console.log(arr2); // []

// 如果对象的属性名不是数字类型
let arrayLike = {
  name: "tom",
  age: "65",
  gender: "男",
  friends: ["zd","jh","rb"],
  length: 4,
};
let arr = Array.from(arrayLike);
console.log(arr); //   [undefined, undefined, undefined, undefined]
// 得到长度为4,元素均为undefined的数组

由此可见,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:

  • 该类数组对象必须具有 length 属性,用于指定数组的长度。如果没有 length 属性,那么转换后的数组是一个空数组
  • 该类数组对象的属性名必须为数字类型或字符串类型的数字
// let arrayLike = {
//   0:"tom",
//   1:"65",
//   2:"男",
//   3:["zd","jh","rb"],
//   length:4,
// }
// console.log(arrayLike);
// let arr = Array.from(arrayLike);
// console.log(arr);

// delete arrayLike.length;
// let arr2 = Array.from(arrayLike);
// console.log(arr2); // []

// 如果对象的属性名不是数字类型
// let arrayLike = {
//   name:"tom",
//   age:"65",
//   gender:"男",
//   friends:["zd","jh","rb"],
//   length:4,
// }
// let arr = Array.from(arrayLike)
// console.log(arr);//   [undefined, undefined, undefined, undefined]
// 得到长度为4,元素均为undefined的数组

// let arrayLike = {
//   0:"tom",
//   1:"65",
//   2:"男",
//   3:["zd","jh","rb"],
//   10:20,
//   length:11,
// }
// let arr = Array.from(arrayLike);
// console.log(arr);
let lis = Array.from(document.querySelectorAll("li"));
console.log(lis);
// let arr = Array.from(lis)
// console.log(arr);
  • 第二参数
  • 类似于数组的 map 方法,用来对每个元素进行处理,将处理后的值放入返回的数组
let arr = [12, 45, 56, 76, 34, 23, 78];
let set = new Set(arr);
let arr2 = Array.from(set, (a, b, c) => {
  console.log(a, b, c);
  return a;
});
console.log(arr2);

// 字符串转数组
let str = new String("hello kitty");
console.log(Array.from(str));
console.log(str);

// 返回一个一摸一样的数组
console.log(Array.from([1, 2, 3, 4, 5, 6, 7, 8]));

Map

  • 是一种新的数据结构
  • 传统 js 中的对象,是键值对的集合(hash 结构),但是只能使用字符串作为键名
  • Map 它类似于对象,也是键值对的集合,但是键名不限于字符串,可以是各种类型的值(包括对象)都可以作为键名
// 传统对象
const data = {};
const ele = document.querySelector("div");
let o = { name: "zd" };

data[ele] = "myDiv";
data[o] = "myO";

console.log(data);
console.log(ele.toString());
console.log(o.toString());

console.log(data[ele]);
console.log(data["[object HTMLDivElement]"]);

// 原意是想要使用一个DOM节点作为data对象的键名,但是由于对象只能接受字符串作为键名,所以ele被自动转为[object HTMLDivElement]

// Map对象
let m = new Map();
let obj = { name: "zd" };

// 向Map结构中添加数据
m.set(obj, "zd");
m.set(ele, "节点");

console.log(m);

// 获取Map中的数据
console.log(m.get(obj)); // "zd"
// 因为obj对象和{}对象不是同一个对象
console.log(m.get({})); // undefined
console.log(m.get(ele)); // 节点
console.log(m.get(document.querySelector("div"))); // 节点
Map 实例方法和属性
  • 属性:
    size:返回 Map 结构的成员总数

  • 方法:

  • set(key,value):向 Map 结构中添加数据

    • 参数:key:键名:value:键值
    • 返回值:返回添加数据过后的 Map
let m = new Map();

m.set("name", "xx");
m.set(999, "笑笑");
m.set(undefined, "yanhao");
// 当发生重复时,与对象一致 新增会变为修改
m.set(undefined, "yaohao2");
console.log(m);

let res = m.set(null, "qx");
console.log(res);
console.log(m);
// 因为set方法返回的是当前的Map对象
// 所以可以使用链式写法添加
m.set({}, "hello")
  .set([], "world")
  .set(function () {}, "我是一个函数");
console.log(m);
// {'name' => 'xx', 999 => '笑笑', undefined => 'yaohao2', null => 'qx', {…} => 'hello', …}

let s = new Set([1, 2, 3]);
s.add(4).add(5).add(6).add(7);
console.log(s);

// 可以向Map传递一个数组作为参数来生成Map结构
// 但该数组的成员必须是一个个表示键值对的数组
// 键值对数组
let arr = [
  ["name", "xx"],
  ["age", 18],
];
let m2 = new Map(arr);
console.log(m2);

// Map接受数组作为参数,实际上执行的算法如下
let m3 = new Map();
arr.forEach(function ([key, value]) {
  m3.set(key, value);
});
console.log(m3);

// 接受一个Set来生成Map
let set = new Set([
  ["name", "笑笑"],
  ["age", 18],
]);
console.log(set);
let m4 = new Map(set);
console.log(m4);
let m5 = new Map(m4);
console.log(m5);

console.log(m5 === m4);
  • get(key):用于获取 Map 对象中对应 key 的值
    • 参数:key 表示需要查找键值的键名
    • 返回值:对应键值或 undefined(没找到的时候)
let m = new Map();
function foo() {
  console.log(123);
}
m.set(foo, "是一个函数");
m.set(null, "qx");
m.set(undefined, "xx");
m.set({}, 123);

console.log(m);

console.log(m.get(foo)); // "是一个函数"
console.log(m.get(null)); // qx
console.log(m.get(undefined)); // xx
console.log(m.get({})); // undefined
  • has(key):用于检测某个键在当前 Map 对象中是否存在
    • 参数:key 表示要检测的键
    • 返回值:是一个布尔值,true 表示存在反之不存在
console.log(m.has(undefined)); // true
console.log(m.has(function foo() {})); // false
console.log(m.has(foo)); // true
console.log(m.has({})); // false
  • delete(key):删除某个键
    • 参数:表示需要删除的键
    • 返回值:一个布尔值。用于表示删除是否成功
console.log(m.delete(foo)); // 都为true
console.log(m.delete(null));
console.log(m.delete(undefined));
console.log(m.delete("qx")); // false
  • clear:清除所有成员
    • 参数:没有
    • 返回值:没有
m.clear();
console.log(m); // {size: 0}
  • 遍历方法
    三个遍历器生成函数,一个遍历方法

  • keys:返回键名的遍历器

let m = new Map([
  ["name", "xx"],
  ["age", 3],
]);

for (let item of m.keys()) {
  console.log(item); // name age
}
  • values:返回键值的遍历器
for (let item of m.values()) {
  console.log(item); // xx 3
}
  • entries:返回所有成员的遍历器
for (let item of m.entries()) {
  console.log(item);
  //  ['name', 'xx'] ['age', 3]
}
// 也可以
for (let [key, value] of m.entries()) {
  console.log(key, value);
  // name xx
  // age 3
}
  • forEach:遍历Map的所有成员
      m.forEach(function(item,index,arr){
        console.log(item,index,arr);
        console.log(this);
        // yh name Map(2) {'name' => 'xx', 'age' => 3}
        // 3 'age' Map(2) {'name' => 'xx', 'age' => 3}
      })

      // Map的遍历顺序就是插入顺序
      // 通过第二参数,来绑定当前方法中的执行函数指向
      let arr = [1,2,3,4,5];
      arr.forEach(function(item){
        console.log(item);
        console.log(this);
      },m)

      // 箭头函数无效
      let res = arr.filter((item)=>{
        console.log(this);
        return item
      },arr)
与其他数据结构的互相转换
      // 转数组
      // 直接使用扩展运算符
      let m = new Map([
        ["name", "xx"],
        ["age", 18],
      ]);
      let arr = [...m];
      console.log(arr); // [Array(2), Array(2)]

      // 数组转Map
      // 将一个键值对数组传入Map构造函数,就可以转为Map
      let m2 = new Map([
        ["name", "xx"],
        ["age", 18],
      ]);
      console.log(m2); // {'name' => 'xx', 'age' => 18}

      // Map转为对象
      // 如果所有Map的键都是字符串,他可以无损的转为对象
      // 如果有非字符串的键名,那么这个键名就会被转为字符串,在作为对象的键名,所以如果有多个对象键名则转为普通对象后,只会留下最后一个。
      let obj = {};
      for(let [k,v] of m){
        obj[k] = v;
      }
      console.log(obj);

      let yh = {
        name:"笑笑"
      }
      let m3 = new Map([
        [undefined,"xx"],
        [null,"qx"],
        [{},"jh"],
        [yh,"yanhao"]
      ])
      let obj2 = {};
      for(let [k,v] of m3){
        obj2[k] = v;
      }
      console.log(obj2); // {undefined: 'yh', null: 'qx', [object Object]: 'yanhao'}

      // 对象转为Map
      // 利用Object.entries()方法,将对象转为一个键值对数组。
      // 将这个转换好的数组,作为Map结构初始化时的参数。
      let obj3 = {
        name:"xz",
        age:18,
        gender:"男"
      }
      let map = new Map(Object.entries(obj3));
      console.log(map);

Iterator和Generator 迭代器和生成器

Iterator 迭代器

迭代器就是一种机制,是一种帮助我们对某种数据结构进行遍历的对象
在js中迭代器是一个对象,这个对象符合迭代器协议:定义产生一系列值的标准方式。
在js中就是一个next方法。而这个方法有如下要求

  1. 无参数或者一个有参数的函数
  2. 返回一个应当有以下两个属性的对象
    done(boolean):表示迭代是否完成
    true:表示迭代已完成
    false:表示迭代没有完成
    value
    迭代器的返回值,done为true返回undefined(可以省略)
{
  next(){
    return {
      done:
      value:
    }
  }
}
  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值