ES6

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 对象 promise1promise2promise3,它们分别在不同的延迟后被解析。通过调用 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 对象 promise1promise2promise3,它们分别在不同的延迟后被解析或被拒绝。通过调用 Promise.race() 并传入这三个 Promise 对象的数组,我们等待其中任何一个 Promise 变为 fulfilled 或 rejected 状态。当第一个 Promise 完成时(无论是解析还是拒绝),.then() 方法会被调用,并接收该 Promise 的解析值或拒绝原因。

在这个示例中,Promise.race() 返回的 Promise 在约 1.5 秒后被解析,因为 promise3 是最先解析的 Promise。我们只关注第一个完成的 Promise,所以忽略了 promise1promise2 的结果。如果第一个完成的 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 中用于处理异步操作的一种语法糖。它使得异步代码更易于编写和阅读,并且能够以类似于同步代码的方式组织和处理异步操作。

相关推荐
鸽鸽程序猿几秒前
【前端】javaScript
开发语言·前端·javascript
秦时明月之君临天下8 分钟前
React和Next.js的相关内容
前端·javascript·react.js
米奇妙妙wuu42 分钟前
React中 setState 是同步的还是异步的?调和阶段 setState 干了什么?
前端·javascript·react.js
new出一个对象6 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
你挚爱的强哥7 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
前端Hardy8 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189118 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
小镇程序员11 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
疯狂的沙粒11 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪11 小时前
AJAX的基本使用
前端·javascript·ajax