【H2O2|全栈】JS进阶知识(六)ES6(2)

目录

前言

开篇语

准备工作

Set和Map

基本概念

Set

相互转化

常见属性和API

数组去重

并集、交集和差集

Map

转化

常见的属性和API

Set和Map的区别

This的指向

function函数

箭头函数

修改this

使用方式

三种方式的异同

案例

更改this指向为obj

求数组数据最大值

闭包

概念

形式

优缺点

案例

事件绑定

稍微复杂一些的情况

结束语


前言

开篇语

本系列博客主要分享JavaScript的进阶语法知识,本期为第六期,依然围绕ES6的语法进行展开。

本期内容为:Set,Map,This指向和闭包。

与基础部分的语法相比,ES6的语法进行了一些更加严谨的约束和优化,因此,在之后使用原生JS时,我们应该尽量使用ES6的语法进行代码编写。

准备工作

软件:【参考版本】Visual Studio Code

插件(扩展包):Open in browser, Live Preview, Live Server, Tencent Cloud AI Code Assistant, htmltagwrap

提示:在不熟练的阶段建议关闭AI助手

浏览器版本:Chrome

系统版本: Win10/11/其他非Windows版本

Set和Map

基本概念

Set和Map是ES6新增的两种数据类型,它们本质上都是构造函数,使用new进行实例化。

Set中的数据项为单项,且可以实现自动去重

Map中的数据项为键值对,可以利用键进行增删改查

Set

相互转化

Set的构造器可以接收一个数组,即将数组转化成Set类型数据

基本形式如下——

let set = new Set(arr);

在这个过程中,数组arr中的重复数据将被自动去除。 

与之对应的,Set可以使用扩展运算符展开,并存入数组中。

基本形式如下——

let arr = [...set];

常见属性和API

属性/API作用
size获取Set的大小
add()增加数据,可以链式操作
delete()删除数据,不可链式操作
clear()清空Set
has()

查询是否含有某个元素,返回true/false

只可以查单层,如果有多层数组转成的Set集合,则查询第一层

数组去重

在数组==>Set==>数组的过程中,可以实现数组的去重操作。

于是,可以得到数组去重的最简单的方式——

arr = [...new Set(arr)];

并集、交集和差集

利用Set集合和数组的API结合,可以求两个数组之间的集合关系。

比如有下面这两个数组——

let arr1 = [1, 2, 5, 8]
let arr2 = [2, 5, 9, 11]

现在要求它们的并集,可以先将两个数组拼接起来,然后转成Set集合去重,最后转回数组。

let arr3 = [...new Set([...arr1, ...arr2])]

如果需要求它们的交集,可以现将其中的一个数组转为Set集合,利用另一数组的filter方法过滤出包含对方的数据。

let arr4 = arr1.filter(item => new Set(arr2).has(item))

如果需要求它们的差集,则只需要从并集中过滤出不是交集的部分即可。

let arr5 = arr3.filter(item => !arr4.has(item))

Map

转化

Map中存储的是键值对数据,所以它的构造器需要接受一个二维数组,每个元素的第一位是键,第二位是值,类似下面的形式——

var arr = [["key1", "value1"], ["key2", "value2"], ["key3", "value3"]]
let map = new Map(arr)

常见的属性和API

属性/API作用
size获取Map的大小
set(key, value)

没有key,则设置key => value对

有key,则修改key对应的value

delete()删除指定键值对
clear()清空Map()
get()查询某个键对应的值

Set和Map的区别

①应用场景:Set用于数据重组,Map用于数据储存;

②Set: 

(1)成员不能重复

(2)只有键值没有键名,类似数组

(3)可以遍历,方法有add, delete, has, clear

Map:

(1)本质上是健值对的集合,类似集合

(2)可以遍历,可以跟各种数据格式转换,方法有add, delete, set, has, clear

This的指向

function函数

命名函数,this指向window。

  function fn() {
    console.log(this);//window
  }

匿名函数,this指向window。

  let a = function () {
    console.log(this);//window
  };

立即调用函数,this指向window。

  (function () {
    console.log(this);//window
  })();

事件函数,this指向事件源。

  document.querySelector("#btn").onclick = function () {
    console.log(this);//事件源(btn)
  }

构造函数,this指向实例化对象。

  function Per(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
    this.fn = function () {
      console.log(this);//实例化对象
    }
  }

对象中的函数,this指向调用者。

  let obj = {
    fn: function() {
      console.log(this);//obj
    }
  }

箭头函数

箭头函数没有this指向,在箭头函数中的this指向为父级的this指向。

  let obj = {
    fn: () => {
      console.log(this);//window
    }
  }

修改this

使用方式

目前,有三种修改this指向的方式——call(),apply(),bind()。

call()的使用方式如下——

方法名.call(修改后的指向,参数1,参数2,……)

call的参数为枚举类型。

apply()的使用方式如下——

方法名.apply(修改后的指向,[参数1,参数2,……])

apply的参数为数组类型。

bind()的使用方式如下——

方法名.bind(修改后的指向,参数1,参数2,……) 

bind()的参数也是枚举类型。

三种方式的异同

三个的相同点:都用于修改this指向;

不同点:

1.调用方式不同:call和apply都是默认立即调用,bind返回函数体,需要手动调用(可以使用立即调用函数);

2.传参方式不同:call和bind都是枚举形式传参,apply为数组形式传参。

案例

更改this指向为obj

对于下面这段代码——

  var x = 1, y = 2
  var obj = {
    x: 3,
    y: 4
  }

  function fun() {
    console.log(this.x, this.y);
  }

上面的代码中,this的指向默认为window,所以这里输出的是window中的x和y的值。

如果想要输出obj中的x和y,可以使用下面的方式(示例)更改this指向——

  fun.call(obj)
求数组数据最大值

Math对象的max()方法可以用来求输入参数中的最大值,如果我们想要让传入的参数为一个数组,则需要使用到apply()方法。

这里我们不需要改变this指向,依然设置原来的指向Math.max。

let maxNum = Math.max.apply(Math.max, [1, 2, 3])

闭包

概念

js方法的作用域是静态的,是定义函数的作用域,不是执行的作用域

调用外部函数返回的内部函数后,即使外部函数已经执行完毕,被内部函数引用外部函数的变量依然会保存在内存中,这些引用了其他函数作用域变量的函数(或变量)以及这些被引用变量的集合,就是闭包。

形式

闭包的一种示例形式如下,b就是一种闭包(保存了方法内部变量a的值)。

  function fn() {
  // 函数作用域
    let a = 7
    return a
  }
  // 执行作用域
  let b = fn()

优缺点

优点:读取函数内部变量,使这些变量保存在内存中,不会在外部函数执行完毕后销毁。

缺点:内存消耗大,IE中会造成内存泄漏。

案例

事件绑定

还记得之前的经典案例li绑定点击事件吗,我们此前已经说过三种方式——

  • 绑定index属性
  • 使用let造成暂时性死区
  • forEach自行遍历

提示:lis为原生DOM获取的所有li。

方式一:

  for (var i = 0; i < lis.length; i++) {
    lis[i].setAttribute("index", i)
    lis[i].onclick = function () {
      console.log(this.getAttribute("index"));
    }
  }

方式二:

  for (let i = 0; i < lis.length; i++) {
    lis[i].onclick = function () {
      console.log(i);
    }
  }

 方式三:

  lis.forEach(function (item, index) {
    item.onclick = function () {
      console.log(index);
    }
  })

现在,我们补充一种使用闭包绑定li点击事件的方式。

首先,设定一个方法用来绑定当前的点击事件,而该方法的参数为当前的索引。

  let fn = function (index) {
    lis[index].onclick = function () {
      console.log(index);
    }
  }

由于index为方法内部的变量,所以我们可以使用一个外部变量来记住index。

而这个外部变量,其实也就是当前的索引值,我们只需要把当前索引值传入fn的形参列表即可。

而我们知道,在for-i遍历中,绑定事件之前的i是可以作为当前li的索引的。

所以,直接传入当前遍历变量i的值即可。

  fn(i)

上述代码可以写成立即调用函数的形式,完整代码如下——

  for (var i = 0; i < lis.length; i++) {
    (function (index) {
      lis[index].onclick = function () {
        console.log(index);
      }
    })(i)
  }

稍微复杂一些的情况

下面这个闭包的使用稍稍复杂一点,代码如下——

  var name = "The Window";

  var object = {
    name: "MyObject",
    getNameFunc() {
      console.log(this.name, this); // 1
      return function () {
        console.log(this); // 2
        return this.name;
      };
    }
  };

  object.getNameFunc();
  object.getNameFunc()();
  console.log(object.getNameFunc()());

现在,问最后三行代码会输出什么结果?

首先,看到第一行输出,调用了object对象的getNameFunc()方法,所以首先会输出语句1的内容,即MyObject  object。

而方法的返回值为一个匿名方法,而该行输出中没有调用这个方法,所以该方法没有执行。

接下来,看到第二行输出,调用了object对象的getNameFunc()方法的返回值中的匿名方法。

当然,首先还是先输出和第一行中相同的输出,即MyObject  object。

然后,立即调用匿名方法,输出语句2的内容,对于这个匿名方法,相当于一个闭包,记录了方法内部的返回值,实质上是在全局执行的,所以输出window。

同样的,匿名方法的返回值没有使用到,所以没有输出。

最后,看到第三行输出, log将最后匿名方法返回的值也输出出来了,而匿名方法是在全局执行的,所以此时的this.name为全局的name。

结束语

本期内容到此结束。关于本系列的其他博客,可以查看我的JS进阶专栏。

在全栈领域,博主也只不过是一个普通的萌新而已。本系列的博客主要是记录一下自己学习的一些经历,然后把自己领悟到的一些东西总结一下,分享给大家。

文章全篇的操作过程都是笔者亲自操作完成的,一些定义性的文字加入了笔者自己的很多理解在里面,所以仅供参考。如果有说的不对的地方,还请谅解。

==期待与你在下一期博客中再次相遇==

——临期的【H2O2】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921611.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Node基本使用

1. 创建自定义全局指令 1.1 新建一个空的文件夹, 创建一个cli.js文件 1.2 在cli.js写入内容 /usr/bin/env就是让系统使用node来执行你的脚本文件。 #! /usr/bin/env node1.3 执行终端指令 // 在文件夹 node-project 的终端下执行指令npm init执行完后package.json结构如下,…

Python编程技巧:多变量赋值的优雅艺术

在Python编程的世界里&#xff0c;有许多令人惊叹的语法特性&#xff0c;而多变量赋值就像是一颗闪耀的明珠&#xff0c;它不仅让代码更优雅&#xff0c;还能提升程序的执行效率。今天我们就深入探讨这个看似简单却蕴含深意的编程技巧。 基础认识 传统的变量赋值方式&#xff…

Transformer架构笔记

Attention is All You Need. 3.Model Architecture 3.1 整体架构如图 3.2 Encoder与Decoder Encoder&#xff1a;由 N 6 N6 N6个相同的Block/Layer堆叠而成。每个Block有两个子层sub-layer&#xff1a;多头注意力和MLP&#xff08;FFN&#xff0c;前馈神经网络&#xff09;&…

网络安全简单入门与扫描

网络安全简单入门 内容大纲 策略制定安全工具其他 1、安全策略 1.1、安全三要素 要全面地认识一个安全问题,我们有很多种办法,但首先要理解安全问题的组成属性。前人通过无数实践,最后将安全的属性总结为安全三要素,简称CIA。 安全三要素是安全的基本组成元素,分别是机密性…

在WPF程序中实现PropertyGrid功能

使用C#开发过Windows Forms的都知道&#xff0c;在Windows Forms程序中&#xff0c;有一个PropertyGrid控件&#xff0c;可以用于显示对象的属性&#xff0c;在WPF中并没有默认提供此功能的控件&#xff0c;今天以一个简单的小例子&#xff0c;简述在WPF中借助WinForm的Propert…

大模型时代的具身智能系列专题(十四)

冯晨团队 冯晨是纽约大学的副教授。他对通过多学科使用启发研究实现机器人主动和协作感知和学习感兴趣&#xff0c;这些研究源自建筑、制造和运输领域。在纽约大学之前&#xff0c;冯晨是马萨诸塞州剑桥市三菱电机研究实验室 (MERL) 计算机视觉小组的研究科学家&#xff0c;专…

力扣-Hot100-栈【算法学习day.40】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

RT_Thread内核源码分析(三)——线程

目录 1. 线程结构 2. 线程创建 2.1 静态线程创建 2.2 动态线程创建 2.3 源码分析 2.4 线程内存结构 3. 线程状态 3.1 线程状态分类 3.2 就绪状态和运行态 3.3 阻塞/挂起状态 3.3.1 阻塞工况 3.4 关闭状态 3.4.1 线程关闭接口 3.4.2 静态线程关闭 3.4.3 动态线程关…

043 商品详情

文章目录 详情页数据表结构voSkuItemVo.javaSkuItemSaleAttrVo.javaAttrValueAndSkuIdVo.javaSpuAttrGroupVo.javaGroupAttrParamVo.java pom.xmlSkuSaleAttrValueDao.xmlSkuSaleAttrValueDao.javaAttrGroupDao.xmlAttrGroupServiceImpl.javaSkuInfoServiceImpl.javaSkuSaleAtt…

硬件知识 cadence16.6 原理图输出为pdf 网络名下划线偏移 (ORCAD)

1. cadence原理图输出为PDF网络名下划线偏移 生这种情况的原因 1. 设计的原理图图纸大小比正常的 A4图纸大。 2. 打印为PDF 的时候&#xff0c;打印机的设置有问题。 2.cadence原理图输出为 PDF网络名下划线偏移的情况 可以看到上图&#xff0c;网络名往上漂移。 3. 解决办法 …

Spring-boot3.4最新版整合swagger和Mybatis-plus

好家伙,今天终于开始用spring-boot3开始写项目了&#xff0c;以后要彻底告别1.x和2.x了&#xff0c;同样的jdk也来到了最低17的要求了,废话不多说直接开始 这是官方文档的要求jdk最低是17 maven最低是3.6 一. 构建工程,这一步就不需要给大家解释了吧 二. 整合Knife4j 1.大于 …

从零开始:如何使用第三方视频美颜SDK开发实时直播美颜平台

开发一个具有实时美颜功能的直播平台&#xff0c;能够显著提高用户体验和内容质量。而利用第三方视频美颜SDK可以大大简化开发过程&#xff0c;加快产品上市速度。本篇文章&#xff0c;小编将从零开始&#xff0c;详细讲解如何使用第三方视频美颜SDK开发一个实时直播美颜平台。…

ROS入门学习ONE

ros入门玩法1&#xff1a;控制小龟龟 终端1输入 sudo apt install ros-noetic-rqt-steering 新建终端2&#xff08;快捷键CtrlAltT)&#xff0c;打开控制台 roscore //启动ros系统 回到原终端 rosrun rosrun rqt_robot_steering rqt_robot_steering 新建终端3&#xff0c;…

shell脚本(二)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

简单理解下基于 Redisson 库的分布式锁机制

目录 简单理解下基于 Redisson 库的分布式锁机制代码流程&#xff1a;方法的调用&#xff1a;具体锁的实现&#xff1a;riderBalance 方法&#xff1a;tryLock 方法&#xff08;重载&#xff09;&#xff1a;tryLock 方法&#xff08;核心实现&#xff09;&#xff1a; 简单理解…

小鹏汽车智慧材料数据库系统项目总成数据同步

1、定时任务处理 2、提供了接口 小鹏方面提供的推送的数据表结构&#xff1a; 这几个表总数为100多万&#xff0c;经过条件筛选过滤后大概2万多条数据 小鹏的人给的示例图&#xff1a; 界面&#xff1a; SQL: -- 查询车型 select bmm.md_material_id, bmm.material_num, bm…

LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))

【LetMeFly】3244.新增道路查询后的最短距离 II&#xff1a;贪心&#xff08;跃迁合并&#xff09;-9行py&#xff08;O(n)&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/shortest-distance-after-road-addition-queries-ii/ 给你一个整数 n 和一个二维…

华为无线AC+AP组网实际应用小结

之前公司都是使用的H3C的交换机、防火墙以及无线AC和AP的&#xff0c;最近优化下无线网络&#xff0c;说新的设备用华为的&#xff0c;然后我是直到要部署的当天才知道用华为设备的&#xff0c;就很无语了&#xff0c;一点准备没有&#xff0c;以下为这次的实际操作记录吧&…

Fakelocation Server服务器/专业版 Windows11

前言:需要Windows11系统 Fakelocation开源文件系统需求 Windows11 | Fakelocation | 任务一 打开 PowerShell&#xff08;以管理员身份&#xff09;命令安装 Chocolatey Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProto…

C语言基础学习:抽象数据类型(ADT)

基础概念 抽象数据类型&#xff08;ADT&#xff09;是一种数据类型&#xff0c;它定义了一组数据以及可以在这组数据上执行的操作&#xff0c;但隐藏了数据的具体存储方式和实现细节。在C语言中&#xff0c;抽象数据类型&#xff08;ADT&#xff09;是一种非常重要的概念&…