web性能实践

2019-05-07  本文已影响0人  萘小蒽

一. 作用域

前面我们了解作用域概念的以及作用域链是如何运作的。

  • 随着作用域链中的作用域数量的增加,访问当前作用域意外的变量的时间也在增加。
  • 查找作用域链外层变量,需要遍历作用域链,所以访问全局变量要比访问局部变量慢。

1. 避免全局查找
优化js性能最重要的就是注意全局查找。使用全局变量或者函数肯定要比局部的开销更大,因为涉及作用域链上的查找。

function updataUI(){
  var ings = document.getElementsByTagName("img");
  for( var i=0,len = imgs.length; i < len ;i++){
       imgs[i].title = document.title + "image" + i 
  }
  var msg = document.getElementById('msg');
  msg.innerHTML = "Update complete."
}

上面的函数包含了三个对于全局document对象的引用。如果页面上有多个图片,那么for循环中的document的引用就会被执行多次甚至上百次。

通过创建一个指向document对象的局部变量,就可以通过限制一次全局查找来改进这个函数的性能:

function updataUI(){
  var doc =  document;
  var ings = doc .getElementsByTagName("img");
  for( var i=0,len = imgs.length; i < len ;i++){
       imgs[i].title = doc .title + "image" + i 
  }
  var msg = doc .getElementById('msg');
  msg.innerHTML = "Update complete."
}

2. 选择正确方法
和 语言一样,性能问题的一部分是和用于解决问题的算法或者方法有关的。

计算科学中,算法的复杂度是使用O符号来表示的。

标记 名称 描述
O(1) 常数 不管有多少值,执行时间都是恒定的,一般表示简单值和存储在变量中的值
O(log.n) 对数 总的执行时间和值的数量相关,但是要完成算法并不一定要获取每个值。例如二分查找
O(n) 线性 总执行时间和值的数量直接相关。例如:遍历某个数组中的元素
O(n²) 平方 总执行时间和值的数量有关。每个值至少获取n次。例如:插入排序

O(1)常数-----指代字面值和存储在变量中的值;如下:

//常数例子
var value = 5;
var sum = 10 + value;
alert(sum)

上面的代码执行了四次常量值查找:数字 510,变量 valuesum。这段代码的整体复杂度被认为是O(1)

//常数例子
var values = [:5 , 10];
var sum  = values[0] + values[1];
console.log(sum)

访问数组的元素也是一个O(1)操作,和简单的变量查找效率一样。


O(n)------线性查找要比常数和对数复杂的多,比如访问对象上的属性,花费的时间更多,因为必须要在其原型链中对拥有该名称的属性进行一次搜索。

//线性例子1
var values = { first: 5, second: 10 };
var sum = values .first + values.second;
console.log(sum);  

上面的例子使用了两次属性查找来计算sum的值。一两次可能并不会导致明显的性能问题,但是进行成百上千次肯定会减慢执行速度。

//线性例子2
var query = window.location.href.substring(window.location.href.indexof('?')); 

上面的代码有6次属性查找,window.location.href.substring 三次,window.location.href.indexof又三次,(数一数代码中点的数量,确定属性查找的次数);

为了避免上个线性例子2的性能影响,我们可以将多次用到的对象属性,存储在局部变量中:

var url = window.location.href;
var query = url.substring(url.indexof('?')); 

上面第一次访问该属性是O(n),而存储在局部变量后,访问都是O(1)总共4次属性查找,相对于6次节省了33%,更大的脚本中进行这种优化,会获得更多性能上的改进。

  1. 减值迭代——大多数循环使用一个从0开始、增加到某个特定值得迭代器。在很多情况下,从最大值开始在循环中不断减值的迭代器更加高效。
  2. 简化终止条件——每次循环过程都会计算终止条件,所以必须保证它尽可能快。也就是避免属性查找或者其他O(n)的操作。
  3. 简化循环体——循环体是执行最多的,所以要确保其被最大限度地优化,确保没有某些可以被很容易移除循环的密集计算。
上一篇 下一篇

猜你喜欢

热点阅读