【JavaScript】ES6,Proxy,Reflect,Promise,生成器,async/await

news2025/1/12 18:11:37

❤️ Author: 老九
☕️ 个人博客:老九的CSDN博客
🙏 个人名言:不可控之事 乐观面对
😍 系列专栏:

文章目录

  • ES6
    • 模板字符串,标签模板字符串
    • 函数的默认参数
    • 函数的剩余参数
      • 剩余参数和arguments有什么区别?
    • 箭头函数
    • 展开语法
      • 浅拷贝/深拷贝
    • Symbol
    • Set
    • Map
  • Proxy
  • Reflect
  • Promise
    • 异步处理代码的困境
    • promise的三种状态
    • resolve方法的参数
    • then方法
    • finally
    • promise中的类方法
    • resolve
    • reject
    • all
    • allSettled
    • race
  • 生成器
    • 生成器代替迭代器
    • 生成器yield*语法糖
  • 异步处理
    • async,await

ES6

  • ES6(ECMAScript 6)是JavaScript的第六个版本,也称为ECMAScript 2015。它是ECMAScript标准的一个重要更新,引入了许多新的语言特性和改进,为JavaScript开发者提供了更强大、更灵活的工具和语法。

模板字符串,标签模板字符串

  • 在ES6之前,拼接字符串很复杂,es6使用反引号和${}拼接字符串
  • 标签模板字符串:(用在styled-components库)
    在这里插入图片描述

函数的默认参数

  • es6增加了函数的默认参数

函数的剩余参数

  • 如果最后一个参数是…为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组,剩余参数要放在最后一个位置

剩余参数和arguments有什么区别?

  • 剩余参数值包含那些没有对应形参的实参,arguments对象包含传给函数所有的实参;
  • arguments对象不是一个真正的数组,而…参数是一个真正的数组,可以进行数组的所有操作
  • arguments是早期ECMAScript中为了方便去获取所有参数提供的一个数据结构,而。。。是es6中提供代替arguments的

箭头函数

  • 箭头函数没有显示原型Prototype的,不能作为构造函数
  • 箭头函数也不绑定,this,arguments,super参数

展开语法

  • 可以用在数组,字符串,对象中,在函数调用/数组构造时,将数组表达式或者string在语法层面展开

  • 还可以构造对象时,将对象表达式按照key-value的方式展开

  • 在这里插入图片描述

  • 展开语法是一个浅拷贝

浅拷贝/深拷贝

  • 这个就叫做引用赋值

- List item

  • 但是…运算符是浅拷贝,如果使用。。。展开运算符,改info就不会改变原来obj的值,而且如果有深层次的对象的话,我们知识复制了这个地址,并没有复制深层次的对象,这个就是浅拷贝
    在这里插入图片描述
  • 如果想实现深拷贝,需要自己实现。其中一种方法是利用JSON的机制来实现深拷贝。
    const info3 = JSON.parse(JSON.stringify(obj));
  • JSON深拷贝的弊端,函数和方法丢失:JSON只能序列化对象的数据,不能序列化对象的方法和函数。当进行深拷贝时,函数和方法将丢失,只有数据被复制。循环引用问题:如果对象存在循环引用,即对象之间相互引用,JSON无法正确处理这种情况。在序列化和反序列化过程中,JSON会陷入循环引用的无限循环中,导致堆栈溢出或内存泄漏。特殊对象丢失:JSON无法序列化特殊对象,例如正则表达式、日期对象、Map、Set等。这些对象在序列化和反序列化后,将丢失它们的原始类型和功能。原型链丢失:JSON无法序列化对象的原型链信息。在深拷贝后,所有对象的原型都将丢失,它们只是简单的数据对象,无法访问原型链上的方法和属性。

Symbol

  • ES6中新增的一个基本数据类型。
  • 在es6之前编写一个属性, 对象的属性名都是字符串,如果不是字符串,就会调用toString()方法改成字符串,那么很容易造成属性名冲突;
  • Symbol就是为了解决这个问题,用于生成一个独一无二的值。通过一个Symbol函数生成的 const s1 = Symbol(),es6之后,对象的属性名就既可以是字符串又可以是Symbol了
  • 使用方法的话可以这么写
    在这里插入图片描述
  • 通常我们获取对象的key的时候,通过Object.keys(obj)实现,但是这个方法获取不到Symbol作为key,需要通过Object.getOwnPropertySymbols(obj)单独获取Symbol作为key的字段
  • Symbol()里面的()可以描述Symbol,通过s.description可以获取Symbol的描述
  • 我们通过Symbol.for可以生成相同的Symbol

Set

  • 里面的数据不能重复,通过构造函数创建
  • 添加元素add,获取元素个数Size,删除一个元素delete返回boolean,清除所有元素clear,是否存在某个元素has,通过forEach/for of遍历Set
  • 作用:数组的去重,Array.from(new Set(数组))/[…new Set(数组)]

Map

  • 我们可以通过其他类型作为key,比如对象
  • 添加元素set(key, val),获取内容get,删除内容delete,判断内容has,清空clear方法,forEach方法直接获取对应的value,for of遍历获取的是整个的元素keyval都有

Proxy

  • 下面是vue2的响应式原理,但是这样写是有弊端的,首先Object.defineProperty的设计的初衷,不是为了去监听一个对象的所有属性,其次我们如果想监听更加丰富的操作,比如新增属性,删除属性,那么Object.defineProperty是不行的,这是就出现了Proxy对象,这个是专门用作监听对象而生成的。
      const keys = Object.keys(obj);
      for (const key of keys) {
        let value = obj[key];
        Object.defineProperty(obj, key, {
          set: function (newValue) {
            value = newValue;
          },
          get: function () {
            return value;
          },
        });
      }
  • 在ES6中,新增了一个Proxy类,帮助我们创建一个代理对象,如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象,之后对该对象的所有操作,都通过代理对象完成,代理对象可以监听我们想要对原对象进行哪些操作
  • 首先我们需要new Proxy对象,传入需要监听的对象和一个处理对象,称之为handler;const p = new Proxy(target,handler),之后我们所有的操作都是直接对Proxy对象的操作,而不是原有的对象
   var obj = {
        name: "lmp",
        age: 18,
        height: 1.88,
      };

      //1.创建一个代理对象
      const objProxy = new Proxy(obj, {
        //编写set和get捕获器
        //get函数有三个参数:1.target:目标对象(侦听的对象)
        //2.property:被捕获 的属性key
        //3.receiver:调用的代理对象
        get: function (target, key) {
          console.log(`监听${key}的获取`);
          return target[key];
        },
        //set函数有四个参数
        //1.target:目标对象
        //property:将被设置的属性key
        //value:新属性值
        //receiver:调用的代理对象
        set: function (target, key, newValue) {
          console.log(`监听${key}的设置值:`, newValue);
          target[key] = newValue;
        },
        deleteProperty: function (target, key) {
          delete obj.name;
        },
        has: function (target, key) {
          return key in target;
        },
      });

      //2.对obj的所有操作,应该去操作objProxy
      console.log(objProxy.name);
      objProxy.name = "why";
      delete objProxy.name;
      console.log(objProxy.name, 111);
  • 函数也是一个对象,所以函数也是可以监听的,监听器例如apply函数,construct函数

Reflect

  • 这个本身是一个对象,字面意思是反射,它提供了操作JavaScript对象的方法,类似于Object中操作对象的方法。例如获取原型对象Reflect.getPrototypeOf(target),定义对象属性Reflect.defineProperty(target,propertyKey,attributes)
  • 如果我们有Object可以做这些操作,为什么还需要Reflect这样的新增对象呢?
  • 早期的ECMA规范中没有考虑到对象本身的操作如何设计更加规范,所以将这些API放在Object上面,但是Object作为一个构造函数,放到它的身上是不合适的,ES6增加了Reflect,让这些操作都集中到了Reflect对象上
  • 区别1:delete操作,使用Reflecct.deleteProperty可以返回一个布尔值
    在这里插入图片描述
  • Reflect一般配合Proxy配合使用
      const objProxy = new Proxy(obj, {
        set: function (target, key, newValue, receiver) {
          //好处1:不再操作直接对象
          //好处2:Reflect.set方法有返回Boolean值,可以判断本次操作是否成功
          //好处3:Reflect可以设置Receiver
          /*
            receiver就是外层的Proxy对象
            Reflect.set/get最后一个receiver参数,可以决定对象访问器Setter/Getter的this指向,可以实现监听两次,默认this是指向元对象obj的,增加recceiver参数后,就可以改变this的指向了
          */
          const isSuccess = Reflect.set(target, key, newValue);
          if (!isSuccess) {
            throw new Error("error");
          }
        },
      });

Promise

异步处理代码的困境

  • 在以前都是自己设计异步代码,这样设计代码的和调用者可能不是同一个人,会有很多的麻烦
  function execCode(counter, successCallback, failCallback) {
        setTimeout(() => {
          if (counter <= 0) failCallback(`${counter}值有问题`);
          let total = 0;
          for (let i = 0; i < counter; i++) {
            total += i;
          }
          successCallback(total);
        }, 3000);
      }

      execCode(
        100,
        (total) => {
          console.log(total);
        },
        (err) => {
          console.log(err);
        }
      );
  • 因此出现了promise,promise就像一个通知器一样,告诉你成功了还是失败了
  • Promise是一个类,当我们需要的时候,promise给予调用者一个承诺,待会给你回调数据,当通过new创建Promise对象时,我们需要传入一个回调函数,称为executor,这个回调函数会立即执行,并传入另外两个回调函数,resolve,reject,分别对应.then,.catch,注意:一旦状态被确定,Promise的状态就会被锁死,不会改变
function execCode(counter) {
        const promise = new Promise((resolve, reject) => {
          setTimeout(() => {
            if (counter <= 0) {
              reject("error");
            }
            let total = 0;
            for (let i = 0; i < counter; i++) {
              total += i;
            }
            resolve(total);
          }, 3000);
        });

        return promise;
      }

      const promise = execCode(100);
      promise
        .then((value) => {
          console.log(value);
        })
        .catch((error) => {
          console.log(error);
        });

promise的三种状态

  • 当还没有调用回调函数(resolve,reject),处理待定状态;当操作成功,执行resolve,表示promise成功兑现,reject就是失败了。
  • Promise的状态一旦确定下来,就不会再更改,也不会再执行某一个回调函数来改变状态。

resolve方法的参数

  • resolve的括号里可以传什么值:1.普通值(字符串,对象,数组等)2.promise,如果传入的值是Promsie对象,那么当前的Promise的状态会由传入的Promise状态来确定

then方法

  • then方法可以传两个参数,第一个是成功的回调函数,第二个也可以传失败的回调函数.then(res=>{},err=>{})
  • promise.then之后的返回值是一个新的Promise对象,如果是链式调用的话,第二个then是等待第一个then的返回值进行决议的,如果抛出异常了,就会中断函数执行
    在这里插入图片描述

finally

  • 这个是ES9新增的方法,用在Promise中
    在这里插入图片描述

promise中的类方法

resolve

  • 上面的下面的代码是一样的
    在这里插入图片描述在这里插入图片描述

reject

  • 和resolve用法一样
    在这里插入图片描述

all

  • 将多个Promise包裹在一起形成一个新的Promise;新的Promise状态由包裹的所有Promise共同决定,当所有的Promise状态编程fulfilled状态时,新的Promise状态为fulfilled,并会将所有Promise的返回值组成一个数组;当由一个Promise状态为reject时候,新的Promise状态为reject,并会将第一个reject的返回值作为参数
    在这里插入图片描述

allSettled

  • all方法有一个缺陷,当其中一个Promise变成reject状态时,新的Promise就会立即变成对应的reject状态;那么对于resolved的,依然处于pending状态的Promise,我们获取不到对应的结果
  • 在ES11中,新增了allSettled的api,该方法会在所有Promise都有结果,无论是fulfilled还是rejected时,才会有最终的状态,并且这个Promise的结果一定是fulfilled的,返回的是一个数组对象,对象中一个是status是状态是rejected还是fulfilled,如果是reject,还有个字段就是reason,如果是fulfilled,就拿到value
    在这里插入图片描述

race

  • 如果有多个Promise相互竞争,谁先有结果,就用谁的。
    在这里插入图片描述

生成器

  • 生成器使ES6中新增的一种函数控制,使用的方案,它让我们更加灵活的控制函数什么时候继续执行,暂停执行。
  • 平时我们编写函数,这些函数种植的条件通常使返回值或者发生了异常
  • 生成器也是一个函数,但是和普通的函数有一些区别;
    1.生成器函数在function后面加一个*
    2.生成器函数可以通过yield关键字来控制函数的执行流程
    3.生成器函数返回值是一个Generator生成器,生成器是一种特殊的迭代器 ,要想生成器执行,调用它的next方法
    在这里插入图片描述
  • next的返回值跟迭代器对象一样,也是返回一个value和一个done,如果想返回value,可以在yield后面写上东西
    在这里插入图片描述
    在这里插入图片描述
  • 如果想传一个参数,写在yield前面加参数,第一次传参数传到foo
    在这里插入图片描述
    在这里插入图片描述
  • 如果想让生成器提前结束,通过return
    在这里插入图片描述
    在这里插入图片描述

生成器代替迭代器

在这里插入图片描述

生成器yield*语法糖

  • yield是一个语法糖,如果我们写成yield*,后面跟了一个可迭代对象,那么就可以自动每次迭代其中一个值

在这里插入图片描述

异步处理

  • 如果有一个需求第二次调用网络请求基于第一次,我们先封装了一个requestData的异步函数,可以使用callback,我们这里使用假promise,这样的话会导致回调地狱
 function requestData(url) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(url);
          });
        });
      }

在这里插入图片描述

  • 使用Promise进行重建,通过return出去给下一个请求调用,改为链式调用,而不是嵌套调用
    在这里插入图片描述

  • 我们可以通过生成器进行实现
    在这里插入图片描述

  • 最终通过async,await就可以实现
    在这里插入图片描述

async,await

  • 这是在ES7新增的语法,前面加上async的函数叫做异步函数
  • 异步函数返回一个promise
  • 在异步函数中,我们才可以使用await;await后面会跟上一个函数,这个函数返回一个Promise,然后await会等待Promise有结果之后,才会继续执行后续的代码,相当于把异步代码变成了同步代码
    在这里插入图片描述

————————————————————————
♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么要学习C++软件调试技术?掌握调试技术都有哪些好处?

目录 1、为什么要学习C软件调试技术&#xff1f; 1.1、IDE调试手段虽必不可少&#xff0c;但还不够 1.2、通过查看日志和代码去排查异常崩溃问题&#xff0c;费时费力&#xff0c;很难定位问 1.3、有的问题很难复现&#xff0c;可能只在客户的环境才能复现 1.4、开发联调工…

使用git远程上传github

如果你不是很熟悉git&#xff0c;在使用git前请先对你的项目进行备份 进入本地文件目录&#xff0c;打开git的cmd界面&#xff08;Git Bash Here&#xff09;如果当面目录使用过git&#xff0c;有.git隐藏文件&#xff0c;则跳过第二步&#xff0c;没有则输入以下命令 git ini…

零基础如何自学网络安全?

第一阶段&#xff1a;学习一种或几种编程语言。 网络安全也属于计算机范畴&#xff0c;涉及到IT行业的&#xff0c;编程语言是不可难免的。 《Head First Python(第2版)》 作为一种高级编程语言&#xff0c;Python越来越受到网络专家的欢迎。它之所以吸引人&#xff0c;主要…

【Java 28岁了】一个有趣的例子,再推荐一些经典好书(文末惊喜福利)

文章目录 1 写在前面2 C语言与Java语言的互相调用2.1 C语言调用Java语言2.2 Java语言调用C语言 3 友情推荐4 更多分享 1 写在前面 众所周知&#xff0c;C语言和Java语言是两种不同的编程语言&#xff0c;它们的关系可以描述为Java语言是在C语言的基础上发展而来的一种高级编程…

内网如何映射到公网访问互联网

我们通常会根据本地应用场景来选择合适的中间件来搭建服务器。tomcat、 apache是比较常用的搭建服务器的中间件&#xff0c;它们之间还是有一些区别差异的。在内网本地部署搭建服务器后&#xff0c;还可以通过快解析端口映射方法&#xff0c;将内网应用地址发布到互联网&#x…

Springboot +spring security,使用过滤器方式实现验证码功能

一.简介 在前面文章章节通过自定义认证器实现了验证码功能&#xff0c;这篇文章使用过滤器来实现验证码功能。 二.思路分析 实现逻辑和通过过滤器实现json格式登录一样&#xff0c;需要继承UsernamePasswordAuthenticationFilter&#xff0c;所以文档这块主要记录下代码实现…

每日一题——两数之和(返回下标和返回数值两种情况)

每日一题 两数之和 题目链接 思路 注&#xff1a;本题只采用暴力解法&#xff0c;时间复杂度为O(n2)&#xff0c;如果采用哈希表&#xff0c;可以将时间复杂度降到O(n)&#xff0c;但由于笔者还未对哈希表展开学习&#xff0c;故不做讨论 我们直接用两层for循环来解决问题 第…

安装部署 Mastodon 长毛象去中心化微博系统

注意&#xff1a;本文采用的为 Docker Compose 方式安装部署。 首先选择你安装的版本&#xff0c;有以下两种推荐&#xff1a; 官方版本&#xff1a; https://github.com/mastodon/mastodonGlitch 版本&#xff1a; https://github.com/glitch-soc/mastodon 项目包含一个 Doc…

不同的去耦电容 阻抗VS频率

不同的去耦电容 阻抗VS频率 • 并联电容可以在一个较宽的频带内降低阻抗 • 小的去耦电容尽可能靠近电源引脚 为什么每个电源引脚都需要去耦 去耦电容总结 • 旁路电容离电容引脚尽可能的近 • SMT磁珠对于降低Ripple非常有效 • 高频时需要地平面 – 最小化寄生参数 • 使用…

记两道小明文攻击题

题一 题目描述&#xff1a; flag **************************** flag "asfajgfbiagbwe" p getPrime(2048) q getPrime(2048) m1 bytes_to_long(bytes(flag.encode()))e1e2 3087 n p*q print()flag1 pow(m1,e1,n) flag2 pow(m1,e2,n) print(flag1 str(fla…

MATLAB 搜索某一点的R邻域点 (13)

MATLAB 搜索某一点的R邻域点 (13) 前言一、算法介绍1.1 :无序点云的R邻域点搜索1.2 :有序点云的R邻域点搜索二、具体实现示例2.1 算法一 (含详细注释)2.2 算法二 (含详细注释)前言 在点云处理中,最基本的算法之一就是搜索某一点的近邻点,这在重叠区域确定,点云密度…

Spring Gateway使用JWT实现统一身份认证

在开发集群式或分布式服务时&#xff0c;鉴权是最重要的一步&#xff0c;为了方便对请求统一鉴权&#xff0c;一般都是会放在网关中进行处理。目前非常流行的一种方案是使用JWT&#xff0c;详细的使用说明&#xff0c;可以找相关的资料查阅&#xff0c;这里先不进行深入的引用了…

鲸图知识图谱平台,助力金融业务深度洞察(上)

导语 大数据时代的背景下&#xff0c;数据早就成为数字经济重要的生产资料。对数据的挖掘能力成为企业数字化转型的驱动力。就金融行业来说&#xff0c;如果经营和管理方式跟不上大数据时代的发展脚步就会使得数据价值无法得到充分发挥。知识图谱作为一个结合了知识存储、知识…

SpringCloud入门概述;微服务入门概述

微服务入门概述 入门概述微服务分布式微服务架构Spring Cloud技术栈spring cloud各个组件的使用服务注册服务调用服务降级服务网关服务配置服务总线 参考 入门概述 auther JaneOnly date 2022/11/6 前置课程需要: java8mavengitNginxmqspringboot2.0 微服务 微服务架构就是一…

【阅读笔记】概率预测之DeepAR(含Pytorch代码实现)

本文作为自己阅读论文后的总结和思考&#xff0c;不涉及论文翻译和模型解读&#xff0c;适合大家阅读完论文后交流想法&#xff0c;关于论文翻译可以查看参考文献。论文地址&#xff1a;https://arxiv.org/abs/1704.04110 DeepAR 一. 全文总结二. 研究方法三. 结论四. 创新点五…

软件设计师--考前查漏补缺

软件设计师 上午题一、计算机系统二、操作系统三、数据库技术四、计算机网络五、软件工程概论六、程序设计语言与编译原理七、数据结构与算法八、算法分析与设计九、其他&#xff1a;标准化与知识产权、英语 下午题一、结构化分析设计二、数据库分析技术三、面向对象分析技术四…

代码随想录算法训练营第十四天|二叉树的遍历

这里主要掌握两种遍历方法&#xff1a;递归法和迭代法 递归法&#xff1a; 1、确定递归函数的参数和返回值&#xff0c;这里参数就是节点和用于存放节点数值的vector。 2、确认终止条件&#xff0c;这里的终止条件是节点为空。 3、确定单层递归逻辑&#xff0c;根据前序、中序…

随身WIFI折腾日记(三)---Docker+ssh远程访问+青龙面板

四、安装Docker 安装完Docker以后&#xff0c;我们便可以一键部署一些服务上去了。 sudo curl -fsSL get.docker.com -o get-docker.sh # 下载安装脚本 \&& sudo sh get-docker.sh --mirror Aliyun # 执行安装脚本 \&& sudo systemctl enable docker # 加入开…

一篇文章弄懂卷积神经网络基础概念

文章目录 一篇文章弄懂卷积神经网络基础概念下采样和上采样卷积普通卷积空洞卷积转置卷积膨胀卷积和转置卷积的区别 池化最大池化平均池化 全连接 一篇文章弄懂卷积神经网络基础概念 卷积神经网络可以说是图像处理的天花板&#xff0c;也是当下图像处理在深度学习方面最热门的…

2023/5/23总结

super关键字 super关键字的用法和this 关键字的用法相似 this:代表本类对象的引用&#xff08;this关键字指向调用该方法的对象一般我们是在当前类中使用this关键字&#xff0c;所以我们常说this代表本类对象的引用&#xff09;super:代表父类存储空间的标识(可以理解为父类对象…