为什么typeof null的值在循环内变化?


109

在Chrome控制台中执行以下代码段:

function foo() {
    return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());

应该打印1000次false,但在某些机器上将打印false多次迭代,然后true进行其余迭代。

在此处输入图片说明

为什么会这样呢?这只是一个错误吗?


4
对我来说,它正在返回1000倍的真实……
隆龙

2
我认为是错误,我有262个错误/ 738个正确
Jax Teller

1
chrome的控制台有点奇怪:如果您推送到一个数组并记录该数组,就全部了false。照原样true,铬的s 数量会波动。
dandavis '16

1
正如我在问题中所说的,@HoàngLong仅在某些计算机上发生。也有可能仅在某些版本的Chrome上发生
Agos

2
@HoàngLong确保您在Chrome中运行它
Nobita

Answers:



37

实际上,这是一个V8 JavaScript引擎(Wiki)错误。

该引擎用于Chromium,Maxthron,Android OS,Node.js等。

您可以在此Reddit主题中找到相对简单的错误描述

现代JavaScript引擎在执行时(及时编译)将JS代码编译为优化的机器代码,以使其运行更快。但是,优化步骤需要一定的初始性能成本,以换取长期的加速,因此引擎会根据使用的频率来动态地决定一种方法是否值得。

在这种情况下,似乎仅在优化路径中存在错误,而未优化路径则可以正常工作。因此,一开始该方法可以按预期工作,但是如果在某个时刻被足够频繁地循环调用,引擎将决定对其进行优化并将其替换为越野车版本。

这个错误似乎已经在V8本身(commit)和Chromium(错误报告)和NodeJS(commit)中修复


我确认该错误仍然存​​在于Node.js 6.2.2中,这令我感到担忧。
Michael Shopsin

它已在今天(21.06)的V8引擎中修复,我相信很快会更新相关软件。
谢尔盖·诺维科夫

向后移植的V8修复程序的Node.js 6.2.x中已经作为问题上取得进展#7348所拥有TheAlphaNerd
Michael Shopsin

18

为了回答为什么会更改的直接问题,该错误在Chrome使用的V8 JS引擎的“ JIT”优化例程中。刚开始,代码的运行与编写时完全相同,但是运行的次数越多,优化带来的好处就越有可能超过分析成本。

在这种情况下,在循环中重复执行后,JIT编译器将分析该函数,并用优化的版本替换它。不幸的是,该分析做出了错误的假设,并且优化版本实际上未产生正确的结果。

具体来说,Reddit用户RainHappens认为这是类型传播中的错误:

它还进行一些类型传播(如变量等可以是什么类型)。当变量未定义或为null时,有一种特殊的“无法检测”类型。在这种情况下,优化器将变为“ null is not detectable,因此可以将其替换为” undefined”字符串以进行比较。

这是优化代码的难题之一:如何确保为性能而重新安排的代码仍具有与原始代码相同的效果。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.