> 웹 프론트엔드 > JS 튜토리얼 > javascript code_javascript 팁의 성능을 향상시키는 방법

javascript code_javascript 팁의 성능을 향상시키는 방법

WBOY
풀어 주다: 2016-05-16 16:06:16
원래의
1145명이 탐색했습니다.

원래는 유지보수성 코드 글을 작성한 후 이 코드 성능 글을 요약하려고 했으나, 원래는 빚이 너무 많아서 이전에 요약하지 않았기 때문에 매일 글을 업데이트하기로 했습니다. , 배운 내용을 요약하지 않으면 매우 빨리 잊어버리게 됩니다. 기록하면 특히 코드의 유지 관리 가능성, 성능 등에 대한 인상이 마음에 남게 됩니다. , 그렇다면 당신은 대단합니다! 초보자를 위한 제안은 다음과 같습니다. 배운 내용을 더 많이 요약하세요. 이는 실제로 새로운 지식을 배우는 것이기 때문입니다! 자, JS 코드의 성능을 향상시키는 방법이라는 주제로 넘어가겠습니다.

1. DOM 상호작용 최적화

DOM은 페이지를 렌더링할 때 파싱된 DOM 요소를 렌더링한다는 의미입니다. DOM 작업 및 상호작용은 페이지 전체 또는 일부를 다시 렌더링해야 하는 경우가 많기 때문에 많은 시간이 소요됩니다. . 게다가 겉으로 보기에는 미묘해 보이는 일부 작업은 수행하는 데 많은 시간이 걸릴 수 있습니다. DOM이 많은 정보를 처리해야 하기 때문입니다. 따라서 브라우저의 페이지 렌더링 속도를 높이기 위해 DOM 관련 작업을 최대한 최적화해야 합니다. 일부 DOM 작업이 페이지 성능에 영향을 미치는 이유는 무엇입니까? 브라우저 원리에 대해 제가 쓴 기사를 확인해 보세요.

자, DOM 작업을 최적화하는 몇 가지 주요 방법이 있습니다.

1.1 현장 업데이트 최소화

DOM 라이브 업데이트란: DOM에 이미 표시되어 있는 페이지의 일부 표시를 즉시 업데이트해야 합니다. 그러나 단일 문자를 삽입하든 전체 조각을 삽입하든 상관없이 모든 변경에는 브라우저가 업데이트하기 위해 수많은 차원을 다시 계산해야 하기 때문에 특정 성능 저하가 발생합니다. 따라서 라이브 업데이트가 많을수록 코드 실행 시간이 길어지고, 반대로 코드 실행 속도도 빨라집니다.

var list = document.getElementById('mylist'),
      item,
      i;
for(i = 0; i < 10; i++){
  item = document.creatElement('li');
  list.appendChild(item);
  item.appendChild(document.creatTextNode('item' + i));
}
로그인 후 복사

이 코드는 목록 mylist에 10개의 항목을 추가합니다. 항목이 추가되지 않은 경우 2번의 현장 업데이트(요소 추가 및 텍스트 노드 추가)가 필요하므로 이 작업에는 20번의 현장 업데이트가 필요합니다. 성능을 보면 이러한 코드가 상대적으로 느리게 실행되는 것을 볼 수 있습니다.

해결책은 문서 조각화를 사용하여 DOM 요소를 간접적으로 변경하는 것입니다.

var list = document.getElementById('mylist'),
      fragment = document.creatDocumentFragment(),
      item,
      i;
for(i = 0; i < 10; i++){
  item = document.creatElement('li');
  fragment .appendChild(item);
  item.appendChild(document.creatTextNode('item' + i));
}
list.appendChild(fragment);
로그인 후 복사

이와 같은 코드는 라이브로 한 번만 업데이트하면 됩니다. 문서 조각을appendChild()에 전달할 때 조각 자체가 아닌 문서 조각의 하위 노드만 대상 요소에 추가된다는 점을 기억하십시오.

이제 루프를 사용하여 DOM 노드 `(∩_∩)'를 직접 추가, 삭제, 확인 및 수정하면 브라우저에 얼마나 미안한지 이해해야 합니다.

1.2 innerHTML 사용

위 코드에서 DOM 요소를 생성하기 위해 사용된 createElement()와appendChild()의 결합 메소드 외에도 innerHTML에 값을 할당하여 생성할 수도 있습니다. 작은 DOM 변경의 경우 두 방법의 효율성은 실제로 거의 동일하지만, 많은 수의 DOM 노드를 변경하는 경우 후자가 전자보다 훨씬 빠릅니다! 왜 꼬집어?

innerHTML에 값을 할당하면 백그라운드에서 HTML 파서가 생성된 다음 Javascript 기반 DOM 호출이 아닌 내부 DOM 호출을 사용하여 DOM 구조를 생성하기 때문입니다. 해석되는 것보다 코드 실행 속도가 훨씬 빠릅니다!

innerHTML을 사용하여 위의 예를 다시 작성하세요.

  var list = document.getElementById('mylist'),
       html = '', //声明一个空字符串
        i;
  for(i = 0; i < 10; i++){
    html += '<li>item' + i + '</li>';
  }
  list.innerHTML = html; // 这里记得innerHTML后面的HTML四个字母都要大写!
로그인 후 복사

这种方式同样也只进行了一次的现场更新,并且性能要比上一种方式要好!虽然在字符串的链接上有点性能损失。

1.3 使用事件代理/事件委托

事件处理程序为web应用提供交互能力,因此许多开发人员会不分青红皂白地向页面中添加大量的处理程序,有个问题就是一个页面上的事件处理程序数量将直接关系到页面的整体运行性能。为什么捏?

首先,事件处理程序对应至少一个函数,JS中每个函数都是对象,都会占用内存,内存中的对象越多,性能就越差。

其次,我们必须事先指定所有事件处理程序,这就导致了DOM访问次数增多,会延迟整个页面的交互就绪时间,页面响应用户操作变得相对缓慢。

所以减少事件处理程序同样也可以让我们的页面更牛畅!使用事件委托势在必得啊!

事件委托的原理其实就是事件冒泡,只指定一个事件处理程序就可以管理某一类型操作的所有事件。例如:click事件会一直冒泡到document层次,也就是说我们不必为每个元素添加事件,只需在较高的层次的元素上添加事件处理程序即可,然后利用事件对象(event)的属性或方法去判断当前点击的元素,然后做出相应的响应。这个我就不展开讲了,初学者可以自行查阅事件冒泡知识。

2.作用域很重要

说到作用域啊就很容易想到作用域链(scope chain),我们知道要搜索一个变量,所在的执行环境都要沿着这条作用域向上搜索这个变量,作用域链上有很多的变量,那么我们就得遍历,遍历就需要时间啊,而且你越往上查找所需时间越多,如果我们能减少这个时间,我们代码执行效率不是可以提高了吗?

好聪明啊,ok,我看看有哪些方式可以减少这个时间:

2.1 避免全局查找

这是性能优化的一重点,上面也说了,越往上查找时间越多,也就是说查找全局变量和函数比局部要多!看代码:

function updateUI(){
  var imgs = document.getElementByTagName('img');
  for(var i = 0 ,lng = imgs.length;i < lng;i ++){
    imgss[i].title = document.title + 'image' + i;
  }
  var msg = docuement.getElementById('msg');
  msg.innerHTML = 'update complete.';
}
로그인 후 복사

这代码很正常呀!我之前也经常这么做滴。但是我们细心可以发现,这段代码有三处引用了全局变量document,如果我们的页面很多图片,那么在for循环中的document就会被执行上百次,而每次都要需要在作用域链中查找,时间都去哪了,我还没......停!。

我们可以通过在函数中创建一个局部变量保存对document的引用,这样,我们在函数里任何地方引用document都不用跑到全局变量去找了。这样就改进了代码的性能,看代码:

function updateUI(){
  var doc = document; // 将document保存在局部变量doc中
  var imgs = doc.getElementByTagName('img');
  for(var i = 0 ,lng = imgs.length;i < lng;i ++){
    imgss[i].title = doc.title + 'image' + i;
  }
  var msg = doc.getElementById('msg');
  msg.innerHTML = 'update complete.';
}
로그인 후 복사

所以啊,我们在开发中,如果在函数中会经常用到全局变量,把它保存在局部变量中!

2.2 避免使用with语句

用with语句延长了作用域,查找变量同样费时间,这个我们一般不会用到,所以不展开了。解决方法还是和上面的例子一样,将全局变量保存在局部变量中!

3.优化循环

循环在编程中可谓家常便饭,在js中也随处可见,循环体会反复地执行同一段代码,执行时间一直累加,所以能够对循环体的代码进行优化也可以大大减少执行时间!如何优化?四种方式。

3.1 减值迭代

我们写迭代器(循环条件)的时候一般都这样(var i = 0;i < 10;i ++),从0开始,增加到某个特定值。然而在很多情况下,如果在循环中使用减值迭代器效率更高。我测试了下,如果循环体不复杂的话,两者差不多!

//增值迭代 --效率较低
for(var i = 0;i < items.length;i++){
  doSomething(items[i]); 
}
//减值迭代 --效率较高
for(var i = items.length - 1;i >= 0;i--){
  doSomething(items[i]); 
}
로그인 후 복사

3.2 简化终止条件

由于每次循环都会计算终止条件,所以必须保证它的执行尽可能地块。这里主要是避免其他DOM元素及其属性的的查找。

 //看终止条件,每次循环都需要查询items及其length属性
for(var i = 0;i < items.length;i++){
  doSomething(items[i]); 
}

//将items.length的值保存在局部变量lng中。
for(var i = 0,lng = items.length;i < lng;i++){
  doSomething(items[i]); 
}
로그인 후 복사

3.3 简化循环体

原因和上面以上的,所以在循环体内避免大量的密集的操作。

这其实和上面讲的:1.1 最小化现场更新 。是一样的优化方式。可以倒回去看看。

4.基本的算法优化

在计算机中,算法的复杂度用O表示。下面是javascript中几种常见的算法类型:

O(1) :常数,不管有多少值,执行的时间都是恒定的,比如简单值和存储在变量中的值。
O(log n):对数,总的执行时间和数量有关,但不一定要获取每一个值,如:二分法查找
O(n) :线性,总执行时间和数量直接相关,如:遍历
O(n*n) :平方,总执行时间和数量有关,每个值至少获取N次,如:插入排序
ok,有了上面的知识,我们就可以对javascript进行一些算法上的优化了。看代码:

var value = 5;
var sum = value + 10;
alert(sum);
로그인 후 복사

这段代码进行了4次常量值的查找:数字5,变量value,数字10,变量sum,这段代码的算法复杂度就是O(1)。又如:

var value = [10,5];
var sum = value[0] + value[1];
alert(sum);
로그인 후 복사

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

var value = {one:10,two:10};
var sum = value.one + value.two;
alert(sum);
로그인 후 복사

要表达的是访问对象上的属性要比访问数组和变量的效率低。因为这是一个O(n)操作。你需要在对象的原型链中查找该属性,所花时间较多。

好了,看完这个是不是感觉眼前一片光明啊。其实我们前面所讲的要把经常用到的全局属性保存在一个局部变量中就是根据这个原理了,访问全局属性是一个O(n)的操作,而访问变量是一个O(1)的操作,大声告诉我,挖掘机哪家强啊!

5.最小化语句数

前面讲的优化差不多都是和精简优化语句有关的,是的,我觉得代码的质量和数量就是性能的评判标准。前面讲了一些代码质量相关的优化,这里就讲讲代码数量的优化。

5.1 精简变量声明

//用了5条语句声明5个变量
var count = 5;
var color = 'red';
var values = [1,2,3];
var now = new Date();

//用了1条语句声明5个变量,注意每个变量用逗号隔开
var count = 5,
  color = 'red',
  values = [1,2,3],
  now = new Date();

로그인 후 복사

5.2 使用数组和对象字面量

// 创建两个对象 ----不好的方式
//one 四条语句
var values = new Array();
values[0] = 123;
values[1] = 456;
values[2] = 789;
//two 四条语句
var person = new Object();
person.name = 'jozo';
person.age = 21;
person.sayName = function(){
  alert(this.name);
};
// 创建两个对象 ----推荐的方式
//one 1条语句
var values = [123,456,789]
//two 1条语句
var person = {
  name : 'jozo',
  age : 21,
  sayName : function(){
  alert(this.name);
};
로그인 후 복사

6.其他

写累了,如有不正确的地方请指正哦,还有一些其他的优化,下次文章继续!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿