ES6
以下内容部分实例代码参考了dengruicode.com的内容
ECMAScript 的背景
JavaScript 是大家所了解的语言名称,但是这个语言名称是商标( Oracle 公司注册的商标)。因此,JavaScript 的正式名称是 ECMAScript 。1996年11月,JavaScript 的创造者网景公司将 JS 提交给国际化标准组织 ECMA(European computer manufactures association,欧洲计算机制造联合会),希望这种语言能够成为国际标准,随后 ECMA 发布了规定浏览器脚本语言的标准,即 ECMAScript。这也有利于这门语言的开放和中立。
ECMAScript 的历史
ES6 是 ECMAScript 标准十余年来变动最大的一个版本,为其添加了许多新的语法特性。
- 1997 年 ECMAScript 1.0 诞生。
- 1998 年 6 月 ECMAScript 2.0 诞生,包含一些小的更改,用于同步独立的 ISO 国际标准。
- 1999 年 12 月 ECMAScript 3.0诞生,它是一个巨大的成功,在业界得到了广泛的支持,它奠定了 JS 的基本语法,被其后版本完全继承。直到今天,我们一开始学习 JS ,其实就是在学 3.0 版的语法。
- 2000 年的 ECMAScript 4.0 是当下 ES6 的前身,但由于这个版本太过激烈,对 ES 3 做了彻底升级,所以暂时被”和谐”了。
- 2009 年 12 月,ECMAScript 5.0 版正式发布。ECMA 专家组预计 ECMAScript 的第五个版本会在 2013 年中期到 2018 年作为主流的开发标准。2011年6月,ES 5.1 版发布,并且成为 ISO 国际标准。
- 2013 年,ES6 草案冻结,不再添加新的功能,新的功能将被放到 ES7 中;2015年6月, ES6 正式通过,成为国际标准。
ES6 的目标与愿景
成为更好编写的开发语言有以下目标。
适应更复杂的应用;实现代码库之间的共享;不断迭代维护新版本。
开始学习
集合
set
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
ps:跟c++里面那个标准库里的那个set不太一样,c++的那个是自带排序的
实例
1 | const set = new Set([1, 2, 3]); |
1 | //使用for...of循环遍历 Set集合 |
map
存储键值对
实例:
1 | let person = new Map([ |
1 | //使用forEach方法遍历Map集合的键值对 |
对象
私有属性、存取器
1 | class Person { |
类的继承extends
1 | //父类 |
解构
这是一种表达式,允许从数组或对象中提取数据,并将提取的数据赋值给声明的变量。这种方法可以使代码更加简洁和易于理解。
数组解构
基本用法:
1 | let [x, y] = [1, 2]; |
这里,数组[1, 2]
中的第一个元素赋值给了变量x
,第二个元素赋值给了变量y
。
跳过某些元素:
1 | let [, , c] = [10, 20, 30]; |
这里,数组中的第一个和第二个元素被跳过,第三个元素赋值给了变量c
。
扩展运算符:
1 | let [A, ...B] = [1, 2, 3, 4, 5, 6]; |
这里,数组的第一个元素赋值给了变量A
,剩余的元素组成了一个新的数组赋值给了变量B
。
默认值:
1 | let [x2, y2 = 200] = [100]; |
如果数组解构时某个位置没有对应的值,则可以使用默认值。这里y2
的默认值是200
。
两数交换:
1 | let x3 = 10; |
通过数组解构,可以很方便地交换两个变量的值。
对象解构
基本用法:
1 | let { name } = person; |
从对象person
中提取name
属性的值,并赋值给变量name
。
重命名:
1 | let { name: userName, gender, web } = person; |
这里,将name
属性的值赋给了变量userName
,同时提取了gender
和web
属性的值。
默认值:
1 | let { address = "安徽" } = person; |
如果对象解构时某个属性不存在,则可以使用默认值。这里person
对象中没有address
属性,所以address
的默认值是"安徽"
。
解构赋值是ES6引入的一个非常有用的特性,它使得从数组或对象中提取数据变得更加直观和简洁。
字符串常见函数方法
1 | let web = "dengruicode.com"; |
promise
Promise 是 JavaScript 中用于处理异步操作的一种机制。它代表了一个在未来某个时刻可能会完成或失败的操作,并允许你为这两种情况分别指定处理函数。Promise 提供了更优雅的方式来处理异步操作,避免了传统的回调地狱(callback hell)。
Promise 的三种状态
- Pending(待处理):这是 Promise 的初始状态,表示异步操作还未完成。
- Fulfilled(已履行):当异步操作成功完成时,Promise 的状态会变为 Fulfilled,此时可以调用
.then()
方法来处理成功的结果。 - Rejected(被驳回):当异步操作失败时,Promise 的状态会变为 Rejected,此时可以调用
.catch()
方法来处理错误。
Promise 的基本用法
创建一个 Promise 对象时,你需要传递一个执行器函数(executor function)给 Promise 构造函数。这个执行器函数接受两个参数:resolve
和 reject
,它们都是函数。
resolve(value)
:当异步操作成功时,调用此函数,并将操作的结果作为参数传递。这会将 Promise 的状态从 Pending 变为 Fulfilled。reject(reason)
:当异步操作失败时,调用此函数,并将错误信息作为参数传递。这会将 Promise 的状态从 Pending 变为 Rejected。
Promise 的链式调用
Promise 提供了 .then()
和 .catch()
方法来分别处理 Fulfilled 和 Rejected 状态。这两个方法都返回一个新的 Promise,这允许你进行链式调用。
.then(onFulfilled, onRejected)
:当 Promise 状态变为 Fulfilled 时,调用onFulfilled
函数;当状态变为 Rejected 时,调用onRejected
函数(可选)。.catch(onRejected)
:这是.then(null, onRejected)
的简写形式,专门用于处理错误。
此外,Promise 还提供了 .finally()
方法,无论 Promise 的最终状态如何,都会执行 finally
中的回调函数。这通常用于清理工作,如关闭数据库连接、清除定时器等。
示例代码解析
1 | let promise = new Promise((resolve, reject) => { |
在这个示例中,我们创建了一个 Promise 对象,并通过调用 reject
函数模拟了一个异步操作的失败。因此,.then()
方法中的回调函数不会被执行,而 .catch()
方法中的回调函数会捕获到错误信息并打印出来。最后,.finally()
方法中的回调函数会执行,打印出“异步执行结束”。
Promise 是处理异步操作的重要工具,它使得代码更加清晰、易于维护。通过合理地使用 Promise,你可以有效地管理复杂的异步流程。
同步与异步编程概念及示例
同步编程
- 定义:代码按照编写顺序逐行执行,后续的代码必须等待当前正在执行的代码完成之后才能执行。
- 特点:当遇到耗时的操作时(如网络请求、文件读写等),主线程会被阻塞,直到该操作完成。
- 示例:就像在单车道路段上发生交通事故导致交通堵塞,只有拖走事故车辆后,后续车辆才能继续行驶。
异步编程
- 定义:当遇到耗时的操作时,主线程不会被阻塞,而是继续执行后续的代码,等待耗时操作完成后,再通过回调函数或其他机制处理结果。
- 特点:提高了程序的响应性和性能,因为主线程可以继续执行其他任务。
- 示例:在具有多车道的高速公路上,发生交通事故后,可以走其他车道继续行驶。
async/await 编程
- async:当一个函数被标记为
async
后,该函数会返回一个Promise
对象。这允许我们使用await
关键字等待异步操作的结果。 - await:只能在
async
函数内部使用。加上await
关键字后,会在执行到这一行时暂停函数的剩余部分,等待Promise
对象解决(即异步操作完成),然后继续执行并获取到异步操作返回的数据。
示例代码
以下是一个HTML文档,其中包含了使用axios
库进行网络请求的示例,展示了回调地狱和async/await
编程风格的对比。
1 |
|
在这个示例中,我们首先展示了回调地狱的写法,它使用了多个嵌套的.then()
方法来处理连续的异步操作。然后,我们展示了如何使用async/await
语法来以同步的方式编写异步代码,从而使代码更加简洁和易读。
Fetch
在现代Web开发中,fetch
是一个非常常用的API,它基于Promise设计,用于发起HTTP请求并接收来自服务器的响应数据。fetch
提供了比传统的 XMLHttpRequest
更简洁和更强大的接口,使得处理HTTP请求变得更加直观和方便。
基本用法
fetch
函数接收一个URL作为参数,并返回一个Promise对象。这个Promise对象会在请求完成时(无论是成功还是失败)被解决。你可以使用 .then()
方法来处理成功的响应,使用 .catch()
方法来处理错误,而 .finally()
方法则会在请求完成后无论结果如何都被执行。
GET 请求示例
在你的代码中,第一个示例展示了如何使用 fetch
发起一个GET请求:
1 | fetch('http://127.0.0.1/get') |
这里,response.json()
方法用于将响应体解析为JSON对象。注意,在解析JSON之前,最好检查响应是否成功(即状态码是否在200-299之间),以避免在解析错误的响应时抛出异常。
POST 请求示例
对于POST请求,你可以通过传递一个包含请求方法、头部信息和请求体的选项对象来配置 fetch
。
- 发送表单数据:
在你的代码中,第二个示例展示了如何发送表单数据(使用 application/x-www-form-urlencoded
编码):
1 | fetch('http://127.0.0.1/post', { |
这里,URLSearchParams
用于创建查询字符串,它会将对象转换为编码后的URL查询字符串格式。
- 发送JSON数据:
第三个示例展示了如何发送JSON数据:
1 | fetch('http://127.0.0.1/postJson', { |
在这个例子中,JSON.stringify
方法用于将JavaScript对象转换为JSON字符串。注意,当发送JSON数据时,你需要将 Content-Type
头部设置为 application/json
。
错误处理
在 .catch()
块中,你可以捕获并处理在请求过程中发生的任何错误,例如网络问题或服务器错误。错误对象通常包含有关错误的详细信息,如错误消息和状态码。
清理工作
.finally()
方法非常有用,因为它会在请求完成后(无论成功还是失败)执行一些清理工作,例如关闭文件、清除计时器等。
总之,fetch
API 提供了一种简洁而强大的方式来处理HTTP请求,使得Web开发变得更加高效和愉快。通过结合使用 .then()
、.catch()
和 .finally()
方法,你可以轻松地管理请求的生命周期,并处理各种可能的响应和错误情况。
Axios
Axios 概述
Axios 是一个基于 Promise 的网络请求库,设计用于浏览器和 Node.js 环境。它提供了丰富的配置选项,使得发送 HTTP 请求和处理响应变得简单而灵活。Axios 返回一个 Promise 对象,这意味着你可以使用 .then()
、.catch()
和 .finally()
方法来处理异步操作的结果。
Fetch 与 Axios 的对比
- 环境支持:
- Fetch:主要设计用于浏览器环境,虽然有一些第三方库(如
node-fetch
)尝试将其引入 Node.js,但原生的 Fetch API 在 Node.js 中并不可用。 - Axios:同时支持浏览器和 Node.js 环境,这使得它成为跨平台网络请求的理想选择。
- Fetch:主要设计用于浏览器环境,虽然有一些第三方库(如
- 配置选项:
- Fetch:虽然功能强大,但配置选项相对较少。例如,发送 JSON 数据时,你需要手动设置
Content-Type
头部,并可能需要将对象转换为 JSON 字符串。 - Axios:提供了更多的配置选项,包括自动转换 JSON 数据、设置请求和响应的拦截器、处理并发请求等。此外,Axios 还允许你轻松地配置默认设置,如基础 URL、超时时间等。
- Fetch:虽然功能强大,但配置选项相对较少。例如,发送 JSON 数据时,你需要手动设置
- 错误处理:
- Fetch:错误处理相对繁琐。当请求失败时,返回的 Promise 会被拒绝,但你需要检查响应的状态码来确定请求是否真的失败(例如,4xx 和 5xx 状态码)。
- Axios:错误处理更加直观。当请求失败时,Axios 会抛出一个错误对象,其中包含有关错误的详细信息,如状态码、响应数据和消息。这使得错误处理更加简单和一致。
- 拦截器:
- Fetch:不直接支持拦截器功能,但你可以通过封装
fetch
函数来实现类似的功能。 - Axios:提供了请求和响应的拦截器功能,这使得你可以在请求发送之前或响应到达之前对其进行处理或修改。这对于添加认证令牌、处理全局错误或日志记录等任务非常有用。
- Fetch:不直接支持拦截器功能,但你可以通过封装
- 自动转换 JSON:
- Fetch:不会自动将响应数据转换为 JSON 对象。你需要手动调用
response.json()
方法来解析 JSON 数据。 - Axios:默认情况下会自动将响应数据转换为 JSON 对象(如果服务器返回的是 JSON 格式的数据)。这使得处理 JSON 响应更加简单和直接。
- Fetch:不会自动将响应数据转换为 JSON 对象。你需要手动调用
- 取消请求:
- Fetch:原生不支持取消请求的功能,但你可以使用
AbortController
来实现这一点(在较新的浏览器中可用)。 - Axios:提供了内置的取消请求功能,你可以使用
CancelToken
或AbortController
(在 Axios 的新版本中)来取消正在进行的请求。
- Fetch:原生不支持取消请求的功能,但你可以使用
Axios 示例代码
在你的示例代码中,展示了如何使用 Axios 发送 GET 和 POST 请求。
- GET 请求:
1 | axios.get('http://127.0.0.1/get').then(response => { |
- POST 请求(表单数据):
1 | axios.get('http://127.0.0.1/get').then(response => { |
注意,当发送 application/x-www-form-urlencoded
编码的表单数据时,你需要使用 qs
库(或其他类似库)来序列化对象,因为 Axios 默认不会为你做这件事。但在你的示例中,由于未包含 qs
库的序列化步骤,如果服务器期望的是 application/x-www-form-urlencoded
格式的数据,则此请求可能会失败。正确的做法是使用 qs.stringify(data)
来序列化对象,并将其作为 params
传递给 axios.post
(如果 Axios 配置为使用 URL 参数发送数据)或作为请求体的一部分,并设置正确的 Content-Type
头部。然而,在你的示例中,你直接将对象作为请求体传递,并设置了 Content-Type
头部为 application/x-www-form-urlencoded
,这通常不是发送 JSON 以外数据的正确方式。如果你确实需要发送表单数据,你应该使用类似 URLSearchParams
的东西来序列化数据(但请注意,URLSearchParams
是浏览器内置的,不是 Axios 的)。
- POST 请求(JSON 数据):
1 | axios.post('http://127.0.0.1/postJson', data).then(response => { |
在这个例子中,Axios 默认会将 data
对象序列化为 JSON 字符串,并设置正确的 Content-Type
头部为 application/json
,因此你不需要手动进行这些操作。
总的来说,Axios 提供了比 Fetch 更丰富和灵活的功能,同时保持了简洁和易用的接口。这使得它成为许多开发者的首选网络请求库。
模块化开发概述与import
、export
详解
模块化开发概念
模块化开发是一种编程实践,旨在将复杂的代码拆分为多个独立的模块。每个模块负责完成特定的功能,从而提高了代码的可读性、可维护性和复用性。
import
与export
机制
在模块化开发中,export
关键字用于将模块内部的代码(变量、函数、类等)导出,以便其他模块能够使用。而import
关键字则用于在其他模块中导入这些导出的代码。
分别导出与导入
- 导出:在模块文件中,可以使用
export
关键字将多个变量或函数分别导出。
1 | // index.js |
- 导入:在需要使用这些导出内容的模块中,可以使用
import
关键字进行导入。同时,可以使用as
关键字为导入的变量或函数重命名,以避免命名冲突。
1 | <script type="module"> |
默认导出与导入
- 默认导出:在模块文件中,可以使用
export default
将一个对象、函数或变量作为整体默认导出。
1 | // index.js |
- 默认导入:在需要使用默认导出的模块中,可以使用
import
关键字(不带花括号)进行导入,并为其指定一个名称。
1 | <script type="module"> |
使用as
关键字进行重命名导入
为了避免命名冲突或提高代码的可读性,可以使用import * as obj
语法将整个模块的内容作为一个对象导入,并通过该对象的属性来访问模块中的变量和函数。
1 | <script type="module"> |
注意事项
- 在使用模块化开发时,需要确保HTML文件中包含
<script type="module">
标签,以指示浏览器该脚本应作为ES模块来处理。 - VSCode扩展“Live Server”可以用于在本地开发环境中预览和运行包含ES模块的HTML文件。但请注意,确保Live Server支持ES模块,并且你的开发环境(如浏览器)也支持ES模块特性。
通过模块化开发,我们可以更好地组织和管理代码,提高代码的可读性和可维护性。同时,import
和export
机制为我们提供了一种简洁而强大的方式来在不同模块之间共享代码。