ECMAScript 6 新特性(二)

ECMAScript 6 新特性(二)

ECMAScript 6 新特性(一)

ECMAScript 6 新特性(二)(本文)

ECMAScript 7~10 新特性

1. 生成器

生成器函数是 ES6 提供的一种解决异步编程方案,一种特殊的函数,语法行为与传统函数完全不同。

function* gen() {yield 1; // yield 关键字用来暂停函数的执行yield 2;yield 3;
}let iterator = gen();
// 调用
// console.log(iterator); // 不能调用
// iterator.next(); // 正常调用// for (let v of gen()) {
//     console.log(v); // 每次返回一个 yield 的值
// }
// 等同于
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

代码说明:

  1. * 的位置没有限制;
  2. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值;
  3. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码;
  4. next 方法可以传递实参,作为 yield 语句的返回值 。

1.1 生成器函数参数

function* gen(arg) {console.log(arg);let one = yield 1;console.log(one);let two = yield 2;console.log(two);let three = yield 3;console.log(three);
}let iterator = gen("aaaaa");
console.log(iterator.next());
// next 方法可以传入实参,传入参数会被赋值给 yield 表达式的值
console.log(iterator.next("BBB"));
console.log(iterator.next("CCC"));
console.log(iterator.next('DDD'));

1.2 实例

  1. 1s后控制台输出111,2s后输出222,3s后输出333

    传统实现

    setTimeout(() => {console.log("111");setTimeout(() => {console.log("222");setTimeout(() => {console.log("333");}, 3000);}, 2000);
    }, 1000);
    

    代码较为复杂,不易扩展,使用生成器函数实现

    function one() {setTimeout(() => {console.log("111");iterator.next();}, 1000);
    }
    function two() {setTimeout(() => {console.log("222");iterator.next();}, 2000);
    }
    function three() {setTimeout(() => {console.log("333");iterator.next();}, 3000);
    }function* gen() {yield one();yield two();yield three();
    }// 调用生成器函数
    let iterator = gen();
    iterator.next();
    
  2. 模拟获取用户数据、订单数据、商品数据

    function getUsers() {setTimeout(() => {let data = "用户数据";// 调用 next 方法,并将数据传入iterator.next(data);}, 1000);
    }
    function getOrders() {setTimeout(() => {let data = "订单数据";iterator.next(data);}, 1000);
    }
    function getGoods() {setTimeout(() => {let data = "商品数据";iterator.next(data);}, 1000);
    }function* genData() {let users = yield getUsers();console.log(users);let orders = yield getOrders();console.log(orders);let goods = yield getGoods();console.log(goods);
    }// 调用生成器函数
    let iterator = genData();
    iterator.next();
    

2. Promise

Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

  1. Promise 构造函数:Promise (excutor) {}
  2. Promise.prototype.then 方法;
  3. Promise.prototype.catch 方法。

2.1 then 方法

实例化 Promise 时,使用回调函数作为参数,回调函数通常有两个参数:

  1. resolve 参数

    当执行到 resolve( ... ) 时,会调用 then 方法中的第一个参数(回调);

  2. reject 参数

    当执行到 reject( ... ) 时,会调用 then 方法中的第二个参数(回调);

then 方法中通常有两个回调函数作为参数,第一个回调在成功时(resolve)调用,第二个回调在出错时(reject)调用,第二个参数可以省略。

基本使用

// 实例化 Promise 对象
const p = new Promise((resolve, reject) => {setTimeout(() => {let data = "Hello, world!";// resolve(data); // 调用 then 方法中第一个回调reject(new Error("出错了")); // 调用 then 方法中第二个回调}, 1000);
});// 调用 Promise 对象的 then 方法
p.then((value) => {console.log(value);}, // 成功回调(reason) => {console.error(reason);} // 失败回调
);

下面列举几个使用 Promise 进行封装的案例:

2.1.1 读取文件
// 引入模块
const fs = require("fs");// 使用Promise 封装
const p = new Promise((resolve, reject) => {fs.readFile("./resources/为学.md", (err, data) => {// 如果失败,则抛出错误if (err) reject(err);// 否则,打印文件内容resolve(data);});
});p.then((value) => {console.log(value.toString());},(reason) => {console.log("出错了:" + reason);}
);
2.1.2 发送 AJAX 请求
// 封装 Promise 对象
const p = new Promise((resolve, reject) => {// 1. 创建对象const xhr = new XMLHttpRequest();// 2. 初始化xhr.open("GET", "https://dog.ceo/api/breeds/image/random");// 3. 发送xhr.send();// 4. 绑定事件,处理响应结果xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {resolve(xhr.responseText);} else {reject(xhr.statusText);}}};
});// 指定回调
p.then((data) => {console.log(data);},(error) => {console.log(error);}
);
2.1.3 Promise.prototype.then
// 创建 Promise 对象
const p = new Promise((resolve, reject) => {resolve("用户数据");// reject("出错了");
});const result = p.then((data) => {console.log(data);},(error) => {console.warn(error);}
);console.log(result);
2.1.4 说明

调用 then 方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定

  1. 返回结果是非 Promise 类型的属性

    返回状态 resolved(成功),返回值为对象成功的值

    const result = p.then((data) => {console.log(data);return 123;},(error) => {console.warn(error);}
    );console.log(result); // 返回值为 123
    

    如果未使用 return 进行返回,则返回值为 undefined。

  2. 返回 Promise 对象

    返回值和返回状态均由返回的 promise 对象的返回值和状态决定

    const result = p.then((data) => {console.log(data);return new Promise((resolve, reject) => {resolve("ok");// reject("出错了");});},(error) => {console.warn(error);}
    );
    console.log(result); // 返回状态为 resolved,返回值为 ok
    // console.log(result); // 返回状态为 rejected,返回值为 出错了
    
  3. 抛出错误

    返回状态 rejected(失败)

    const result = p.then((data) => {console.log(data);// throw new Error("出错了");throw "出错了";},(error) => {console.warn(error);}
    );console.log(result); // 返回状态为 rejected,返回值为 出错了
    

由于 promise 可以返回 promise 对象,因此可以进行链式调用

// 链式调用
p.then((data) => {},(error) => {}
).then((data) => {},// 失败回调可以省略
)...;

同时避免的回调地域的问题

2.2 catch 方法

指定 Promise 对象失败的回调

const p = new Promise((resolve, reject) => {setTimeout(() => {reject("出错了");}, 1000);
});p.catch((err) => {console.log(err); // 输出 "出错了"
});

3. Set

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用扩展运算符for…of… 进 行遍历,集合的属性和方法:

  1. size 返回集合的元素个数
  2. add 增加一个新元素,返回当前集合
  3. delete 删除元素,返回 boolean 值
  4. has 检测集合中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
// 声明一个 set
let s1 = new Set();
let s2 = new Set([1, 2, 3, 4, 5]);console.log(s1, typeof s1); // Set(0) {} object
console.log(s2, typeof s2);// 元素个数
console.log(s2.size); // 5
// 添加元素
s2.add(6);
console.log(s2); // Set(6) {1, 2, 3, 4, 5, 6}
// 删除元素
s2.delete(1);
console.log(s2); // Set(5) {2, 3, 4, 5, 6}
// 判断元素是否存在
console.log(s2.has(2)); // true
console.log(s2.has(7)); // false
// 清空集合
s2.clear();
console.log(s2); // Set(0) {}

4. Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口,所以可以使用扩展运算符for…of… 进行遍历。Map 的属 性和方法:

  1. size 返回 Map 的元素个数
  2. set 增加一个新元素,返回当前 Map
  3. get 返回键名对象的键值
  4. has 检测 Map 中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
// 声明 map
let m = new Map();// 向 map 中添加键值对
m.set("name", "张三");
m.set("change", () => {console.log("change");
});
m.set({ age: 25 }, ["李四"]);
// size
console.log(m.size);
// 删除
m.delete("name");
// 获取
console.log(m.get("change"));
// 清空
m.clear();console.log(m);

5. Class

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

知识点:

  1. class 声明类

    class 类名 {属性 =;...方法() {...}
    }
    
  2. constructor 定义构造函数初始化

    class 类名 {// 构造方法,实例化时自动调用constructor(参数1, 参数2) {this.属性1 = 参数1;this.属性2 = 参数2;}... // 属性、方法
    }// 实例化对象
    let 对象 = new 类名(参数1, 参数2);
    
  3. extends 继承父类

    class 父类 {...
    }class 子类 extends 父类 {...
    }
    
  4. super 调用父级构造方法

    class 父类 {constructor(参数1, 参数2) {this.属性1 = 参数1;this.属性2 = 参数2;}
    }class 子类 extends 父类 {constructor(参数1, 参数2, 参数3, 参数4) {super(参数1, 参数2); // 继承父类的构造方法// 子类的属性this.属性1 = 参数3;}
    }
    
  5. static 定义静态方法和属性

    class 类名 {static 属性 =;static 方法() {...}
    }
    

    静态属性和方法不能被读取和继承。

  6. 子类重写父类方法

    子类中可以声明一个跟父类同名的方法

    class 父类 {方法() {...}
    }class 子类 extends 父类 {// 重写父类中的同名方法方法() {...}
    }
    

5.1 get 和 set

class Phone {get price() {console.log("价格属性被读取");return 3999}set price(value) {console.log("价格属性被修改");}
}let p = new Phone();console.log(p.price);
p.price = "free";

6. 数值扩展

Number.EPSILON 是 JavaScript 的最小精度,即 2.220446049250313e-16。

当两个数的差值小于该值,就可以认为这两个数相等,主要用于浮点数的计算

console.log(0.1 + 0.2 === 0.3); // false,因为浮点数计算不精确
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON); // true
// 这时就可以认为 0.1 + 0.2 等于 0.3

6.1 二进制、八进制、十六进制

进制前缀
二进制0b
八进制0o
十六进制0x
let a = 0b1010; // 10
let b = 0o777; // 511
let c = 0x1F;  // 31console.log(a, b, c);

6.2 Number 方法

  1. Number.isFinite() 检查是否为有限数

    console.log(Number.isFinite(Infinity)); // false
    console.log(Number.isFinite(-Infinity)); // false
    console.log(Number.isFinite(NaN)); // false
    console.log(Number.isFinite(0)); // true
    
    • Infinity:无穷大
    • NaN:非数值
  2. Number.isNaN() 检查是否为NaN

    console.log(Number.isNaN(NaN)); // true
    console.log(Number.isNaN(0)); // false
    
  3. Number.parseInt()Number.parseFloat() 用于将字符串转换为数字

    let d = "123";
    let e = "123.456";
    let f = "0b1010";console.log(Number.parseInt(d)); // 123
    console.log(Number.parseFloat(e)); // 123.456
    console.log(Number.parseInt(f)); // 0
    

    这两个方法都会忽略字符串开头的空格,并且只解析到第一个非数字字符为止。

  4. Number.isInteger() 检查是否为整数

    console.log(Number.isInteger(123)); // true
    console.log(Number.isInteger(123.456)); // false
    
  5. Math.trunc() 用于截断小数部分,返回整数部分

    let i = 123.456;
    let j = -123.456;console.log(Math.trunc(i)); // 123
    console.log(Math.trunc(j)); // -123
    
  6. Math.sign() 用于判断一个数的正负号

    返回值
    正数1
    0
    负数-1
    console.log(Math.sign(5)); // 1
    console.log(Math.sign(-5)); // -1
    console.log(Math.sign(0)); // 0
    

7. 对象方法扩展

  1. Object.is() 判断两个值是否完全相等

    console.log(Object.is(120, 121)); // false
    console.log(Object.is(1.1 + 1.2, 2.3)); // true
    

    作用类似于 == 或 ===,但区别在于对 NaN 的判断

    console.log(Object.is(NaN, NaN)); // true
    console.log(NaN === NaN); // false
    
  2. Object.assign() 用于两个对象的合并

    const config1 = {host: "localhost",port: 3306,pass: "root",
    };
    const config2 = {host: "www.baidu.com",port: "8080",
    };
    console.log(Object.assign(config1, config2));
    

    合并两个对象,相同属性的值,后者覆盖前者

  3. Object.setPrototypeOf() 设置对象的原型对象

    Object.getPrototypeOf() 获取对象的原型对象

    const school = {name: "学院",
    };
    const cities = {xiaoqv: ["商丘", "开封", "洛阳"],
    };
    Object.setPrototypeOf(school, cities);
    console.log(school);
    console.log(Object.getPrototypeOf(school));
    

8. 模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来

8.1 模块化的好处

模块化的优势有以下几点

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性
    • 开发人员对文件的修改不会产生过多冲突
    • 当某个功能需要修改、更新时,只需要对单个模块修改即可

8.2 模块化规范产品

ES6 之前的模块化规范有:

规范产品
CommonJSNodeJS、Browserify
AMDrequireJS
CMDseaJS

8.3 ES6 模块化语法

模块功能主要由两个命令构成:exportimport

  • export 命令用于规定模块的对外接口(暴露模块接口);
  • import 命令用于输入其他模块提供的功能(导入其它模块)。

暴露接口的几种方式

  1. 默认暴露:export default 接口;

    每个模块只能有一个默认暴露

    导入:import 接口 from ...;

  2. 命名暴露:export 属性名/对象名/...;

    命名导出允许你导出多个值,并且每个导出都有一个名称。

    导入:import { 属性名/对象名/... } from ...;

  3. 混合暴露:export { 属性名/对象名/..., 属性名2/对象名2/... as default };

    在一个模块中同时使用默认暴露和命名暴露。

    导入:import 属性名2/对象名2/..., { 属性名/对象名/... } from ...;

  4. 重新暴露

    可以从一个模块中导出另一个模块的导出内容。

    模块1:export 属性名/对象名/...;

    模块2:export { 属性名/对象名/... } from ...;

    导入:import { 属性名/对象名/... } from ...;

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

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

相关文章

深入理解 RxSwift 中的 Driver:用法与实践

目录 前言 一、什么是Driver 1.不会发出错误 2.主线程保证 3.可重放 4.易于绑定 二、Driver vs Observable 三、使用场景 1.绑定数据到UI控件 2.响应用户交互 3.需要线程安全的逻辑 4.如何使用Driver? 1.绑定文本输入到Label 2.处理按钮点击事件 3.从网络请求…

Linux自行实现的一个Shell(15)

文章目录 前言一、头文件和全局变量头文件全局变量 二、辅助函数获取用户名获取主机名获取当前工作目录获取最后一级目录名生成命令行提示符打印命令行提示符 三、命令处理获取用户输入解析命令行执行外部命令 四、内建命令添加环境变量检查和执行内建命令 五、初始化初始化环境…

RocketMQ和kafka 的区别

一、数据可靠性与容错机制 数据可靠性 RocketMQ支持同步刷盘和同步复制&#xff0c;确保消息写入磁盘后才返回确认&#xff0c;单机可靠性高达10个9&#xff0c;即使操作系统崩溃也不会丢失数据。而Kafka默认采用异步刷盘和异步复制&#xff0c;虽然吞吐量高&#xff0c;但极端…

在 openEuler 24.03 (LTS) 操作系统上添加 ollama 作为系统服务的步骤

以下是在 openEuler 操作系统上添加 ollama 作为系统服务的步骤&#xff1a; 创建 systemd 服务文件 sudo vi /etc/systemd/system/ollama.service将以下内容写入服务文件&#xff08;按需修改参数&#xff09;&#xff1a; [Unit] DescriptionOllama Service Afternetwork.…

光谱相机的关键技术参数

光谱相机的关键技术参数直接影响其数据获取能力和应用场景适配性。以下是核心参数的详细解析&#xff0c;涵盖光谱性能、空间性能、硬件性能及环境适应性&#xff1a; 一、光谱性能参数‌ ‌1. 光谱范围&#xff08;Spectral Range&#xff09;‌ ‌定义‌&#xff1a;相机可…

ARM内核与寄存器

ARM内核与寄存器详解 目录 ARM架构概述ARM处理器模式 Cortex-M3内核的处理器模式Cortex-A系列处理器模式 ARM寄存器集 通用寄存器程序计数器(PC)链接寄存器(LR)堆栈指针(SP)状态寄存器(CPSR/SPSR) 协处理器寄存器NEON和VFP寄存器寄存器使用规范常见ARM指令与寄存器操作 ARM架…

Git 拉取时常见冲突及解决方法总结

Git 拉取时常见冲突及解决方法总结 一、常见错误场景1. 本地修改与远程修改冲突解决方法 2. 未跟踪文件与远程文件冲突解决方法 3. 子模块权限问题解决方法 二、总结 在日常开发中&#xff0c;使用 Git 进行团队协作和代码管理时&#xff0c;经常会遇到拉取代码&#xff08;git…

深度学习、图像算法学习记录

深度学习加速 综述文档&#xff1a; https://chenzomi12.github.io/02Hardware01Foundation/02ArchSlim.html winograd: https://zhuanlan.zhihu.com/p/260109670 ncnn 1.修改模型结构&#xff0c;优化模型内存访问次数&#xff0c;加速。 VGG 和 InceptionNet &#xff1a; …

Java中的Exception和Error有什么区别?还有更多扩展

概念 在Java中&#xff0c;Exception和Error都是Throwable的子类&#xff0c;用于处理程序中的错误和异常情况。 然而&#xff0c;它们在用途和处理方式上有显著的不同&#xff1a; Exception&#xff1a; 用于表示程序在正常运行过程中可能出现的错误&#xff0c;如文件未找…

文章记单词 | 第26篇(六级)

一&#xff0c;单词释义 actor&#xff1a;名词&#xff0c;演员mask&#xff1a;名词&#xff0c;面具&#xff1b;口罩&#xff1b;遮盖物&#xff1b;动词&#xff0c;掩饰&#xff1b;戴面具&#xff1b;遮盖construct&#xff1a;动词&#xff0c;建造&#xff1b;构造&a…

LeetCode算法题(Go语言实现)_38

题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 一、代码实现 type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode }func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {if root nil || root p || root q {return root}left : lowes…

Java 基础语法、Java注释

Java 基础语法 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫…

用VScode来编写前后端——构建基础框架

前言 我写这一个板块的原因是我参加了我们学校的新生项目课&#xff0c;需要创立一个系统&#xff0c;我们小组选的标题的基于计算机视觉的商品识别系统&#xff0c;那么我们需要一个网站来展示我们的功能&#xff0c;故写这些来记录一下自己&#xff0c;大家如果有什么问题的话…

git clone阻塞问题

问题描述 git clone采用的ssh协议&#xff0c;在克隆仓库的时候&#xff0c;会经常卡一下&#xff0c;亦或是直接卡死不动。 最开始以为是公司电脑配置的问题&#xff0c;想着自己实在解决不了找it帮忙。 查阅资料发现&#xff0c;最终发现是git版本的问题&#xff0c;这个是…

WEB攻防-Java安全JNDIRMILDAP五大不安全组件RCE执行不出网不回显

目录 1. RCE执行-5大类函数调用 1.1 Runtime方式 1.2 Groovy执行命令 1.3 脚本引擎代码注入 1.4 ProcessImpl 1.5 ProcessBuilder 2. JNDI注入(RCE)-RMI&LDAP&高版本 2.1 RMI服务中的JNDI注入场景 2.2 LDAP服务中的JNDI注入场景 攻击路径示例&#…

【Hadoop入门】Hadoop生态之Sqoop简介

1 什么是Sqoop&#xff1f; 在企业的数据架构中&#xff0c;关系型数据库与Hadoop生态系统之间的数据流动是常见且关键的需求。Apache Sqoop&#xff08;SQL-to-Hadoop&#xff09;正是为解决这一问题而生的高效工具&#xff0c;它专门用于在结构化数据存储&#xff08;如RDBMS…

如何自动检测使用的组件库有更新

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&#…

Go语言编写一个进销存Web软件的demo

Go语言编写一个进销存Web软件的demo 用户现在要求用。之前他们已经讨论了用Django实现的方案&#xff0c;现在突然切换到Go&#xff0c;可能有几个原因。首先&#xff0c;用户可能对Go语言感兴趣&#xff0c;或者他们公司的技术栈转向了Go。其次&#xff0c;用户可能希望比较不…

【前缀和】矩阵区域和(medium)

矩阵区域和&#xff08;medium&#xff09; 题⽬描述&#xff1a;解法&#xff1a;代码Java 算法代码&#xff1a;C 算法代码&#xff1a; 题⽬描述&#xff1a; 题⽬链接&#xff1a;1314. 矩阵区域和 给你⼀个 m x n 的矩阵 mat 和⼀个整数 k &#xff0c;请你返回⼀个矩阵 …

Java学习手册:Java发展历史与版本特性

Java作为全球最流行的编程语言之一&#xff0c;其发展历程不仅见证了技术的演进&#xff0c;也反映了软件开发模式的变革。从1995年的首次发布到如今的持续更新&#xff0c;Java始终保持着强大的生命力和广泛的影响力。本文将简要回顾Java的发展历程&#xff0c;并重点介绍其关…