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: 2const [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】(四)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day26 文件io

函数接口 1 .open和close 文件描述符&#xff1a;系统为用open打开的文件分配的标识符 非负的整形数据 0-1023 最小未被使用原则 使用完时及时释放&#xff0c;避免文件描述符溢出 文件描述溢出就是文件使用完没有及时关闭文件 int open(const char *pathname, int flags); /…

mysql索引的理解

1、索引是什么&#xff1f; 索引&#xff1a;简单理解就是我们字典的目录&#xff0c;一个索引可以找得到多个记录。 作用加快我们数据库的查询速度。索引本身较大&#xff0c;往往存储在磁盘的文件里。可能存储在单独的索引文件中&#xff0c;也可能和数据一起存储在数据文件…

Leetcode打卡:查询数组中元素出现的位置

执行结果&#xff1a;通过 题目 3159 查询数组中元素出现的位置 给你一个整数数组 nums &#xff0c;一个整数数组 queries 和一个整数 x 。 对于每个查询 queries[i] &#xff0c;你需要找到 nums 中第 queries[i] 个 x 的位置&#xff0c;并返回它的下标。如果数组中 x 的出…

Overleaf中设置表格中的字体为Times New Roman

在Overleaf中设置表格中的字体为Times New Roman 需要有这个字体包 使用 \usepackage{times} 宏包 在文档的导言区添加 \usepackage{times} 宏包,这将把整个文档的字体设置为Times New Roman,包括表格中的字体。例如:\documentclass{article} \usepackage{times} \begin{…

如何理解 CNN 中的 RGB 图像和通道?

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请参考这里。 在灰度图一节的最后&#xff0c;给出了一个由彩色图片转成灰度图的示例&#xff0c;并且通过 color_image.mode获取了图片的格式&#xff1a;彩色图片获取到的格式为 RGBA&a…

可灵1.6正式上线,图生视频再创新视界

大家最近有刷到过这几个视频吗&#xff1f; “一觉醒来&#xff0c;罗马斗兽场塌了”&#xff0c;可达鸭睡塌了罗马斗兽场&#xff01; 【视频来源于网络&#xff0c;侵删】 “卡比兽把一碗雪倒扣在富士山上&#xff0c;富士山瞬间被雪覆盖” 【图片来源于网络&#xff0c;侵删…

微积分复习(微分方程)

1,一阶微分方程 可分离的微分方程: 可以把x和y分列等号两边,然后求积分可以解决 齐次方程和准齐次方程 要求是 :yf(y/x),也就是没有单独的x项,我们可以通过设ty/x来统一变量方便我们运算 准齐次方程就是常数项不统一,我们可以将Xxa,Yyb来消灭常数项进而转化为齐次形式…

【火猫DOTA2】VP一号位透露队伍不会保留原阵容

1、最近VP战队的一号位选手Kiritych在直播中透露,VP战队的阵容将会有新的变动,原有的阵容将不再保留。 【目前VP战队阵容名单如下】 一号位:Kiritych 二号位:squad1x 三号位:Noticed 四号位:Antares 五号位:待定 2、Spirit的战队经理Korb3n在直播时谈到了越来越多的职业选…

两分钟解决:vscode卡在设置SSH主机,VS Code-正在本地初始化VSCode服务器

问题原因 remote-ssh还是有一些bug的&#xff0c;在跟新之后可能会一直加载初始化SSH主机解决方案 1.打开终端2.登录链接vscode的账号&#xff0c;到家目录下3.找到 .vscode-server文件,删掉这个文件4.重启 vscode 就没问题了

[银河麒麟] Geogebra

Geogebra 几何作图工具 是一款跨平台的几何作图工具软件&#xff0c; 目前已经覆盖了&#xff0c; windows&#xff0c;android&#xff0c; mac, linux 等操作系统。 Geogebra 官网 Geogebra 官网提供了 Geogebra 5.0 版本下载包, Linux Portable 双击 geogebra-portable…

一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类

机器学习实战通常是将理论与实践结合&#xff0c;通过实际的项目或案例&#xff0c;帮助你理解并应用各种机器学习算法。下面是一个简单的机器学习实战例程&#xff0c;使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集&#xff08;Iris Dataset&#xff09;**的…

浅谈下雪花算法的原理,及在项目中使用需要注意哪些事项

目录 背景 雪花算法原理 算法特点 注意事项 总结 背景 雪花算法是一种分布式ID生成算法&#xff0c;由Twitter提出&#xff0c;用于在分布式系统中生成全局唯一的ID。该算法通过将64位的长整型数字分为符号位、时间戳、工作机器ID和序列号四个部分&#xff0c;确保了ID的…

Kubernetes 安装 Nginx以及配置自动补全

部署 Nginx &#xff1a; [rootk8s-master ~]# kubectl create deployment nginx --imagenginx:1.14-alpine deployment.apps/nginx created暴露端口&#xff1a; [rootk8s-master ~]# kubectl expose deployment nginx --port80 --typeNodePort service/nginx exposed查看服…

C#使用Tesseract C++ API过程记录

Tesseract Tesseract 是一个开源的光学字符识别&#xff08;OCR&#xff09;引擎&#xff0c;最初由 Hewlett-Packard&#xff08;惠普&#xff09;实验室开发&#xff0c;后来由 Google 收购并继续维护和开源贡献。Tesseract 可以识别多种语言的文字&#xff0c;广泛应用于将…

在交叉编译中,常见的ELF(elf)到底是什么意思?

ELF 是 Executable and Linkable Format 的缩写&#xff0c;中文翻译为“可执行与可链接格式”。它是一种通用的文件格式&#xff0c;主要用于存储可执行文件、目标文件&#xff08;编译后的中间文件&#xff09;、动态库&#xff08;.so 文件&#xff09;以及内存转储文件&…

使 el-input 内部的内容紧贴左边

<el-inputv-model"form.invitor"placeholder"PC端的自动取当前账号的手机号"readonlyclass"no-border-input" />::v-deep(.no-border-input .el-input__inner) { border: none; box-shadow: none; padding-left: 0; /* 确保内容紧贴左边 *…

国标GB28181-2022平台EasyGBS:安防监控中P2P的穿透方法

在安防监控领域&#xff0c;P2P技术因其去中心化的特性而受到关注&#xff0c;尤其是在远程视频监控和数据传输方面。P2P技术允许设备之间直接通信&#xff0c;无需通过中央服务器&#xff0c;这在提高效率和降低成本方面具有明显优势。然而&#xff0c;P2P技术在实际应用中也面…

前端开发 -- 自动回复机器人【附完整源码】

一&#xff1a;效果展示 本项目实现了一个简单的网页聊天界面&#xff0c;用户可以在输入框中输入消息&#xff0c;并点击发送按钮或按下回车键来发送消息。机器人会根据用户发送的消息内容&#xff0c;通过关键字匹配来生成自动回复。 二&#xff1a;源代码分享 <!DOCTYP…

【速成51单片机】1.已经学过stm32如何快速入门51单片机——软件下载与安装

引言 本系列专题用于已经熟悉stm32单片机的情况下&#xff0c;快速掌握51单片机。背景是我其实大一大二已经进入学校实验室了&#xff0c;已经学习了stm32单片机&#xff0c;但是现在大三期末考51单片机&#xff0c;实际期末复习更应该看老师给的重点和背书上知识点。但我不想…

node-js Express防盗链

什么是防盗连 一个简单的说明&#xff0c;假如在前端img标签想要引用图片网站上的图片&#xff0c;当你将图片地址放到img标签上想要显示的时候你发现&#xff0c;图片显示不了&#xff0c;这说明网站采用了防盗链。 怎么实现的呢 在请求头中一般会有 Referer&#xff0c;它…