chrome 68提供了一个便利的新功能:Eager Evaluation
它可以让你在控制台输入一段代码后,无需回车运行即可看到执行结果(实际上是在你输入完后它会自动执行并显示结果)
显然,那些会改变外部变量(有副作用)的表达式不能使用这个功能(比如let a = 1; a++
就不会显示a++的结果2)
DevTools does not eager evaluate if the expression causes side effects
几天前我无意中发现Math.random()
也能使用Eager Evaluation,这产生了一个神奇的结果,效果如下图
一般来说,生成随机数会改变seed的值,因此random应该属于有副作用的函数,但是Eager Evaluation为什么会判断它是无副作用的呢?
我做了以下几个猜测:
- JS的
Math.random()
不能设置种子,它只能产生一个0-1的随机数,也就是说在js的环境中它没有(不需要)改变任何的变量,只是在v8中改变了seed,Eager Evaluation的实现是只要在js环境中无副作用就能触发 - 虽然它改变了seed,但因为
Math.random()
是唯一能够影响这个值的方式,且seed不能被指定初始值,所以Eager Evaluation单独标记了Math.random()
为纯函数 - 单纯是chrome的bug(应该不可能)
之前V8的4.x分支是没有种子,在5.x以及后面的分支版本都是有种子,目前v8的master分支默认就是在win下是用rand_s来做种,在其他环境下则是用/dev/urandom文件来做种。以目前的默认方式来看应该是且seed不能被指定初始值,道理上是第二条猜测。但我觉得实际上通过缓存还是能实现Eager Evaluation保持一致,估计是他们还没做到这步吧。 目前最新的node可以直接用–random-seed来指定种子(如我设置种子等于123),如下
node --random-seed=123
而且ECMA要求也简单,所以不同的浏览器,它可以想用什么算法都可以用,只要均匀就好
Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy. This function takes no arguments.