JS 是单线程的
所以 JS 中的代码都是 串行
的, 前面没有执行完毕后面不能执行, 但是我如下的代码运行的结果并不是想前面我所说的,前面没有执行完毕后面不能执行
:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script>
console.log("1");
setTimeout(function () {
console.log("2");
}, 500);
console.log("3");
</script>
</head>
<body>
</body>
</html>
你们如果按照我所说的那句话来查看如上代码那么运行的结果你们认为是不是 1, 2, 3
但是真实结果并不是,而是 1, 3, 2
:
那么为什么是串行的还输出的是 1, 3, 2 呢,这个时候就需要去了解一下 JS 当中的事件循环这个东西了,还要了解一下 JS 当中的同步代码和异步代码。
同步代码和异步代码
除了 "事件绑定的函数"
和 "回调函数"
以外的都是 同步
代码。
- 程序运行会从上至下依次执行所有的同步代码
- 在执行的过程中如果遇到异步代码会将异步代码放到事件循环中
- 当所有同步代码都执行完毕后, JS 会不断检测事件循环中的异步代码是否满足条件
- 一旦满足条件就执行满足条件的异步代码
首先来看一个事件循环的这么一个东西吧,在我们编写完 JS 代码之后呢,JS 最后会自动在添加一段代码,类似如下的这个样子:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script>
// 异步代码数组
let arr = [
// 异步代码
setTimeout(function () {
console.log("2");
}, 500)
];
let index = 0;
let length = arr.length;
while (true) {
let item = arr[index];
if (item.time === 500) {
// 执行异步代码
}
index++;
if (index === length) {
index = 0;
break;
}
}
</script>
</head>
<body>
</body>
</html>
如上就是 JS 自动帮我们添加的类似的代码,但并不是一模一样的,在来看一个注意点,程序运行会从上至下依次执行所有的同步代码
:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script>
// 同步代码
console.log("1");
// 异步代码
setTimeout(function () {
console.log("2");
}, 500);
// 同步代码
console.log(3);
// 同步代码
alert("BNTang");
</script>
</head>
<body>
</body>
</html>
如上的示例代码如果 alter 这一行同步代码没有执行完毕,那么事件循环当中的异步代码就不会被执行,这就足以可以证明 JS 是单线程的了,效果可以自行运行在浏览器当中会弹出一个确认框,点击了确认之后异步代码当中的 2 才打印:
如上的这个实例就至于验证我如上所说的那几点都是正确的,在所有同步代码执行完毕之后 JS 会去不断的去事件循环当中判断有没有满足条件的异步代码然后进行执行异步代码当中的内容。
JS 为什么是单线程的
JavaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。例如: 如果 JS 是多线程的, 现在有一个线程要修改元素中的内容, 一个线程要删除该元素, 这时浏览器应该以哪个线程为准。