????????关于如何使用JavaScript语言来编写高效的代码,有很多铺天盖地的经验分享,以及很多特别好的建议,读者可以搜索相关的词条,就能获得一些你可能需要的结果。同时,本节希望结合前面介绍的各种引擎内部的技术,按照特定的类别为读者归纳一些方式和方法,让我们从以下几个方面来解读它们。
????????在浏览器中,JavaScript引擎和渲染引擎WebKit需要协同工作才能达到一个好的效果,结合这二者,这一小节来介绍一个简单的例子,就是后来被引入的新的JavaScript接口requestAnimationFrame,以此来解释它是如何解决两者之间一些比较难以处理的问题的,以及它给Web前端开发者带来的思考。
????????接触过JavaScript的读者应该有过了解或者使用setTimeout或setInterval的经历,其功能是在每个时间间隔之后一次性或者重复多次执行一段JavaScript代码(称为回调函数),以完成特定的动画要求。但是,这里面多少还有些疑问。
????????这些问题对setTimeout和setInterval来说很重要。对主循环机制和渲染机制有一定了解的读者来说,上面这几条其实是非常难做到的,哪怕是较为接近理想的结果也很难达到。
????????幸运的是,总是有聪明的人来帮助大家解决难题。对问题提出一个漂亮解决方案的是Mozilla的Robert O'Callahan。他的灵感和依据来源于CSS。CSS能够知道动画什么时候发生,所以能够较为准确地知道什么时候该刷新用户界面。对于JavaScript来说,是不是也可以应用类似的机制呢?答案是肯定的。其做法是增加一个新的函数requestAnimationFrame,该函数告诉浏览器JavaScript想发起一个动画帧,然后在动画帧绘制之前,需要做一些动作,这样浏览器可以根据需要来优化自己的消息循环机制和调用时间点,以达到较好的平衡效果。
????????WebKit中setTimeout和setInterval的实现机制是类似的,区别在于后者是重复性的,如图9-28所示的类关系。
????????????????????????? ? ? ? ? ? ? ? ? ? 图9-28 WebKit中的计时器等相关类
????????WebKit会为DOM树中的每个setTimeout和setInterval调用创建一个DOMTimer,而后该对象会由存储TLS(Thread Local Storage)中的ThreadTimers负责管理,其内部其实是一个最小堆,每次将超时时间设置为最小的。同时,时间相同的计时器可以合并。当计时器超时后,Chromium将清除该计时器对象,同时调用相应的回调函数,回调函数通常会更新页面的样式和布局,这会触发重新计算布局,从而触发立即重新绘制一个新帧。结合上面的描述,这里大致总结一下setTimeout和setInterval的不足。
????????现在再来看看requestAnimationFrame是如何解决这些不足之处的呢?其原理就是其会申请绘制下一帧,至于什么时候还不知道,都是由浏览器决定,浏览器只需要在绘制下一帧前执行其设置的回调函数,完成JavaScript代码对动画所做的设置和逻辑即可。基本过程如下。
上面这些描述会给Web前端开发者们在编写JavaScript代码时带来哪些思考和便利呢?
????????一个新的JavaScript接口可以带来很不错的处理方式,以此来平衡JavaScript引擎和渲染引擎之间的关系,并且能够有效帮助那些利用JavaScript和HTML5技术来实现动画的开发者们,这一点值得我们思考。
????????因为历史的局限性,JavaScript最初的时候并不合适用来开发大工程和性能要求非常高的场景,所以开发者编写的代码对性能要求也不是很高。但是,目前的发展趋势是需要很高的性能,为此,仅仅依靠任何一方是没有办法来达到此目标的。笔者认为,今后为了高效的JavaScript代码性能,至少需要以下三个方面的努力,而且,就目前而言,它们也都在不停地向前发展。
????????首先是JavaScript语言和规范的发展。目前虽然规范定义的WebWorker在一定程度上能够并发,但是能力非常有限,而且两者之间只能通过有限的方式来通信(这个技术是由W3C组织引入的)。如果能够在ECMAScript标准中推动并行JavaScript能力,这绝对是一个大胆而又令人神往的想法。目前,一些大公司或者组织已经在推动并行JavaScript,希望未来有快速的发展,能够带领JavaScript真正进入并行时代。
????????其次是JavaScript引擎技术的发展和创新。一个简单的例子就是,V8不停地将之前用在其他编译器的技术带入到JavaScript引擎中来,同时自身也创造一些新的方法。据笔者目前观察得知,基本每个V8版本的升级都会带来性能上的提高,大家有理由相信,在这场JavaScript引擎大战中,各个引擎都会不停地提升技术以提升性能。
????????最后是同Web前端开发者相关的,那就是关于编写高效的JavaScript代码。结合语言的新能力和引擎技术的不断发展,要根据它们的特点,使用新技术和回避一些会对引擎带来重大性能伤害的用法。目前还没有这方面的系统介绍,希望未来能够有更多帮助开发者提高代码效率的使用方法被共享出来。