2009-03-24 4 views
27

브라우저에서 DOM 트리를 가장 잘 복제하는 방법을 알아 내려고하고 있습니다. 내가 더 빨리 될 것입니다 무엇deepcloning과 innerHTML의 설정 : 무엇이 더 빠릅니까?

var div = document.getElementById("source"); 
var markup = div.innerHTML; 

으로 시작하는 경우

,

var target = div.cloneNode(true); 

또는

var target = document.cloneNode(false); 
target.innerHTML = markup; 

은 그래서 어떤 브라우저 플랫폼은 여기에 큰 차이를 만들 수 있습니다 이해 현실 세계에서 이들이 어떻게 비교되는지에 대한 정보는 높이 평가 될 것입니다.

+0

나는 당신이 원하는 것을 얻지 못합니다. 요소를 복제하고 싶습니까? 'var target = div.cloneNode (true);'그냥 그렇게했습니다. 복제는 'innerHTML'과 어떤 관련이 있습니까? –

+0

구체적인 결과는 브라우저에 따라 다르지만 jsPerf [여기] (http://jsperf.com/clonenode-vs-createelement-performance/39) 및 [여기] (http : // jsperf .com/innerclone/13). – Blazemonger

+0

[innerHTML은 이벤트 리스너를 파기합니다.] (http://stackoverflow.com/q/595808/1048572), 사용하지 마십시오. – Bergi

답변

48

시험합시다!

는 I에 유래의 질문 페이지의 사본에 다음 코드를 추가 (100 개 작전의 3 실점 첫째 기존 스크립트를 제거하고, 주변의 timeit 중 하나()의 처음부터 주석 때마다 실행 :

function timeit(f) { 
    var start= new Date(); 
    for (var i=100; i-->0;) { 
     f(); 
    } 
    return new Date()-start; 
} 

var c= document.getElementById('content'); 
var clones= []; 

//alert('cloneNode: '+timeit(function() { 
// clones.push(c.cloneNode(true)); 
//})) 

//alert('innerHTML: '+timeit(function() { 
// var d= document.createElement('div'); 
// d.innerHTML= c.innerHTML; 
// clones.push(d); 
//})) 
을 여기

결과는 코어 2 Q9300에 버추얼 박스에서 실행됩니다 훨씬 빠르게 innerHTML을을 복사하는 것보다

IE7 
cloneNode: 3238, 3235, 3187 
innerHTML: 8442, 8468, 8552 

Firefox3 
cloneNode: 1294, 1315, 1289 
innerHTML: 3593, 3636, 3580 

Safari3 
cloneNode: 207, 273, 237 
innerHTML: 805, 818, 786 

Chrome1 
cloneNode: 329, 377, 426 
innerHTML: 2327, 2536, 2865 

Opera10 
cloneNode: 801, 791, 771 
innerHTML: 1852, 1732, 1672 

그래서 cloneNode (사실)입니다 물론 항상있을 거라고, 텍스트에 DOM을 serialising합니다. HTML에서 다시 파싱하는 것은 어렵습니다. DOM 자식 작업에 일반적으로 느리다는 것은 하나씩 삽입하거나 이동한다는 것입니다. cloneNode와 같은 all-at-once DOM 작업은 그렇게 할 필요가 없습니다.

Safari는 innerHTML을 놀랍게 빨리 처리하지만 cloneNode만큼 빨리 처리하지는 않습니다. IE는 예상대로 개다.

그래서 innerHTML이 실제로 무엇을하고 있었는지 고려하지 않고 더 빠르다 고 말한 모든 사용자에게 자동 -1이 표시됩니다.

그리고 예, jQuery는 innerHTML을 사용하여 복제합니다. 그것이 비록 빠른 때문에하지 않음 - 소스를 읽어

// IE copies events bound via attachEvent when 
// using cloneNode. Calling detachEvent on the 
// clone will also remove the events from the orignal 
// In order to get around this, we use innerHTML. 

jQuery를()가 자신의 이벤트 시스템을 구현하는 Element.attachEvent 사용하기 때문에 자연스럽게 그 버그를 방지 할 필요가있다. 필요하지 않으면 오버 헤드를 피할 수 있습니다.

는 는

[오프 주제 옆 : 그럼 다시, 나는, 특히 다음 라인 주어진 잘못된 조금있을 수 있습니다 최대 우수 사례의 절정으로 jQuery를 잡고 생각 :

html.replace(/ jQuery\d+="(?:\d+|null)"/g, "") 

맞아 - jQuery를 자체를 추가 임의의 애트리뷰트를 HTML 요소에 적용한 다음,이를 복제 할 때 제거해야한다. 그렇지 않으면 $(). html() 메소드를 통해 마크 업에 액세스 할 수있다. 이것은 충분히 추한 것입니다. 그렇지만 최선의 방법은 정규 표현식을 사용하여 HTML을 처리하는 것입니다. 이것은 재능있는 1 명의 평판을 가진 사람들로부터 기대하는 기본적인 실수입니다. 재림 최고의 JS Framework Evar.

텍스트 콘텐츠에 "jQuery1 ="2 ""문자열이 없기를 바랍니다. 그렇다면 신비하게도 잃어 버렸을 것입니다. 감사합니다 jQuery! 따라서 주제를 벗어난 주제는 끝이 없습니다.]

+0

우수한 분석가. 유일한 작은 니트는 루프 내에서가 아니라 innerHTML 소스를 한 번 미리 직렬화하려고했다는 것입니다. 그러나 그것은 여전히 ​​느리게 나타납니다. 감사합니다. – levik

+0

위대한 답변 Bobince. 궁금한 점은 이러한 추가 속성을 제거하는 가장 좋은 방법은 무엇일까요? HTML 요소의 허용 목록에서 꺾쇠 괄호 안에서만 검색하거나 DOM 요소를 만든 다음 jQuery의'removeAttr()'을 사용하면됩니까? 아마도 그것은 트레이드 오프 일 것입니다. 문자열을 사용하는 사람을 맹 글링하는 대신 훨씬 빨라질 수 있습니다. 드문 경우이긴하지만, jQuery 문서에는 경고가 있어야합니다 (내가있는 경우 발견하지 못했습니다) – alex

+0

HTML 속성 대신 ID에 대한 JS 속성을 설정하는 것이 좋습니다. IE는 속성이 속성 인 것처럼 직렬화되는 버그가 있지만 속성 값이 원시 데이터 유형 인 경우에만 실행됩니다. Object-type 속성은 'innerHTML'에 포함되지 않습니다. 따라서'elementnode.jQueryId45438 = [1]'(Array 객체)를 설정하면 jQuery는 직렬화를 엉망으로 만들지 않고 post -innerHTML 픽스 업을 필요로하지 않고 고유 ID를 요소에 넣을 수 있습니다. – bobince

-5

일반적으로 innerHTML이 빠릅니다. 이것 좀 봐, benchmark across many platforms :

+0

새로운 요소를 복제하는 것보다는 복제하는 경우에만 유용합니다. –

1

흠 ... 흥미롭게도, 나는 Firefox 3에서 테스트를했고, 깊은 복제본은 innerHTML 경로를가는 것보다 약 3 배 빠른 것 같습니다.

innerHTML은 여전히 ​​개별 DOM 작업보다 빠르지 만 최소한 딥 복제의 경우 cloneNode (true)가 더 최적화 된 것으로 보입니다.

관련 문제