浏览器(IE和Firefox)每次页面刷新时都会解析链接的javascript文件吗?
他们可以缓存文件,因此我猜他们不会每次都尝试下载它们,但由于每个页面基本上是分开的,我希望它们可以拆除任何旧代码并重新解析它.
这是低效的,虽然完全可以理解,但我想知道现代浏览器是否足够聪明以避免站点内的解析步骤.我在想一个网站使用javascript库的情况,比如ExtJS或jQuery等.
这些是我能够挖掘的细节.首先值得注意的是,尽管JavaScript通常被认为是在VM上进行解释和运行,但现代解释器并不是这种情况,现代解释器倾向于将源代码直接编译为机器代码(IE除外).
Chrome:V8引擎
V8有一个编译缓存.这使用源的哈希存储编译的JavaScript,最多可存储5个垃圾收集.这意味着两个相同的源代码将共享内存中的缓存条目,无论它们是如何包含的.重新加载页面时不会清除此缓存.
资源
更新 - 19/03/2015
Chrome团队发布了有关JavaScript流媒体和缓存新技术的详细信息.
脚本流
脚本流优化了JavaScript文件的解析.[...]
从版本41开始,Chrome会在下载开始后立即在单独的线程上解析异步和延迟脚本.这意味着解析可以在下载完成后的几毫秒内完成,并使页面加载速度提高10%.
代码缓存
通常情况下,V8引擎会在每次访问时编译页面的JavaScript,并将其转换为处理器可以理解的指令.一旦用户导航离开页面,该编译的代码就被丢弃,因为编译代码在编译时高度依赖于机器的状态和上下文.
Chrome 42引入了一种存储已编译代码的本地副本的高级技术,因此当用户返回页面时,可以跳过下载,解析和编译步骤.在所有页面加载中,这使Chrome可以避免大约40%的编译时间,并在移动设备上节省宝贵的电池.
歌剧:Carakan Engine
实际上,这意味着无论何时编写脚本程序,其源代码与最近编译的其他程序的源代码相同,我们都会重用编译器的先前输出并完全跳过编译步骤.这种缓存在典型的浏览场景中非常有效,其中一个页面从同一站点加载页面,例如来自新闻服务的不同新闻文章,因为每个页面通常加载相同的,有时非常大的脚本库.
因此,JavaScript在页面重新加载时被缓存,对同一脚本的两个请求不会导致重新编译.
资源
Firefox:SpiderMonkey引擎
SpiderMonkey使用Nanojit
JIT编译器作为其本机后端.编译机器代码的过程可以在这里看到.简而言之,它似乎在加载时重新编译脚本.但是,如果我们仔细研究内部结构,Nanojit
我们会看到jstracer
用于跟踪编译的更高级别监视器可以在编译期间转换为三个阶段,从而为以下方面提供了一个好处Nanojit
:
跟踪监视器的初始状态是监视.这意味着spidermonkey正在解释字节码.每次spidermonkey解释向后跳转字节码时,监视器都会记录跳转目标程序计数器(PC)值跳转到的次数.此编号称为PC的命中计数.如果特定PC的命中计数达到阈值,则认为目标是热的.
当监视器确定目标PC很热时,它会查看片段的哈希表,以查看是否存在包含该目标PC的本机代码的片段.如果找到这样的片段,它将转换为执行模式.否则它将转换为录制模式.
这意味着对于hot
代码片段,本机代码被缓存.意义不需要重新编译.在页面刷新之间保留这些散列的原生部分并不清楚.但我会认为他们是.如果有人能为此找到支持证据那么优秀.
编辑:它已经指出,Mozilla开发鲍里斯Zbarsky曾表示,壁虎不缓存编译脚本还.取自这个SO答案.
Safari:JavaScriptCore/SquirelFish Engine
我认为这个实施的最佳答案已经由其他人提供.
我们目前不缓存字节码(或本机代码).这是
我们考虑过的一个选项,但是,目前,代码生成是
JS执行时间的一个微不足道的部分(<2%),所以我们目前不追求
这一点.
这是由Safari的首席开发人员Maciej Stachowiak撰写的.所以我认为我们可以认为这是真的.
我无法找到任何其他信息,但你可以阅读更多有关最新的速度提高SquirrelFish Extreme
发动机在这里,或浏览源代码,在这里,如果你喜欢冒险的感觉.
IE:Chakra引擎
目前还没有关于IE9的JavaScript引擎(Chakra)的信息.如果有人知道,请发表评论.
这是相当非正式的,但对于IE的旧的引擎实现,埃里克利珀(JScript中的MS开发商)在博客中回应称这里是:
JScript Classic就像编译语言一样,在任何JScript Classic程序运行之前,我们完全语法检查代码,生成完整的解析树,并生成字节码.然后我们通过字节码解释器运行字节码.从这个意义上说,JScript就像Java一样被"编译".不同之处在于JScript不允许您持久化或检查我们的专有字节码.此外,字节码比JVM字节码高得多 - JScript Classic字节码语言只不过是解析树的线性化,而JVM字节码显然是为了在低级别的堆栈机器上运行.
这表明字节码不会以任何方式持久存在,因此字节码不会被缓存.
正如其他答案所述,Opera就是这样做的.(来源)
火狐(SpiderMonkey的引擎),并没有缓存的字节码.(来源)
WebKit的(Safari浏览器,Konqueror中)确实不缓存字节码.(来源)
我不确定IE [6/7/8]或V8(Chrome),我认为IE可能会进行某种缓存,而V8可能不会.IE是封闭源,所以我不确定,但在V8中,缓存"编译"代码可能没有意义,因为它们直接编译为机器代码.