当前位置: 首页 > java >正文

es6/7练习题1

文章目录

  • 前言
      • ✅ **题目 1:输出顺序题(async + Promise + 微任务)**
      • 📌 涉及知识点:
    • ✅ 原始代码:
    • ✅ 输出顺序是什么?
    • 🧠 步骤详解:
      • 🔷 第一步:执行同步代码
      • 🔷 第二步:执行微任务队列(当前宏任务执行完后)
    • 🧠 async/await 背后发生了什么?
    • ✅ 最终执行顺序汇总
    • ✅ 小结口诀(面试必备)
      • ✅ **题目 2:作用域与解构陷阱题**
      • ✅ **题目 3:this 指向 + 箭头函数**
      • ✅ **题目 4:数组解构与默认值**
      • ✅ **题目 5:Promise 链式调用陷阱题**
      • ✅ **题目 6:typeof 与 Symbol**
    • ✅ 原始代码回顾(题目 3):
    • 🧠 我们重点看 `"2"` 是怎么变成微任务的
      • 🔹 1. 调用 `async1()`
    • 🔁 等价的 Promise 写法是什么?
    • ✅ 那为什么 `"7"` 会比 `"2"` 先打印?
    • ✅ 最终执行顺序解释:
    • 🧠 小结:为什么 `"2"` 是微任务而 `"7"` 先执行?


前言

以下是几道高质量的 ES6+ 综合面试题,覆盖变量作用域、闭包、Promise、解构、this、async/await 等知识点,适合中高级前端岗位筛选与自我训练:


题目 1:输出顺序题(async + Promise + 微任务)

console.log("1");async function asyncFunc() {console.log("2");await Promise.resolve();console.log("3");
}asyncFunc();Promise.resolve().then(() => {console.log("4");
});console.log("5");

🧠 你能写出输出顺序吗?为什么?

✅ 正确输出:

1
2
5
4
3

这道题是ES6 面试经典题,考察你对以下内容的理解:

📌 涉及知识点:

  • async/await 的本质
  • Promise 微任务(microtask)
  • JavaScript 的 事件循环(Event Loop)
  • 同步 vs 微任务执行顺序

✅ 原始代码:

console.log("1");async function asyncFunc() {console.log("2");await Promise.resolve();console.log("3");
}asyncFunc();Promise.resolve().then(() => {console.log("4");
});console.log("5");

✅ 输出顺序是什么?

1
2
5
4
3

🧠 步骤详解:

🔷 第一步:执行同步代码

  1. console.log("1") 输出 → 1

  2. 声明 asyncFunc(不会执行,跳过)

  3. 调用 asyncFunc()

    • 输出 2
    • 遇到 await Promise.resolve() → 进入暂停状态,并将后面的 console.log("3") 注册为一个微任务
  4. 注册一个 Promise.resolve().then(...) → 将 console.log("4") 注册为另一个微任务

  5. console.log("5") 输出 → 5

🔷 第二步:执行微任务队列(当前宏任务执行完后)

  1. 执行 Promise.resolve().then(...) → 输出 4
  2. await 后面的微任务恢复 → 输出 3

🧠 async/await 背后发生了什么?

await 会把其后面的语句(如 console.log("3")放入微任务队列,不会立刻执行!

等价于:

function asyncFunc() {console.log("2");return Promise.resolve().then(() => {console.log("3");});
}

✅ 最终执行顺序汇总

阶段语句输出
同步console.log("1")1
同步asyncFunc() → log(“2”)2
同同步console.log("5")5
微任务队列.then(() => console.log("4"))4
微任务队列await 后 log(“3”)3

✅ 小结口诀(面试必备)

await 后的代码是微任务,必须等当前同步执行完 + 微任务队列依次执行;多个 .then()await 的顺序取决于注册先后。


题目 2:作用域与解构陷阱题

let a = 1;
function test() {console.log(a);let a = 2;
}
test();

❓这段代码会输出什么?

✅ 正确答案:

报错:Cannot access 'a' before initialization

🧠 原因:

  • 虽然是函数作用域,但 let a = 2 在作用域中形成暂时性死区(TDZ),在此之前访问会报错。

题目 3:this 指向 + 箭头函数

const obj = {name: "vue",say() {setTimeout(function () {console.log("1:", this.name)}, 0)setTimeout(() => {console.log("2:", this.name)}, 0)}
}obj.say();

✅ 输出:

1: undefined
2: vue

🧠 原因:

  • 普通函数 function () {}thiswindow(非严格模式);
  • 箭头函数不绑定 this,继承自 obj

题目 4:数组解构与默认值

const [a = 1, b = a + 1, c = b + 1] = [undefined, undefined];
console.log(a, b, c);

✅ 输出:

1 2 3

🧠 解构中默认值是惰性求值,逐个执行:

  • a = 1
  • b = a + 1 = 2
  • c = b + 1 = 3

题目 5:Promise 链式调用陷阱题

Promise.resolve().then(() => {console.log('A');return Promise.resolve('B');}).then((res) => {console.log(res);});

✅ 输出:

A
B

🧠 链式 then 中 return Promise,会等待该 Promise 解析完成并传递结果到下一个 then。


题目 6:typeof 与 Symbol

const sym = Symbol('test');
console.log(typeof sym);
console.log(typeof Symbol);

✅ 输出:

symbol
function

🧠 Symbol 是基本类型;但 Symbol 构造器本身是函数。


✅ 原始代码回顾(题目 3):

async function async1() {console.log("1");await async2();console.log("2");
}async function async2() {console.log("3");
}console.log("4");setTimeout(() => {console.log("5");
}, 0);async1();new Promise((resolve) => {console.log("6");resolve();
}).then(() => {console.log("7");
});console.log("8");

🧠 我们重点看 "2" 是怎么变成微任务的

🔹 1. 调用 async1()

  • 打印 "1"(同步执行)

  • 遇到 await async2()

    • 执行 async2(),打印 "3"(同步)
    • await 的行为:暂停函数的后续代码,挂起为微任务

这意味着:

await async2();
console.log("2");

这两行中的第二行 console.log("2")会被推迟到微任务队列中,在当前宏任务完成后执行。


🔁 等价的 Promise 写法是什么?

function async1() {console.log("1")return async2().then(() => {console.log("2")})
}

✅ 那为什么 "7" 会比 "2" 先打印?

因为这行代码:

new Promise((resolve) => {console.log("6")resolve()
}).then(() => {console.log("7")
});

中:

  • .then(() => { console.log("7") }) 是在当前宏任务中同步创建并注册的微任务
  • console.log("2")async1 函数在 await 之后才挂起注册的微任务

所以注册顺序是:

微任务 1:then(() => console.log("7"))   ← 更早注册
微任务 2:await async2() 后 console.log("2")  ← 稍后注册

✅ 最终执行顺序解释:

阶段内容输出
同步任务4 → 1 → 3 → 6 → 84, 1, 3, 6, 8
微任务队列then → console.log(“7”)7
微任务队列await 后 console.log(“2”)2
宏任务setTimeout → console.log(“5”)5

🧠 小结:为什么 "2" 是微任务而 "7" 先执行?

await 会把 await 后的语句包装成微任务,但它的注册是异步的,所以在当前宏任务后期才注册;
.then()同步注册微任务,因此先于 await 后代码执行。


http://www.xdnf.cn/news/4805.html

相关文章:

  • 微软推动智能体协同运作:支持 A2A、MCP 协议
  • mqtt选型,使用
  • 关键字where
  • Docker学习笔记
  • deeplabv3+街景图片语义分割,无需训练模型,看不懂也没有影响,直接使用,cityscapes数据集_25
  • python小说网站管理系统-小说阅读系统
  • 什么是HTML、CSS 和 JavaScript?
  • 电容的基本介绍
  • WPF 子界面修改后通知到主页面
  • 嵌入式 C 语言控制语句
  • 44 Python MySQL(PyMySQL 驱动)
  • Java的对象头:原理与源码详解
  • python实现的音乐播放器
  • 企业生产安全管理平台的功能架构
  • Java后端程序员学习前端之JavaScript
  • PHP反序列化漏洞
  • CBO和HBO区别及介绍
  • 【包含例题P1955、P1892、P2024、P1196】并查集、扩展域并查集、带权并查集
  • arcmap栅格数据地理坐标转换,从WGS84坐标到2000
  • 深入理解Bitmap及Roaring Map:原理与应用详解
  • PPIO × GPT4All:构建本地知识库,让AI更懂你
  • 从单智到多智:深度拆解基于MetaGPT的智能体辩论
  • AI原生手机:三大技术阵营的终极对决与未来展望
  • 使用Maple Flow创建电路最坏情况分析WCCA工作表
  • 【前端】每日一道面试题2:解释CSS盒模型的box-sizing属性,以及它在响应式布局中的作用。
  • 字符串哈希(算法题)
  • VR 南锣鼓巷:古老街区的数字化绘卷与沉浸式遨游​
  • 高处安装、维护拆除作业考试重点知识
  • PlatformIO
  • 遗传算法求解异构车队VRPTW问题