1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <button id="btn">click</button>
  9. <script src="./index.js"></script>
  10. </body>
  11. </html>
  1. const oBtn = document.getElementById('btn');
  2. oBtn.addEventListener('click', ()=>{
  3. console.log('1');
  4. Promise.resolve('m1').then((str)=>{
  5. console.log(str);
  6. })
  7. },false);
  8. oBtn.addEventListener('click',()=>{
  9. console.log('2');
  10. Promise.resolve('m2').then((str)=>{
  11. console.log(str);
  12. })
  13. },false);
  14. oBtn.click();

分析

宏任务中,事件处理函数就是回调,也是把addEventListener cb添加到宏任务队列
宏任务中,事件处理函数->回调
事件绑定addEventListener里面的回调函数cb不会直接运行,等事件触发才能运行,与setTimeout cb类似,都是得一定条件之后才能运行
oBtn.click();相当于点击事件触发了,也可以理解成点击事件触发时执行的是oBtn.click();
上面理解是错的,因为点击与执行,结果不一样

  1. const oBtn = document.getElementById('btn');
  2. //addEvent1
  3. oBtn.addEventListener('click', () => {
  4. console.log('1');
  5. //m1promise
  6. Promise.resolve('m1').then((str) => {
  7. console.log(str);
  8. })
  9. }, false);
  10. //addEvent2
  11. oBtn.addEventListener('click', () => {
  12. console.log('2');
  13. //m2promise
  14. Promise.resolve('m2').then((str) => {
  15. console.log(str);
  16. })
  17. }, false);
  18. //函数执行
  19. oBtn.click();

执行栈
script
1
2
m1promise.then cb 3th->m1
m2promise.then cb 4th->m2

宏任务
addEvent1
addEvent1 cb 1th
addEvent2
addEvent2 cb 2th

微任务
m1promise
m1promise.then cb 3th
m2promise
m2promise.then cb 4th

time 7m06s
相当于以下代码,oBtn.click();调用相当于执行了两个函数

  1. const handler1 = function(){
  2. console.log(1);
  3. Promise.resolve('m1').then((str)=>{
  4. console.log(str);
  5. })
  6. }
  7. const handler2 = function(){
  8. console.log('2');
  9. Promise.resolve('m2').then((str)=>{
  10. console.log(str);
  11. })
  12. }
  13. handler1();
  14. handler2();

image.png

点击按钮

time 9m42s
点击按钮与oBtn.click()运行不一样,点击按钮是addEvent1执行,m1promise cb进入微任务队列,之后清空微任务,再增加宏任务addEvent2 cb在宏任务队列中
也可以理解成,先走宏任务队列,增加宏任务addEvent1 cb,addEvent2 cb,宏任务队列有了两个宏任务,之后把addEvent1 cb推入js执行栈执行,把m1promise cb加入微任务栈,清空微任务栈,再执行宏任务,把剩下的addEvent2 cb推入js执行栈

  1. const oBtn = document.getElementById('btn');
  2. //addEvent1
  3. oBtn.addEventListener('click', () => {
  4. console.log('1');
  5. //m1promise
  6. Promise.resolve('m1').then((str) => {
  7. console.log(str);
  8. })
  9. }, false);
  10. //addEvent2
  11. oBtn.addEventListener('click', () => {
  12. console.log('2');
  13. //m2promise
  14. Promise.resolve('m2').then((str) => {
  15. console.log(str);
  16. })
  17. }, false);
  18. //函数执行
  19. //oBtn.click();

image.png

执行栈
script
addEvent1 cb 1th->1
m1promise.then cb 2th->m1
addEvent2 cb 3th->2
m2promise.then cb 4th->m2

宏任务
addEvent1
addEvent1 cb 1th
addEvent2
addEvent2 cb 3th

微任务
m1promise
m1promise.then cb 2th
m2promise
m2promise.then cb 4th

变形1

time 15m11s

  1. const oBtn = document.getElementById('btn');
  2. //addEvent
  3. oBtn.addEventListener('click', () => {
  4. setTimeout(() => {
  5. console.log('1');
  6. }, 0);
  7. //promise
  8. Promise.resolve('m1').then((str) => {
  9. console.log(str);
  10. })
  11. }, false);
  12. //addEvent
  13. oBtn.addEventListener('click', () => {
  14. setTimeout(() => {
  15. console.log('2');
  16. }, 0)
  17. //promise
  18. Promise.resolve('m2').then((str) => {
  19. console.log(str);
  20. })
  21. }, false);
  22. //函数执行
  23. // oBtn.click();

image.png

image.png

time 20m38s
函数执行与上面结果一样

  1. const oBtn = document.getElementById('btn');
  2. //addEvent
  3. oBtn.addEventListener('click', () => {
  4. //setTimeout
  5. setTimeout(() => {
  6. console.log('1');
  7. }, 0);
  8. //promise
  9. Promise.resolve('m1').then((str) => {
  10. console.log(str);
  11. })
  12. }, false);
  13. //addEvent
  14. oBtn.addEventListener('click', () => {
  15. //setTimeout
  16. setTimeout(() => {
  17. console.log('2');
  18. }, 0)
  19. //promise
  20. Promise.resolve('m2').then((str) => {
  21. console.log(str);
  22. })
  23. }, false);
  24. //函数执行
  25. oBtn.click();

image.png

分析

通过意思一样、类似,更容易看懂,更容易分析的代码分析

  1. const handler1 = function(){
  2. //setTimeout
  3. setTimeout(() => {
  4. console.log('1');
  5. }, 0);
  6. //promise
  7. Promise.resolve('m1').then((str) => {
  8. console.log(str);
  9. })
  10. }
  11. const handler2 = function(){
  12. //setTimeout
  13. setTimeout(() => {
  14. console.log('2');
  15. }, 0)
  16. //promise
  17. Promise.resolve('m2').then((str) => {
  18. console.log(str);
  19. })
  20. }
  21. handler1();
  22. handler2();

image.png