js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)

目录

Proxy

Reflect

静态方法

部分实例

Iterator

实际开发迭代器的使用实例

迭代器(Iterator)应用

Generator

Proxy

Proxy 是 ES6 中新增的对象

  • Proxy 是JavaScript中的内置对象,它提供了一种机制,可以拦截并自定义各种操作,如属性访问、函数调用、构造函数调用等。
  • Proxy 构造函数接受两个参数目标对象(被代理的对象)和一个处理器对象(用于定义拦截器)。
// 写法:target是目标对象,handler是处理器对象
const proxy = new Proxy(target, handler);

 详解请看:ES6之---Proxy简介

Reflect

Proxy 是 ES6 中新增的对象【:不可使用new操作符生成实例】

特点:

  • 将 Object 对象的一些明显属于语言内部的方法(如 Object.defineProperty)放到 Reflect 对象上,现阶段,某些方法同时在 Object 和 Reflect 对象上部署,未来新的方法只在 Reflect 对象上部署。也就是说,从 Reflect 对象上可以获得语言内部的方法。
  • 修改某些Object的内部方法返回结果,使其变的合理。(以Object.defineProperty为例, 现在如果没有办法定义时,则会报错,放在Reflect上面,则会返回false)
  • 让 Object 操作都编程函数行为,某些 Object 操作是命令式,比如 name in obj 和 delete obj [name],而 Reflect.has(obj, name) 和 Reflect.deleteProperty(obj, name) 让它们变成了函数行为。
  • Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法,这就是 Proxy 对象可以方便的调用对应的 Reflect 方法来完成默认行为,作为修改行为的基础。也就是说,无论 Proxy 怎么修改默认行为,我们总可以在 Reflect 上获取到默认行为。

静态方法

  • Reflect.apply
  • Reflect.construct
  • Reflect.defineProperty
  • Reflect.deleteProperty
  • Reflect.get
  • Reflect.getOwnPropertyDescriptor
  • Reflect.getPrototypeOf
  • Reflect.has
  • Reflect.isExtensible
  • Reflect.ownKeys
  • Reflect.preventExtensions
  • Reflect.set
  • Reflect.setPrototypeOf

部分实例

Reflect.construct(target, args)

  • Reflect.construct 方法等同于 new target(…args),这提供了一种不使用 new ,来调用构造函数的方法。
  • 如果 Reflect.construct () 方法的第一个参数不是对象,会报错。
// 说明1的例子如下: 
function Greeting(name) {
  this.name = name;
}
// new 的写法
const instance = new Greeting('张三');
// Reflect.construct 的写法
const instance1 = Reflect.construct(Greeting, ['张三']); // {name: '张三'}
// 说明2的例子如下: 
console.log(Reflect.construct(1, 'baz'))  // TypeError: Reflect.construct called on non-object

Reflect.deleteProperty(target, name)

  • Reflect.deleteProperty方法等同于delete obj[name],用于删除对象的属性。
  • 注意:**如果删除成功,或者被删除的属性不存在,返回 true ;删除失败,被删除的属性依然存在,返回 false **
  • 如果 Reflect.deleteProperty() 方法的第一个参数不是对象,会报错。
// 说明1,2的例子如下: 
var myObject = {
  foo: 1,
}
console.log(Reflect.deleteProperty(myObject, 'foo')) // true
console.log(Reflect.deleteProperty(myObject, 'zzz')) // true
// 此时的myObject 就是{}

Reflect.get(target, name, receiver)

  • Reflect.get方法查找并返回 target 对象的 name 属性值,如果没有该属性,则返回 undefined 。
  • 如果 name 属性部署了读取函数(getter),则读取函数的 this 绑定 receiver 。
  • 如果第一个参数不是对象, Reflect.get 方法会报错。
// 说明1的例子如下: 
var myObject = {
  foo: 1,
  bar: 2,
  get baz() {
    return this.foo + this.bar;
  },
}
console.log(Reflect.get(myObject, 'foo')) // 1 
console.log(Reflect.get(myObject, 'bar')) // 2
console.log(Reflect.get(myObject, 'baz')) // 3 没有传receiver,则this取原对象
console.log(Reflect.get(myObject, 'zzz')) // undefined
// 说明2的例子如下: 
const otherObject = {
	foo: 3,
	bar: 4
}
console.log(Reflect.get(myObject, 'baz', otherObject)) // 7
// 说明3的例子如下: 
console.log(Reflect.get(1, 'baz'))  // TypeError: Reflect.get called on non-object

Reflect.has(target, name) 

  • Reflect.has方法对应name in obj里面的in运算符。
  • 如果 Reflect.has() 方法的第一个参数不是对象,会报错。
// 说明1的例子如下: 
var myObject = {
  foo: 1,
}
console.log(Reflect.has(myObject, 'foo')) // true
console.log(Reflect.has(myObject, 'zzz')) // false
// 说明2的例子如下: 
console.log(Reflect.has(1, 'baz'))  // TypeError: Reflect.has called on non-object

观察者模式实例

// 这里就是简单观察者的核心逻辑,主要实现两个功能,一个就是observe,另一个就是observable
// 先定义了一个Set 集合,所有观察者函数都放进这个集合。
// observable 函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数
// 拦截函数 set 之中,会自动执行所有观察者
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});
function set(target, key, value, receiver) {
  const result = Reflect.set(target, key, value, receiver);
  queuedObservers.forEach(observer => observer());
  return result;
}
// 使用如下:
const person = observable({
  name: '张三',
  age: 20
});
function print() {
  console.log( ${person.name}, ${person.age} )
}
observe(print);
person.name = '李四';

Iterator

Iterator即迭代器,它是一种接口,为各种不同的数据结构提供了统一的访问机制,换句话说,只要有任何数据结构部署了迭代接口,就可以使用统一的方式的来遍历它。

ES6为数组和普通对象,以及新增的Map和Set提供了统一的遍历机制:迭代器(Iterator),并新增了for … of语法来使用迭代器。

实现可迭代接口的数据结构,一般都自身实现或继承了以Symbol.iterator属性的,就属于可迭代对象。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。

一个包含next()方法的对象,才可以称为一个迭代对象。next()对象的会有返回一个对象,对象中包含两个值,如下所示:

  • value:迭代器返回的任何JavaScript值。donetrue时可省略。
  • done:一个布尔值,为false时表示迭代未停止,为true时立即停止迭代器,且可以省略value的值。

实际开发迭代器的使用实例

实际开发中,为每一个对象单独定义一个迭代器属性实在不是一件聪明事。我们可以仿照js引擎部署迭代器的做法,将迭代器署在对象原型上,这样由某个构造函数或类(指es6的class)所生成的每个对象都可以方便地进行遍历了。 

构造函数写法

function Student(name, age){
  this.name = name;
  this.age = age;
}
Student.prototype[Symbol.iterator] = function(){
  let index = 0;
  let keys = [...Object.keys(this)];
  let _this = this;
  keys.sort((key1, key2) => { //按字母顺序对属性排序
    return key1 < key2 ? -1 : 1;
  })
  return {
    next(){
      return index < keys.length ?
      			{value: _this[keys[index++]], done: false} :
      			{value: undefined, done: true}
    }
  }
}


let s = new Student('小明', 24);
for(let val of s){
  console.log(val);
}  //输出:24 '小明'

类写法

class Student{
  constructor(name, age){
    this.name = name;
    this.age = age;
  }
  
  [Symbol.iterator](){
    let index = 0;
    let keys = [...Object.keys(this)];
    keys.sort((key1, key2) => { //按字母顺序对属性排序
      return key1 < key2 ? -1 : 1;
    })
    let _this = this;
    
    return {
      next(){
        return index < keys.length ?
      			{value: _this[keys[index++]], done: false} :
      			{value: undefined, done: true}
      }
    }
  }
}

迭代器(Iterator)应用

【1】 解构赋值

Array和Set的解构赋值就是借助迭代器来实现的

js引擎依次在左右两侧结构上调用next方法,进行逐个赋值,这样左侧数组的每个变量会对应被赋为右侧的值。

const [a, b] = [1, 2];             //a: 1, b: 2

const [c, d] = new Set([3, 4]);    //c: 3, d: 4

【2】扩展运算符

ES6的扩展运算符可以将数组展开为一列,这也是借助Iterator接口实现的

let args = ['name', 'age'];
f(...args);                    //等价于f('name', 'age')

【3】return和throw

迭代器对象除了必要的next方法外,还可以部署return和throw方法,用于在for … of语句中终止遍历和抛出异常。

let s = {
  name: '小明',
  age: 24,

  [Symbol.iterator]: function (){
    let index = 0;
    let keys = ['name', 'age'];
    let _this = this;
    
    return {
      next(){
        return index < keys.length ?
        		{value: _this[keys[index++]], done: false} :
        		{value: undefined, done: true}
      },
      return(){
        ...  //结束循环前可以在这里执行某些操作,如关闭文件系统等
        return {done: true}
      },
      throw(){
        ...  //抛出异常时可以在这里执行某些操作
        return {done: true}
      }
    }
  }
}

for(let val of s){
  console.log(val);
  break;   //该语句会触发迭代器对象的return方法
}

for(let val of s){
  console.log(val);
  throw new Error(); //该语句会触发迭代器对象的throw方法
}

【4】Iterator与Generator函数

Generator函数调用之后返回的就是一个迭代器对象,这个对象原生就具备next接口

let s = {
  name: '小明',
  age: 24,

  [Symbol.iterator]: function* (){
    yield this.name;
    yield this.age;
  }
}

Generator 

Generator【生成器】是ES6中提供的一种异步编程解决方案定义Generator函数在function关键字和函数名中间使用*星号,函数内部使yield关键字定义不同的状态

注:需要注意的是,生成器函数定义时需要在函数关键字 function 后面加上星号(*),以标识该函数为生成器函数。另外,yield 关键字只能在生成器函数内部使用

function* testGenerator(){
    // yield定义一个状态
    yield1 'css6之generator'
    yield 'es新特性'
    return 'generator'        // 终结Generator,后面即使有yield关键字也无效
}
const g=testGenerator()       // 返回 Generator 对象,通过next()方法移动状态

g.next()                      //{value:'-碗周',done:false }
g.next()                      //{value:'es新特性',done:false }
g.next()                      //{ value:generator',done:true }

Generator详解

此文借鉴了一下博主的优秀文章

https://blog.csdn.net/Rookie_lei/article/details/140790532

https://blog.csdn.net/qq_41694291/article/details/103432571

上一章:js版本之ES6特性简述【let和const、数组、函数、集合、Symbol】(四)

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

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

相关文章

电脑配置maven-3.6.1版本

不要使用太高的版本。 apache-maven-3.6.1-bin.zip 下载这个的maven压缩包 使用3.6.1版本。 解压缩放在本地软甲目录下面&#xff1a; 配置系统环境变量 在系统环境下面配置MAVEN_HOME 点击path 新增一条 在cmd中输入 mvn -v 检查maven的版本 配置阿里云镜像和本地的仓库 …

Python基础语法知识——数据类型的查询、数据类型转化

今天第一次学习python&#xff0c;之前学习过C&#xff0c;感觉学习起来还可以&#xff0c;就是刚用的时候有点手残&#xff0c;想的是python代码&#xff0c;结果写出来就是C,本人决定每天抽出时间写点。同时继续更新NX二次开发专栏学习&#xff0c;话不多说&#xff0c;晚上的…

Boost之log日志使用

不讲理论&#xff0c;直接上在程序中可用代码&#xff1a; 一、引入Boost模块 开发环境&#xff1a;Visual Studio 2017 Boost库版本&#xff1a;1.68.0 安装方式&#xff1a;Nuget 安装命令&#xff1a; #只安装下面几个即可 Install-package boost -version 1.68.0 Install…

C语言初阶习题【17】求N的阶乘( 递归和非递归实现)

1.题目 2.分析 非递归 需要用到循环&#xff0c;n个数就是循环n次&#xff0c;每次和之前的乘起来 例如 5的阶乘 就是 5*4 *3 *2 *1 循环1到5 。需要一个变量来接收每次的结果 注意这个地方是乘&#xff0c;所以要从1 开始&#xff0c;sum 也需要是1而不是0 for(i 1&#xf…

云效流水线自动化部署web静态网站

云效流水线部署静态网站 背景新建流水线配置流水线运行流水线总结 背景 配置流水线以前&#xff0c;每次更新导航网站都要登进去宝塔后台&#xff0c;删掉旧的目录和文件&#xff0c;再上传最新的文件&#xff0c;太麻烦啦 网上的博客基本都是分享vue项目&#xff0c;这一篇是…

【开源项目】数字孪生化工厂—开源工程及源码

飞渡科技数字孪生化工厂管理平台&#xff0c;基于自研孪生引擎&#xff0c;将物联网IOT、人工智能、大数据、云计算等技术应用于化工厂&#xff0c;为化工厂提供实时数据分析、工艺优化、设备运维等功能&#xff0c;助力提高生产效率以及提供安全保障。 通过可视化点位标注各厂…

SpringCloud整合skywalking实现链路追踪和日志采集

1.部署skywalking https://blog.csdn.net/qq_40942490/article/details/144701194 2.添加依赖 <!-- 日志采集 --><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version&g…

Linux下Nvidia显卡GPU开启驱动持久化

GPU开启驱动持久化的原因 GPU 驱动一直处于加载状态&#xff0c; 减少运行程序时驱动加载的延迟。不开启该模式时&#xff0c;在程序每次调用完 GPU 后&#xff0c; GPU 驱动都会被卸载&#xff0c;下次调用时再重新加载&#xff0c; 驱动频繁卸载加载&#xff0c; GPU 频繁被…

图像处理-Ch4-频率域处理

Ch4 频率域处理(Image Enhancement in Frequency Domain) FT &#xff1a;将信号表示成各种频率的正弦信号的线性组合。 频谱&#xff1a; ∣ F ( u , v ) ∣ [ R 2 ( u , v ) I 2 ( u , v ) ] 1 2 |F(u, v)| \left[ R^2(u, v) I^2(u, v) \right]^{\frac{1}{2}} ∣F(u,v)…

虚拟化 | Proxmox VE 8.x 开源的虚拟化平台快速上手指南

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x00 简介说明 前言简述 描述:作为一个爱折腾的IT打工佬,时刻以学习各类新技术新知识为目标,这不正好有一台部署了VMware vSphere ESXi 虚拟化环境的服务器,由于正好安装其系统的磁盘有坏道,经常导致使用 ESXi 异…

rocketmq-push模式-消费侧重平衡-类流程图分析

1、观察consumer线程 使用arthas分析 MQClientFactoryScheduledThread 定时任务线程 定时任务线程&#xff0c;包含如下任务&#xff1a; 每2分钟更新nameServer列表 每30秒更新topic的路由信息 每30秒检查broker的存活&#xff0c;发送心跳请求 每5秒持久化消费队列的offset…

使用亚马逊针对 PyTorch 和 MinIO 的 S3 连接器实现可迭代式数据集

2023 年 11 月&#xff0c;Amazon 宣布推出适用于 PyTorch 的 S3 连接器。适用于 PyTorch 的 Amazon S3 连接器提供了专为 S3 对象存储构建的 PyTorch 数据集基元&#xff08;数据集和数据加载器&#xff09;的实现。它支持用于随机数据访问模式的地图样式数据集和用于流式处理…

[2003].第2-01节:关系型数据库表及SQL简介

所有博客大纲 后端学习大纲 MySQL学习大纲 1.数据库表介绍&#xff1a; 1.1.表、记录、字段 1.E-R&#xff08;entity-relationship&#xff0c;实体-联系&#xff09;模型中有三个主要概念是&#xff1a; 实体集 、 属性 、 联系集2.一个实体集&#xff08;class&#xff09…

wps透视数据表

1、操作 首先选中你要的行字段表格 -> 插入 -> 透视数据表 -> 拖动行值&#xff08;部门&#xff09;到下方&#xff0c;拖动值&#xff08;包裹数量、运费&#xff09;到下方 2、删除 选中整个透视数据表 -> delete 如图&#xff1a;

Python-流量分析常用工具脚本(Tshark,pyshark,scapy)

免责声明&#xff1a;本文仅作分享~ 目录 wireshark scapy 例&#xff1a;分析DNS流量 检查数据包是否包含特定协议层&#xff08;过滤&#xff09; 获取域名 例&#xff1a;提取 HTTP 请求中的 Host 信息 pyshark 例&#xff1a;解析 HTTP 请求和响应 例&#xff1a;分…

开发场景中Java 集合的最佳选择

在 Java 开发中&#xff0c;集合类是处理数据的核心工具。合理选择集合&#xff0c;不仅可以提高代码效率&#xff0c;还能让代码更简洁。本篇文章将重点探讨 List、Set 和 Map 的适用场景及优缺点&#xff0c;帮助你在实际开发中找到最佳解决方案。 一、List&#xff1a;有序存…

[2029].第6-06节:MyISAM引擎中的索引与 InnoDB引擎中的索引对比

所有博客大纲 后端学习大纲 MySQL学习大纲 1.MyISAM索引&#xff1a; 1.1.B树索引适用存储引擎&#xff1a; 1.B树索引适用存储引擎如下表所示&#xff1a; 2.即使多个存储引擎都支持同一种类型的B树索引&#xff0c;但它们的实现原理也是不同的 Innodb和MyISAM默认的索引是B…

DS的使用

使用DS和[address]实现字的传送 要解决的问题:CPU从内存单元中要读取数据 要求&#xff1a;CPU要读取一个内存单元的时候&#xff0c;必须先给出这个内存单元的地址。 原理&#xff1a;在8086PC中&#xff0c;内存地址段地址和偏移地址组成(段地址:偏移地址) 解决方案 :DS和[a…

使用RKNN进行YOLOv8人体姿态估计的实战教程:yolov8-pose.onnx转yolov8-pose.rknn+推理全流程

之前文章有提到“YOLOv8的原生模型包含了后处理步骤,其中一些形状超出了RK3588的矩阵计算限制,因此需要对输出层进行一些裁剪”,通过裁剪后得到的onnx能够顺利的进行rknn转换,本文将对转rnkk过程,以及相应的后处理进行阐述。并在文末附上全部源码、数据、模型的百度云盘链…

短视频矩阵系统后端源码搭建实战与技术详解,支持OEM

一、引言 随着短视频行业的蓬勃发展&#xff0c;短视频矩阵系统成为了众多企业和创作者进行多平台内容运营的有力工具。后端作为整个系统的核心支撑&#xff0c;负责处理复杂的业务逻辑、数据存储与交互&#xff0c;其搭建的质量直接影响着系统的性能、稳定性和可扩展性。本文将…