High Perfomance Javascript 笔记

第一章 加载与执行脚本
    这一章主要提供了几个提高脚本加载速度技巧:
    1、由于script标签会阻塞html页面的加载,浏览器会等到加载完script后才渲染页面,以防止script
    会对页面DOM元素进行操作,因此建议将script标签放在底部</body>前面,同事使用defer属性(支持ie)
    2、将多个脚本合并成为一个,减少http请求
    3、动态加载脚本,通过ajax或者动态创建script标签

第二章 数据访问

    这一章主要讲解如果提高访问数据的速度,文章对比了元数据类型,局部变量,数组,对象四种存储数据
    方式的性能,其中元数据类型是最高,其次是局部变量,接着就是数组和对象。这里我们可以理解为什么jquery要把window对象作为
    参数传进去,目的就是为了提高性能。
   
    js作用域:(scope)
   
    Each  time a variable  is encountered during  the  function’s execution,  the process of
  identifier resolution takes place to determine where to retrieve or store the data. During
  this process, the execution context’s scope chain is searched for an identifier with the
  same name. The search begins at the front of the scope chain, in the execution function’s
  activation object. If found, the variable with the specified identifier is used; if not, the
  search continues on to the next object in the scope chain. This process continues until
  either the identifier is found or there are no more variable objects to search, in which
  case  the  identifier  is deemed  to be undefined. The same approach  is  taken  for each
  dentifier found during the function execution
  
  每执行一个函数js会创建一个“执行环境”(execution context),每个执行环境都有一个作用域链(scope chain)
  当执行完毕后,执行环境也同时被销毁。当创建完“执行环境”后,所有函数变量会被复制到“执行环境”中,之后会创建一个
  activation object(活动对象),这个对象包含了函数的所有局部变量,参数命名,参数集合和this。然后这个对象会被压到
  scope chain的顶端。
  
  再引用文章的一段话:
  The deeper into the execution context’s scope chain an
  identifier exists, the slower it is to access for both reads and writes. Consequently, local
  variables are always the fastest to access inside of a function, whereas global variables
  will generally be the slowest (optimizing JavaScript engines are capable of tuning this
  in certain situations). Keep in mind that global variables always exist in the last variable
  object of the execution context’s scope chain, so they are always the furthest away to
  resolve.
  
  执行一个函数会从当前执行环境开始位置搜索变量,变量处于执行环境作用域链的位置越深,读写变量的速度就越慢。
  通常情况下,函数中的局部变量访问速度是最快的,而相反全局变量是最慢的。因此我们应该尽量将全局变量私有化,降低搜索
  变量的时间。
  
  不过文章也提到随着浏览器的发展,浏览器本身对js进行优化,到了chome,Safari 4,IE8影响就不怎么明显了
  
    这里引用http://hi.baidu.com/meteoric_cry/blog/item/7df9af2b92caa2f0e7cd40dd.html一段话对作用域的描述:
   
    a、javascript的作用域机制
  通过编译,javascript代码已经翻译成了语法树,然后会立刻按照语法树执行。
  进一步的执行过程,需要理解javascript的作用域机制:词法作用域(lexcical scope)。
  通俗地讲,就是javascript变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,
  编译器通过静态分析就能确定,因此词法作用域也叫做静态作用域(static scope)。
  但需要注意,with和eval的语义无法仅通过静态技术实现,所以只能说javascript的作用域机制非常接近词法作用域(lexical scope).
  javascript引擎在执行每个函数实例时,都会创建一个执行环境(execution context)。
  执行环境中包含一个调用对象(call object), 调用对象是一个scriptObject结构(scriptObject是与函数相关的一套静态系统,
  与函数实例的生命周期保持一致),用来保存内部变量表varDecls、内嵌函数表funDecls、父级引用列表upvalue等语法分析结构
  (注意varDecls和funDecls等信息是在语法分析阶段就已经得到,并保存在语法树中。函数实例执行时,会将这些信息从语法树复制到scriptObject上)。
  
  b、javascript作用域机制的实现方法
  词法作用域(lexical scope)是javascript的作用域机制,还需要理解它的实现方法,就是作用域链(scope chain)。
  作用域链是一个name lookup机制,首先在当前执行环境的scriptObject中寻找,没找到,则顺着upvalue到父scriptObject中寻找,
  一直lookup到全局调用对象(global object)。
  
  通过上面亮点,我们可以看出,js执行函数时候,搜索变量会在当前执行环境的scope chain中查找,如果找不到,就需要继续往上找
  那么这种搜索必定会带来性能的损耗,因此文章建议使用私有变量,尽量减少变量的搜索。
 
 
第三章 js操作DOM

    这一章讲到js操作DOM时,对性能的影响很大,因此我们应该尽量减少对DOM的操作,尽量减少页面的重绘和回流。
    其中提到了一些技巧:
    1、尽量减少对DOM的读取次数,对于循环体,我们可以先将元素赋值给局部变量,然后再在循环体中使用
    2、使用innerHTML进行批量修改
    3、缓存HTML Collections 的长度
    4、避免重绘和回流,批量修改样式,使用cssText或者class名修改样式,批量修改dom元素
    5、将dom元素display置为none后进行操作,然后再显示
    6、使用document.createDocumentFragment();复制一份需要更新的节点,然后修改后在更新原来的节点
   
   

原文地址:https://www.cnblogs.com/coolkiss/p/1771385.html