ECMAScript 6.0简介
ECMAScript 和 javaScript 关系
1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,希望这种语言能够成为国际标准。次年,ECMA 发布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript,这个版本就是 1.0 版。
该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。
因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现。
1、let 和 const 命令
let const var 相互间特点和区别
-
var 在 ES5 及之前的版本中使用的关键字 定义的变量具有函数作用域或全局作用域 在同一个作用域内,可以重复声明同名变量,后面的声明会覆盖前面的声明 具有变量提升(hoisting)的特性,即变量可以在声明之前使用 允许重新赋值
-
let 在 ES6(ECMAScript 2015)中引入的关键字 定义的变量具有块级作用域,例如在 if 语句、循环语句或任何花括号 {} 内部 在同一个作用域内,不允许重复声明同名变量 不具有变量提升的特性,变量只能在声明后使用 允许重新赋值
-
const
在 ES6(ECMAScript 2015)中引入的关键字 定义的变量也具有块级作用域 在同一个作用域内,不允许重复声明同名变量 声明时必须同时初始化变量,并且一旦初始化后,就不能再修改其值(它是一个常量) 不具有变量提升的特性,变量只能在声明后使用
-
总结:
var 具有函数作用域,let 和 const 具有块级作用域。 var 允许重复声明同名变量,let 和 const 不允许。 var 具有变量提升特性,let 和 const 不具备。 const 声明的变量是一个常量,不可重新赋值。 推荐使用 let 和 const,因为它们提供了更好的作用域控制和代码可读性,并且避免了一些常见的 JavaScript 错误。只有在特殊情况下需要使用 var 时,才使用它。
2、解构赋值
ES6(ECMAScript 2015)引入了解构赋值(Destructuring Assignment)的特性,它允许我们从数组或对象中提取值,并将它们赋给变量。解构赋值提供了一种简洁、灵活的方式来处理数据。
数组解构赋值
在数组解构赋值中,我们可以通过模式匹配的方式从数组中提取值,并将其赋给变量。例如:
javascript
const [a, b, c] = [1, 2, 3];
console.log(a); // 输出: 1
console.log(b); // 输出: 2
console.log(c); // 输出: 3
解构赋值还支持默认值的定义:
javascript
const [a, b, c = 3] = [1, 2];
console.log(c); // 输出: 3
我们还可以通过解构赋值交换变量的值:
javascript
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a); // 输出: 2
console.log(b); // 输出: 1
对象解构赋值
在对象解构赋值中,我们可以通过模式匹配的方式从对象中提取值,并将其赋给变量。对象的属性名用作模式匹配的依据。例如:
javascript
const { name, age } = { name: 'Alice', age: 25 };
console.log(name); // 输出: 'Alice'
console.log(age); // 输出: 25
我们可以通过指定新的变量名来对属性进行解构赋值:
javascript
const { name: n, age: a } = { name: 'Alice', age: 25 };
console.log(n); // 输出: 'Alice'
console.log(a); // 输出: 25
对象解构赋值也支持默认值的定义:
javascript
const { name, age = 30 } = { name: 'Alice' };
console.log(age); // 输出: 30
嵌套解构赋值
解构赋值可以用于嵌套结构的数据。例如,我们可以同时从数组和对象中进行解构赋值:
javascript
const [a, { b, c }] = [1, { b: 2, c: 3 }];
console.log(a); // 输出: 1
console.log(b); // 输出: 2
console.log(c); // 输出: 3
函数参数中的解构赋值
我们可以直接传递一个对象作为函数参数,并在函数内部解构赋值获取所需的值:
javascript
function greet({ name, age }) {
console.log(`Hello, ${name}! You are ${age} years old.`);
}
greet({ name: 'Alice', age: 25 }); // 输出: 'Hello, Alice! You are 25 years old.'
3、字符串的扩展
模板字符串
模板字面量(Template Literals) 使用反引号(`)包围的字符串,可以包含嵌入的表达式。这样可以更方便地拼接变量和表达式到字符串中。例如:
javascript
const name = 'Alice';
const greeting = `Hello, ${name}!`;
console.log(greeting); // 输出:Hello, Alice
多行字符串
使用反引号(`)包围的字符串可以跨越多行,而不需要使用换行符或字符串连接符。例如:
javascript
const multiLineString = `This is
a multi-line
string.`;
console.log(multiLineString);
// 输出:
// This is
// a multi-line
// string.
字符串插值(String Interpolation) 在模板字面量中,可以使用${}
语法嵌入表达式和变量。例如:
javascript
const a = 5;
const b = 10;
const result = `${a} + ${b} = ${a + b}`;
console.log(result); // 输出:5 + 10 = 15
字符串新增方法
startsWith(searchString[, position]) 判断字符串是否以指定的字符串开头,并返回布尔值。
javascript
const str = 'Hello, world!';
console.log(str.startsWith('Hello')); // true
console.log(str.startsWith('world')); // false
endsWith(searchString[, length]) 判断字符串是否以指定的字符串结尾,并返回布尔值。
javascript
const str = 'Hello, world!';
console.log(str.endsWith('world!')); // true
console.log(str.endsWith('Hello')); // false
includes(searchString[, position]) 判断字符串是否包含指定的字符串,并返回布尔值。
javascript
const str = 'Hello, world!';
console.log(str.includes('world')); // true
console.log(str.includes('foo')); // false
repeat(count) 复制字符串指定次数,并返回新的字符串。
javascript
const str = 'Hello';
console.log(str.repeat(3)); // 'HelloHelloHello'
padStart(targetLength [, padString]) 在字符串的开头用指定的字符串填充,直到字符串达到指定的长度。
javascript
const str = 'Hello';
console.log(str.padStart(10, 'x')); // 'xxxxxHello'
console.log(str.padStart(10)); // ' Hello'
padEnd(targetLength [, padString])
在字符串的结尾用指定的字符串填充,直到字符串达到指定的长度。
javascript
const str = 'Hello';
console.log(str.padEnd(10, 'x')); // 'Helloxxxxx'
console.log(str.padEnd(10)); // 'Hello '
trim() 去除字符串两端的空格,并返回新的字符串。
javascript
const str = ' Hello, world! ';
console.log(str.trim()); // 'Hello, world!'
trimStart()
scss
去除字符串开头的空格,并返回新的字符串。也可以使用 `trimLeft()` 方法,效果相同。
javascript
const str = ' Hello, world! ';
console.log(str.trimStart()); // 'Hello, world! '
trimEnd() 去除字符串结尾的空格,并返回新的字符串。也可以使用 trimRight()
方法,效果相同。
javascript
const str = ' Hello, world! ';
console.log(str.trimEnd()); // ' Hello, world!'
replace() 只能替换第一个匹配
javascript
'aabbcc'.replace('b', '_')
// 'aa_bcc'
如果要替换所有的匹配,不得不使用正则表达式的g
修饰符
javascript
'aabbcc'.replace(/b/g, '_')
// 'aa__cc'
replaceAll() 可以一次性替换所有匹配
javascript
'aabbcc'.replaceAll('b', '_')
// 'aa__cc'
at() 方法接受一个整数作为参数,返回参数指定位置的字符,支持负索引(即倒数的位置)
javascript
const str = 'hello';
str.at(1) // "e"
str.at(-1) // "o"
4、函数扩展
默认参数(Default Parameters)
可以在函数定义中为参数提供默认值。如果调用函数时未提供对应参数的值,则会使用默认值。
javascript
function foo(x = 10, y = 20) {
console.log(x, y);
}
foo(); // 输出: 10 20
foo(30); // 输出: 30 20
foo(30, 40); // 输出: 30 40
```
剩余参数(Rest Parameters)
可以使用剩余参数语法来捕获函数调用时传递的多余参数,将它们收集到一个数组中。
javascript
function sum(...numbers) {
let result = 0;
for (let number of numbers) {
result += number;
}
return result;
}
console.log(sum(1, 2, 3, 4, 5)); // 输出: 15
```
扩展操作符(Spread Operator)
扩展操作符可以在函数调用和数组/对象字面量中展开数组或对象。
javascript
function foo(x, y, z) {
console.log(x, y, z);
}
const arr = [1, 2, 3];
foo(...arr); // 输出: 1 2 3
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // 输出: { a: 1, b: 2, c: 3 }
```
箭头函数(Arrow Functions)
箭头函数提供了一种更简洁的函数定义语法,并且自动绑定了当前上下文的this值。
javascript
const add = (x, y) => x + y;
console.log(add(2, 3)); // 输出: 5
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // 输出: [2, 4, 6]
```
5、数组扩展
扩展运算符
扩展运算符(spread)是三个点(...
)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
javascript
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
数组新增方法
Array.from()
Array.from() 方法可以将类数组对象或可迭代对象转换为真正的数组
javascript
// 示例 1:从字符串创建数组
const str = 'Hello';
const arr = Array.from(str);
console.log(arr); // 输出:['H', 'e', 'l', 'l', 'o']
// 示例 2:从 Set 创建数组
const set = new Set([1, 2, 3]);
const arr2 = Array.from(set, x => x * 2);
console.log(arr2); // 输出:[2, 4, 6]
// 示例 3:从类数组对象(arguments)创建数组
function printArgs() {
const args = Array.from(arguments);
console.log(args);
}
printArgs('apple', 'banana', 'cherry'); // 输出:['apple', 'banana', 'cherry']
Array.of() 方法 Array.of() 方法可以根据传入的参数创建一个新的数组,不论参数的数量或类型如何。
javascript
const arr = Array.of(1, 'two', 3.14); // [1, 'two', 3.14]
find() 和 findIndex() 方法
find() 方法返回数组中满足测试函数条件的第一个元素, 而findIndex()方法返回满足测试函数条件的第一个元素的索引。
javascript
const arr = [1, 2, 3, 4, 5];
const foundElement = arr.find(element => element > 3); // 4
const foundIndex = arr.findIndex(element => element > 3); // 3
includes() 方法 includes() 方法用于检查数组是否包含特定的元素,并返回相应的布尔值。
javascript
const arr = [1, 2, 3];
const includesElement = arr.includes(2); // true
flat() 方法 和 flatMap() 方法
默认只会"拉平"一层,如果想要"拉平"多层的嵌套数组,可以将flat()
方法的参数写成一个整数,表示想要拉平的层数,默认为1 flatMap() 方法在执行扁平化操作的同时,还可以对每个元素执行映射操作
javascript
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
// 如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数
[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]
const arr2 = [1, 2, 3];
arr2.flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]
6、对象扩展
属性简写
ES6允许在对象字面量中使用属性简写语法,可以省略冒号和属性值的重复
javascript
const name = 'John';
const age = 25;
const person = { name, age };
方法简写
对象字面量中定义方法时,可以省略 function关键字和冒号:
javascript
const obj = {
method() {
// 方法体
}
};
计算属性名:
ES6引入了计算属性名的语法,允许在对象字面量中使用动态的属性名
javascript
const propKey = 'name';
const obj = {
[propKey]: 'John'
};
Object.assign()
``Object.assign()`方法用于将一个或多个源对象的属性复制到目标对象中
ini
const target = { a: 1 };
const source = { b: 2, c: 3 };
const result = Object.assign(target, source);
```
Object.keys()、Object.values()和Object.entries()
Object.keys()`方法返回一个由目标对象的所有可枚举属性组成的数组 Object.values()方法返回一个由目标对象的所有可枚举属性值组成的数组 Object.entries()方法返回一个由目标对象的所有可枚举属性键值对组成的数组
ini
const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
const values = Object.values(obj);
const entries = Object.entries(obj);
7、运算符的扩展
指数运算符
ES2016 新增了一个指数运算符(**
)。
javascript
2 ** 2 // 4
2 ** 3 // 8
这个运算符的一个特点是右结合,而不是常见的左结合。多个指数运算符连用时,是从最右边开始计算的。
javascript
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512
上面代码中,首先计算的是第二个指数运算符,而不是第一个。
指数运算符可以与等号结合,形成一个新的赋值运算符(**=
)。
javascript
let a = 1.5;
a **= 2;
// 等同于 a = a * a;
let b = 4;
b **= 3;
// 等同于 b = b * b * b;
链判断运算符
编程实务中,如果读取对象内部的某个属性,往往需要判断一下,属性的上层对象是否存在。比如,读取message.body.user.firstName
这个属性,安全的写法是写成下面这样。
javascript
// 错误的写法
const firstName = message.body.user.firstName || 'default';
// 正确的写法
const firstName = (message
&& message.body
&& message.body.user
&& message.body.user.firstName) || 'default';
上面例子中,firstName
属性在对象的第四层,所以需要判断四次,每一层是否有值。
三元运算符?:
也常用于判断对象是否存在。
javascript
const fooInput = myForm.querySelector('input[name=foo]')
const fooValue = fooInput ? fooInput.value : undefined
上面例子中,必须先判断fooInput
是否存在,才能读取fooInput.value
。
这样的层层判断非常麻烦,因此 ES2020 引入了"链判断运算符"(optional chaining operator)?.
,简化上面的写法。
javascript
const firstName = message?.body?.user?.firstName || 'default';
const fooValue = myForm.querySelector('input[name=foo]')?.value
逻辑运算符
ES2021 引入了三个新的逻辑赋值运算符(logical assignment operators),将逻辑运算符与赋值运算符进行结合。
javascript
// 或赋值运算符
x ||= y
// 等同于
x || (x = y)
// 与赋值运算符
x &&= y
// 等同于
x && (x = y)
// Null 赋值运算符
x ??= y
// 等同于
x ?? (x = y)
8、Set 和 Map 数据结构
Set()
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set
本身是一个构造函数,用来生成 Set 数据结构。
javascript
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i);
}
// 2 3 5 4
上面代码通过add()
方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。
Set
函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
javascript
// 例一
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
// 例二
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
// 例三
const set = new Set(document.querySelectorAll('div'));
set.size // 56
// 类似于
const set = new Set();
document
.querySelectorAll('div')
.forEach(div => set.add(div));
set.size // 56
下面是一些常用的Set方法:
add(value)
:向Set中添加一个值。delete(value)
:从Set中删除指定的值。has(value)
:检查Set中是否存在指定的值。clear()
:清空Set中的所有值。size
:返回Set中值的个数。
javascript
const set = new Set();
set.add(1);
set.add(2);
set.add(3);
console.log(set.has(2)); // 输出: true
set.delete(2);
console.log(set.size); // 输出: 2
set.clear();
console.log(set.size); // 输出: 0
Map()
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
javascript
const data = {};
const element = document.getElementById('myDiv');
data[element] = 'metadata';
data['[object HTMLDivElement]'] // "metadata"
上面代码原意是将一个 DOM 节点作为对象data
的键,但是由于对象只接受字符串作为键名,所以element
被自动转为字符串[object HTMLDivElement]
。
为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了"字符串---值"的对应,Map 结构提供了"值---值"的对应,是一种更完善的 Hash 结构实现。如果你需要"键值对"的数据结构,Map 比 Object 更合适。
javascript
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
下面是一些常用的Map方法:
set(key, value)
:向Map中添加一个键值对。get(key)
:根据键获取对应的值。has(key)
:检查Map中是否存在指定的键。delete(key)
:从Map中删除指定的键值对。clear()
:清空Map中的所有键值对。size
:返回Map中键值对的个数。
javascript
const map = new Map();
map.set('key1', 'value1');
map.set('key2', 'value2');
map.set('key3', 'value3');
console.log(map.get('key2')); // 输出: value2
map.delete('key2');
console.log(map.size); // 输出: 2
map.clear();
console.log(map.size); // 输出: 0
9、Promise 对象
ES6引入了Promise对象作为JavaScript中处理异步操作的内置功能。Promise提供了一种编写异步代码的方式,使其行为更像同步代码,使得处理异步操作更加简单和可理解。
Promise表示最终的完成(或失败)结果的占位符。它可以在异步操作完成后返回一个值或一个错误。Promise有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。当异步操作执行时,Promise会处于pending状态,然后可以转变为fulfilled或rejected状态。
使用Promise可以通过链式调用then()方法来处理异步操作的结果。then()方法接收两个回调函数:一个用于处理异步操作成功的结果,另一个用于处理异步操作失败的错误。这样可以避免回调地狱(callback hell)的问题,使代码更加清晰和可读。
以下是一个使用Promise的简单示例:
javascript
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Hello, world!';
if (data) {
resolve(data); // 异步操作成功
} else {
reject('Error'); // 异步操作失败
}
}, 2000);
});
}
fetchData()
.then(result => {
console.log(result); // 输出: Hello, world!
})
.catch(error => {
console.error(error); // 输出: Error
});
在上面的示例中,fetchData()函数返回一个Promise对象。在Promise的构造函数中,我们模拟了一个异步操作,并在2秒后返回一个字符串。如果字符串存在,我们通过调用resolve()方法将Promise状态设置为fulfilled,并传递结果数据。否则,我们通过调用reject()方法将Promise状态设置为rejected,同时传递错误信息。
然后,我们通过链式调用then()方法来处理异步操作的结果。如果异步操作成功,then()方法的第一个回调函数将被调用,并接收异步操作的结果作为参数。如果异步操作失败,catch()方法将会被调用,并接收错误信息作为参数。
Promise.all() Promise.all()
是一个非常有用的 Promise 方法,它接收一个 Promise 数组作为参数,并返回一个新的 Promise 对象。该 Promise 对象在所有输入的 Promise 都变为 fulfilled 状态时才被解析,解析值是一个包含所有 Promise 结果的数组。如果其中任何一个 Promise 被拒绝(rejected),则返回的 Promise 立即被拒绝,并返回被拒绝的 Promise 的原因。
以下是 Promise.all()
的示例用法:
javascript
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2 resolved');
}, 3000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 3 resolved');
}, 1500);
});
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log(results);
// 输出: ['Promise 1 resolved', 'Promise 2 resolved', 'Promise 3 resolved']
})
.catch(error => {
console.error(error);
});
在上面的示例中,我们创建了三个 Promise 对象 promise1
、promise2
和 promise3
,它们分别在不同的延迟后被解析。通过调用 Promise.all()
并传入这三个 Promise 对象的数组,我们等待所有 Promise 都变为 fulfilled 状态。当所有 Promise 都解析完成时,.then()
方法会被调用,并接收一个包含所有 Promise 结果的数组 results
。
在这个示例中,Promise.all()
返回的 Promise 在约 3 秒后被解析,并且 results
数组包含了每个 Promise 对象解析的结果。如果其中任何一个 Promise 被拒绝,那么返回的 Promise 将立即被拒绝,并传递被拒绝的 Promise 的原因。
Promise.all()
对于同时处理多个异步操作非常有用,例如同时发起多个网络请求并等待它们的结果。它提供了一种简洁而方便的方式来管理和处理多个 Promise 对象的结果。
Promise.race() Promise.race()
是另一个常用的 Promise 方法,它接收一个 Promise 数组作为参数,并返回一个新的 Promise 对象。该 Promise 对象在数组中的任何一个 Promise 变为 fulfilled 或 rejected 状态时就会被解析,解析值或拒绝原因与第一个完成的 Promise 相关。
以下是 Promise.race()
的示例用法:
javascript
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Promise 2 rejected');
}, 3000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 3 resolved');
}, 1500);
});
Promise.race([promise1, promise2, promise3])
.then(result => {
console.log(result);
// 输出: 'Promise 3 resolved'
})
.catch(error => {
console.error(error);
});
在上面的示例中,我们创建了三个 Promise 对象 promise1
、promise2
和 promise3
,它们分别在不同的延迟后被解析或被拒绝。通过调用 Promise.race()
并传入这三个 Promise 对象的数组,我们等待其中任何一个 Promise 变为 fulfilled 或 rejected 状态。当第一个 Promise 完成时(无论是解析还是拒绝),.then()
方法会被调用,并接收该 Promise 的解析值或拒绝原因。
在这个示例中,Promise.race()
返回的 Promise 在约 1.5 秒后被解析,因为 promise3
是最先解析的 Promise。我们只关注第一个完成的 Promise,所以忽略了 promise1
和 promise2
的结果。如果第一个完成的 Promise 是拒绝状态,那么返回的 Promise 将立即被拒绝,并传递拒绝原因。
Promise.race()
对于处理竞争条件非常有用,例如同时发起多个异步操作,但只关心最快完成的结果。它提供了一种有效的方式来处理并发操作,并利用第一个完成的 Promise 的结果或错误。
10、async 函数
async
函数是一种特殊类型的函数,用于定义异步操作。它是 JavaScript 中的一项功能,允许你编写更具表达力和灵活性的异步代码。
在传统的 JavaScript 中,异步操作通常通过回调函数或 Promise 来处理。但是,使用 async
函数可以更简洁地处理异步代码。
下面是一个简单的例子,展示了如何使用 async
函数处理异步操作:
javascript
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function fetchData() {
console.log('开始获取数据...');
await delay(2000); // 等待2秒钟
console.log('数据获取完成!');
return '数据结果';
}
async function main() {
console.log('开始执行主函数...');
const result = await fetchData();
console.log('获取到的结果:', result);
}
main();
在上面的例子中,fetchData
函数模拟了一个异步操作,其中使用了 await
关键字来等待 delay
函数返回的 Promise 完成。然后,在 main
函数中,使用 await
等待 fetchData
函数的执行结果。
总结来说,async
函数是 JavaScript 中用于处理异步操作的一种语法糖。它使得异步代码更易于编写和阅读,并且能够以类似于同步代码的方式组织和处理异步操作。