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

时间:2016-06-21 08:39:03

标签: javascript v8

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

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

应打印1000次false,但在某些计算机上会打印false一段时间,然后再true

enter image description here

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

4 个答案:

答案 0 :(得分:74)

为此开放了一个铬虫:

Issue 604033 - JIT compiler not preserving method behavior

所以是的,这只是一个错误!

答案 1 :(得分:37)

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

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

您可以在此bug description找到相对简单的Reddit topic

  

现代JavaScript引擎将JS代码编译为优化的机器代码   执行时(Just In Time编译)使其运行得更快。   但是,优化步骤具有一些初始性能成本   交换长期加速,因此引擎动态决定   一种方法是否值得,取决于它的使用频率。

     

在这种情况下,仅在优化路径中出现错误,   而未优化的路径工作正常。所以起初这个方法就像   打算,但是如果它在一个循环中被调用,那么在某些时候它就足够了   引擎将决定对其进行优化并将其替换为越野车   版本

此错误似乎已在V8本身(commit)以及Chromium(bug report)和NodeJS(commit)中得到修复。

答案 2 :(得分:18)

为了回答它为何发生变化的直接问题,该错误发生在Chrome使用的V8 JS引擎的“JIT”优化例程中。首先,代码的运行与编写完全相同,但运行得越多,优化的好处就越有可能超过分析成本。

在这种情况下,在循环中重复执行后,JIT编译器会分析该函数,并将其替换为优化版本。不幸的是,分析假设不正确,优化版本实际上并没有产生正确的结果。

具体而言,Reddit user RainHappens suggests 类型传播中的错误

  

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

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

答案 3 :(得分:1)