루프에서 매번 배열의 길이 속성에 액세스하지 말고 루프가 시작되기 전에 캐시하세요.
var myLength = myArray.length; for (var i = 0; i < myLength; i++) { // do stuff }
루프 외부에서 추가 작업 수행
DOM을 직접 조작하는 것은 성능 집약적입니다. 특히 루프에서 DOM을 직접 조작하지 마십시오.
// 这样性能很差 $.each(myArray, function(i, item) { var newListItem = '<li>' + item + '</li>'; $('#ballers').append(newListItem); }); <p>// 这样性能较好<br />var frag = document.createDocumentFragment();</p><p>$.each(myArray, function(i, item) {<br /> var newListItem = '<li>' + item + '</li>';<br /> frag.appendChild(newListItem);<br />});<br />$('#ballers')[0].appendChild(frag);</p><p>// 这样也很好<br />var myHtml = '';</p><p>$.each(myArray, function(i, item) {<br /> html += '<li>' + item + '</li>';<br />});<br />$('#ballers').html(myHtml);</p>
코드를 간결하게 유지하세요
반복적인 작업을 피하세요. 같은 일을 계속하면 뭔가 잘못되었을 수 있습니다.
// 丑 if ($eventfade.data('currently') != 'showing') { $eventfade.stop(); } if ($eventhover.data('currently') != 'showing') { $eventhover.stop(); } if ($spans.data('currently') != 'showing') { $spans.stop(); } // 漂亮!! var $elems = [$eventfade, $eventhover, $spans]; $.each($elems, function(i,elem) { if (elem.data('currently') != 'showing') { elem.stop(); } });
익명 기능 주의
익명 함수가 여기저기로 날아다니는 것은 매우 고통스럽습니다. 디버깅, 유지 관리, 테스트 또는 재사용이 어렵습니다. 효과적인 관리를 구현하려면 함수 이름을 최대한 지정하고 객체에 캡슐화해야 합니다.
// 不好 $(document).ready(function() { $('#magic').click(function(e) { $('#yayeffects').slideUp(function() { // ... }); }); $('#happiness').load(url + ' #unicorns', function() { // ... }); }); // 好 var PI = { onReady : function() { $('#magic').click(PI.candyMtn); $('#happiness').load(PI.url + ' #unicorns', PI.unicornCb); }, candyMtn : function(e) { $('#yayeffects').slideUp(PI.slideCb); }, slideCb : function() { ... }, unicornCb : function() { ... } }; $(document).ready(PI.onReady);
선택기 최적화
document.querySelectorAll()을 지원하는 브라우저가 늘어나면서 선택기의 부담이 서서히 브라우저로 이전되었지만 여전히 주의해야 할 몇 가지 팁이 있습니다.
가능한 경우 ID 선택기의 우선순위를 정하고 사용하세요.
// 快 $('#container div.robotarm'); // 相当快 $('#container').find('div.robotarm'); 使用 $.fn.find 的方式更快,因为在 $.fn.find 之前的选择器并没有使用 jQuery 自带的 Sizzle 选择器引擎,而是使用了浏览器 document.getElementById() 方法,浏览器原生的方法自然更快。 使用组合选择器时,尽可能使右端更明确,而左端不尽量不明确: // 未优化 $('div.data .gonzalez'); // 已优化 $('.data td.gonzalez');
선택기 오른쪽 끝에는 tag.class를 사용하고, 가능하면 왼쪽 끝에는 tag나 .class만 사용하세요.
지나치게 구체적이지 마세요.
$('.data table.attendees td.gonzalez'); // 在不影响结果的情况下尽量删掉中间多余部分 $('.data td.gonzalez');
간결한 DOM 구조는 선택기의 성능을 향상시키는 데에도 도움이 됩니다. 왜냐하면 선택기가 해당 요소를 찾는 데 더 적은 우회가 필요할 수 있기 때문입니다.
와일드카드를 명시적으로 또는 암시적으로 사용하지 마세요. 선택기의 성능이 저하됩니다.
$('.buttons > *'); // 极慢 $('.buttons').children(); // 好多了 $('.gender :radio'); // 隐式地使用通配符,慢 $('.gender *:radio'); // 显式地使用通配符,同上,慢 $('.gender input:radio'); // 嗯,快多了
이벤트 프록시 사용
이벤트 프록시를 사용하면 이벤트가 컨테이너의 모든 요소(예: 목록 요소 li)가 아닌 컨테이너(예: 순서가 지정되지 않은 목록 ul)에 바인딩될 수 있습니다. $.fn.live 및 $.fn.delegate는 모두 이벤트를 컨테이너에 바인딩하지만 $.fn.delegate는 가능한 한 많이 사용해야 하며 결국 명확한 컨텍스트($.fn.live 문서의 컨텍스트와 비교)를 사용해야 합니다. )은 훨씬 작으므로 불필요한 필터링을 많이 피할 수 있습니다.
성능 향상 외에도 이벤트에 바인딩된 컨테이너에 새 요소를 추가하면 이러한 새 요소를 이벤트에 다시 바인딩할 필요가 없다는 점도 장점입니다.
// 不好 (如果列表元素非常多,你就悲剧了) $('li.trigger').click(handlerFn); // 好些:使用 $.fn.live 进行事件代理 $('li.trigger').live('click', handlerFn); // 最好:使用 $.fn.delegate 进行事件代理 // 因为这样可以明确的指定一个上下文 $('#myList').delegate('li.trigger', 'click', handlerFn);
DOM에서 요소를 언로드한 후 작동
DOM 작업은 상대적으로 느리므로 DOM을 직접 작업하는 것은 피해야 합니다. jQuery는 버전 1.4에서 DOM에서 요소를 언로드한 다음 작업이 완료된 후 DOM에 추가할 수 있는 $.fn.detach 메서드를 도입했습니다.
var $table = $('#myTable'); var $parent = $table.parent(); $table.detach(); // ... 例如这里给表格添加了很多很多行 $parent.append(table);
외부 스타일 시트를 사용하여 많은 요소의 스타일 수정
$.fn.css를 사용하여 20개 이상의 요소에 대한 스타일을 수정하는 경우 페이지에 직접 스타일 태그를 추가하는 것을 고려해야 합니다. 이렇게 하면 성능이 60% 향상된다고 합니다.
// 当元素少于 20 个时使用这个方法,多余 20 个时,速度就慢了 $('a.swedberg').css('color', '#asd123'); // 多余 20 个元素时,应考虑直接在页面中添加 style 标签 $('<style type="text/css">a.swedberg { color : #asd123 }</style>') .appendTo('head');
$.fn.data 대신 $.data 사용
$.data를 DOM 요소에 적용하는 것은 선택기에서 직접 $.fn.data를 호출하는 것보다 10배 빠릅니다. 물론 전제는 DOM 요소와 jQuery 결과 세트의 차이점을 먼저 이해하는 것입니다.
// 速度一般 $(elem).data(key,value); // 速度提升 10 倍 $.data(elem,key,value);
빈 요소에 시간을 낭비하지 마세요
jQuery는 빈 결과 집합에서 코드가 실행되고 있음을 적극적으로 알려주지 않으며 실행 중에 오류가 발생하지 않습니다. 따라서 때로는 코드를 실행하기 전에 먼저 결과 집합이 비어 있는지 확인해야 합니다.
// 不好:执行了三个函数之后 // 才发现结果集上没有任何元素 $('#nosuchthing').slideUp(); // 好 var $mySelection = $('#nosuchthing'); if ($mySelection.length) { $mySelection.slideUp(); } // 最好:增加一个 doOnce 插件 jQuery.fn.doOnce = function(func){ this.length && func.apply(this); return this; } $('li.cartitems').doOnce(function(){ // 这里可以确保结果集不是空的 });
이 접근 방식은 결과 집합에 요소가 없더라도 오버헤드가 상당할 수 있으므로 jQuery UI 측면에 특히 유용합니다.
변수의 정의
하나의 명령문에 여러 변수를 정의할 수 있습니다.
// 老掉牙的写法 var test = 1; var test2 = function() { ... }; var test3 = test2(test); // 新写法 var test = 1, test2 = function() { ... }, test3 = test2(test);
자체 실행 함수에서는 변수를 정의할 필요도 없습니다.
(function(foo, bar) { ... })(1, 2);
조건부 판단
// 土方法 if (type == 'foo' || type == 'bar') { ... } // 较先进的方法 if (/^(foo|bar)$/.test(type)) { ... } // 使用对象查找 if (({ foo : 1, bar : 1 })[type]) { ... }