众所周知,JavaScript在所有现代浏览器实现中都是单线程的,但这是在任何标准中指定的还是只是传统?假设JavaScript总是单线程的,这是完全安全的吗?
当前回答
我已经尝试了@bobince的例子,做了轻微的修改:
<html>
<head>
<title>Test</title>
</head>
<body>
<textarea id="log" rows="20" cols="40"></textarea>
<br />
<button id="act">Run</button>
<script type="text/javascript">
let l= document.getElementById('log');
let b = document.getElementById('act');
let s = 0;
b.addEventListener('click', function() {
l.value += 'click begin\n';
s = 10;
let s2 = s;
alert('alert!');
s = s + s2;
l.value += 'click end\n';
l.value += `result = ${s}, should be ${s2 + s2}\n`;
l.value += '----------\n';
});
window.addEventListener('resize', function() {
if (s === 10) {
s = 5;
}
l.value+= 'resize\n';
});
</script>
</body>
</html>
所以,当你按下运行,关闭警报弹出并执行“单线程”,你应该会看到如下内容:
click begin
click end
result = 20, should be 20
但如果你尝试在Opera或Firefox稳定的Windows上运行这个,并最小化/最大化屏幕上弹出的警告窗口,那么会有这样的东西:
click begin
resize
click end
result = 15, should be 20
我不想说,这是“多线程”,但一些代码在错误的时间执行,我没有预料到这一点,现在我有一个损坏的状态。 最好了解这种行为。
其他回答
No.
我要跟大家唱反调,但请大家耐心听我说。单个JS脚本的目的是有效的单线程,但这并不意味着它不能被不同的解释。
假设您有以下代码……
var list = [];
for (var i = 0; i < 10000; i++) {
list[i] = i * i;
}
这是在期望到循环结束时,列表必须有10000个索引平方的条目,但VM可能会注意到循环的每次迭代都不影响其他迭代,并使用两个线程重新解释。
第一个线程
for (var i = 0; i < 5000; i++) {
list[i] = i * i;
}
第二个线程
for (var i = 5000; i < 10000; i++) {
list[i] = i * i;
}
这里我简化了,因为JS数组比内存块更复杂,但如果这两个脚本能够以线程安全的方式向数组中添加条目,那么当它们都完成执行时,它将得到与单线程版本相同的结果。
虽然我不知道有哪个VM可以检测这样的可并行代码,但它似乎在将来会出现在JIT VM中,因为它在某些情况下可以提供更快的速度。
进一步应用这个概念,可以对代码进行注释,让VM知道要将哪些代码转换为多线程代码。
// like "use strict" this enables certain features on compatible VMs.
"use parallel";
var list = [];
// This string, which has no effect on incompatible VMs, enables threading on
// this loop.
"parallel for";
for (var i = 0; i < 10000; i++) {
list[i] = i * i;
}
自从Web worker开始使用Javascript,不太可能……更丑陋的系统将会出现,但我认为可以肯定地说Javascript传统上是单线程的。
尝试在彼此内嵌套两个setTimeout函数,它们将表现为多线程(即;外部计时器在执行其功能之前不会等待内部计时器完成)。
@Bobince提供了一个非常模糊的答案。
引用Már Örlygsson的回答,Javascript总是单线程的,因为这个简单的事实:Javascript中的所有内容都是沿着单一的时间轴执行的。
这是单线程编程语言的严格定义。
Chrome是多进程的,我认为每个进程都有自己的Javascript代码,但就代码所知,它是“单线程”的。
Javascript中不支持多线程,至少不是显式的,所以没有什么区别。
是的,尽管Internet Explorer 9会在一个单独的线程上编译你的Javascript,为在主线程上执行做准备。但是,对于作为程序员的您来说,这并没有任何改变。
推荐文章
- javascript toISOString()忽略时区偏移
- 如何在JavaScript中获得当前时间
- 我如何从一个元标签与JavaScript的信息?
- 匹配精确字符串
- Haskell对Node.js的响应是什么?
- 用JavaScript创建一个基于字符串的十六进制颜色
- JavaScript数据网格数百万行
- 我可以在JavaScript中获得当前运行函数的名称吗?
- 如何防止输入键提交网页表单?
- 在html文本框中设置键盘插入符号的位置
- 使用jQuery选择多个类
- Cypress:只运行一个测试
- 如何同步确定JavaScript Promise的状态?
- 在Link react-router中传递道具
- 我如何承诺本地XHR?