microtask-demo3

HTML

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<div id="content">
    		<div class="code-source">var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');

new MutationObserver(function() {
 	<span id="high1">console.log('mutate');</span>
}).observe(outer, {
 	attributes: true
});
7
function onClick() {
	<span id="high2">console.log('click');</span>

	<span id="high3">setTimeout(function() {</span>
		<span id="high4">console.log('timeout');</span>
	}, 0);

	<span id="high5">Promise.resolve().then(function() {</span>
		<span id="high6">console.log('promise');</span>
	});

	<span id="high7">outer.setAttribute('data-random', Math.random());</span>
}

inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

<span id="high8">inner.click()</span></div>
    		<div class="tasks queue-wrapper">
    			<div id="task-title" class="queue-title">tasks</div>
    			<div id="task-content" class="queue-content"></div>
    		</div>
    		<div class="microtask queue-wrapper">
    			<div id="microtask-title" class="queue-title">microtasks</div>
    			<div id="microtask-content" class="queue-content"></div>
    		</div>
    		<div class="js-stack queue-wrapper">
    			<div id="stack-title" class="queue-title">JS stack</div>
    			<div id="stack-content" class="queue-content"></div>
    		</div>
    		<div class="log queue-wrapper">
    			<div id="log-title" class="queue-title">log</div>
    			<div id="log-content" class="queue-content"></div>
    		</div>
    		<div id="prev-btn">prev</div>
    		<div id="next-btn">next</div>
    		<div class="alert-window"></div>
    	</div>

CSS

* {
  margin: 0;
  padding: 0;
  font-family: 'Microsoft Yahei';
}

#content {
  position: relative;
  width: 700px;
  height: 500px;
  margin: 0 auto;
  border: 1px solid gray;
  background-color: #e0e0e0;
}

.code-source {
  position: relative;
  width: 680px;
  height: 290px;
  background-color: #3b3b3b;
  overflow: auto;
  color: #ececec;
  white-space: pre-wrap;
  font-size: 16px;
  padding: 0 10px;
}

.code-source p {}

.queue-wrapper {
  position: relative;
  width: 100%;
  height: 40px;
  border-top: 1px solid gray;
  border-bottom: 1px solid gray;
  font-size: 0;
}

.queue-title {
  display: inline-block;
  vertical-align: top;
  width: 90px;
  height: 100%;
  padding: 0 5px;
  background-color: #bdbdbd;
  line-height: 40px;
  color: #242424;
  font-size: 16px;
}

.queue-content {
  display: inline-block;
  width: 590px;
  height: 100%;
  line-height: 40px;
  padding: 0 5px;
  background-color: #ececec;
  vertical-align: top;
  font-size: 16px;
  font-size: 0;
}

.queue-item {
  display: inline-block;
  width: auto;
  height: 35px;
  padding: 0 4px;
  margin: 0 2px;
  background-color: #e0e05b;
  vertical-align: middle;
  font-size: 16px;
  line-height: 35px;
  color: #393939;
}

.queue-highlighted {
  background-color: #ff5100;
}

span.selected {
  background-color: #959595;
}

#next-btn {
  position: absolute;
  width: 50px;
  height: 35px;
  right: 10px;
  bottom: 3px;
  background-color: gray;
  text-align: center;
  line-height: 35px;
  border: 1px solid #8d8d8d;
  border-radius: 4px;
  box-shadow: 1px 1px 4px 0px;
  cursor: pointer;
    -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
#prev-btn {
  position: absolute;
  width: 50px;
  height: 35px;
  left: 10px;
  bottom: 3px;
  background-color: gray;
  text-align: center;
  line-height: 35px;
  border: 1px solid #8d8d8d;
  border-radius: 4px;
  box-shadow: 1px 1px 4px 0px;
  cursor:...

JavaScript

'use strict';
(function() {
	var taskContent = document.getElementById("task-content");
	var microContent = document.getElementById("microtask-content");
	var stackContent = document.getElementById("stack-content");
	var logContent = document.getElementById("log-content");
	var nextBtn = document.getElementById("next-btn");
	var prevBtn = document.getElementById("prev-btn");
	var $alert = $(".alert-window");
	//语句高亮器
	var mark = function(selector) {
			$(".code-source span").removeClass('selected');
			$(selector).addClass('selected');
			location.hash = selector.substring(selector.lastIndexOf("#"), selector.length);
		}
		//事件循环器
	var eventLoop = (function() {
		var events = [];
		var domBackups = [];
		var eventBackups = [];

		return {
			push: function(event) {
				events.push(event);
			},
			next: function() {
				var event = events.shift();
				if (!event) {
					return;
				}
				var content = document.getElementById("content");
				$(content).find('*').stop(false, true);
				var temp = content.cloneNode(true);
				domBackups.push(temp);
				eventBackups.push(event);
				event();
			},
			rollback: function() {
				var temp = domBackups.pop();
				if (!temp) {
					return;
				}
				events = Array.from([eventBackups.pop()]).concat(events);
				var content = document.getElementById("content");
				document.body.insertBefore(temp, content);
				document.body.removeChild(content);
				taskContent = document.getElementById("task-content");
				microContent = document.getElementById("microtask-content");
				stackContent = document.getElementById("stack-content");
				logContent = document.getElementById("log-content");
				nextBtn = document.getElementById("next-btn");
				prevBtn = document.getElementById("prev-btn");
				$alert = $(".alert-window");
				nextBtn.addEventListener("click", function(event) {
					eventLoop.next();
				}, false);
				prevBtn.addEventListener("click", function(event) {
					eventLoop.rollback();
				},...