Javascipt Patterns 책의 8장 “DOM 과 브라우저 패턴” 을 요약하였습니다.
DOM 접근
- dom 접근은 최소화한다.
-
루프문 내에서 DOM 접근은 피한다.
// 안티패턴 for (var i = 0; i < 100; i += 1) { document.getElementById("result").innerHTML += i + ", "; } // 지역 변수를 이용한 개선 var i, content = ""; for (var i = 0; i < 100; i += 1) { content += i + ", "; } document.getElementById("result").innerHTML += content;
-
DOM 참조를 지역변수에 할당하여 사용한다.
// 안티패턴 var padding = document.getElementById("result").style.padding, margin = document.getElementById("result").style.margin; // 개선안 var style = document.getElementById("result").style. padding = style.padding; margin = style.margin; document.querySelector("ul .selected"); // 쿼리 셀렉터는 다른 DOM 메서드 선택방식보다 빠르다.
- 자주 접근하는 엘리먼트에 id 속성을 추가하는 것도 성능 향상에 도움이 된다. 왜냐면,
document.getElementById("id")
가 노드를 찾는 가장 빠른 방법
DOM 조작
- DOM 업데이트는 최소화 하는 것이 좋다.
- 업데이트시에 화면을 repaint 하고, 엘리먼트를 reflow 하는데 비용이 많이 들어가기 떄문
-
서브트리를 추가할 시에는 서브 트리의 구성요소를 모두 생성한 후에 마지막에 한번만 추가해준다.
// 안티 패턴 var p, t; p = document.createElement("p"); t = document.createTextNode("first paragraph"); p.appendChild(t); document.body.appendChild(p); p = document.createElement("p"); t = document.createTextNode("second paragraph"); p.appendChild(t); document.body.appendChild(p); // 개선 var p, t, frag; frag = document.createDocumentFragment(); p = document.createElement("p"); t = document.createTextNode("first paragraph"); p.appendChild(t); frag.appendChild(p); p = document.createElement("p"); t = document.createTextNode("second paragraph"); p.appendChild(t); frag.appendChild(p); document.body.appendChild(frag);
-
존재하는 트리를 변경하는 경우에는 서브트리의 루트를 복제해서 변경한 뒤 원래의 노드와 바꾼다.
var oldnode = document.getElementById("result"), clone = oldnode.cloneNode(true); oldnode.parentNode.replaceChild(clone, oldnode);
이벤트
-
이벤트 리스너는 아래와 같이 구현할 수 있다.
var b = document.getElementById("clickme"); if (document.addEventListener) { b.addEventListener("click", myHandler, false); } else if (document.attachEvent) { b.attachEvent("onclick". myHandler); } else { b.onclick = myHandler; } function myHandler(e) { var src, parts; e = e || window.event; src = e.target || e.srcElement; if (src.nodeName.toLowerCase() !== "button") { return ; } parts = src.innerHTML.split(": "); parts[1] = parseInt(parts[1], 10) + 1; src.innerHTML = parts[0] + ": " + parts[1]; if (typeof e.stopPropagation === "function") { e.stopPropagation(); } if (typeof e.cancelBubble !== "undefined") { e.cancelBubble = true; } if (typeof e.preventDefault() === "funtion") { e.preventDefault(); } if (typeof e.preventDefault() !== "undefined") { e.returnValue = false; } }
-
setTimeOut()
이나 Web Worker 를 이용하여 쓰레드 같은 기능을 구현할 수 있다.
XMLHttpRequest
- 자바스크립트에서 HTTP 요청을 생성하는 특별한 객체 (생성자 함수)
-
생성과정은 아래와 같다.
- XMLHttpRequest(XHR) 객체를 생성
var xhr = new XMLHttpRequest();
- 응답 객체의 상태 변경시 알림을 받기 위한 콜백함수 지정
xhr.onreadystatechange = handleResponse;
- 요청을 보낸다.
xhr.open("GET", "page.html", true); // 마지막 true 값은 요청의 비동기 여부, 가급적 true 로 사용자 경험 올리기 xhr.send();
JSONP
- JSON with padding
- 브라우저의 동일 도메인 정책의 제약을 받지 않는다.
-
JSONP 의 요청 URL 형태
http://example.org/getdata.php?callback=myHandler
- 위에서 getdata.php 가 웹페이지 이거나 스크립트가 될 수 있다.
- getdata.php 파일이 수신되면, myHandler({“hello”: “world”}) 같은 콜백함수가 실행된다.
웹 페이지 로딩 전략
-
script 태그에 들어가는 엘리멘트를 살펴보자.
- type=”text/javascript” : HTML5 에서는 필수 속성이 아니고, 마크업 유효성 검사를 위한 경우가 아니라면 사용하지 않는다.
- async (defer) : 비동기 스크립트 로딩으로, 스크립트를 받는 동안 다른 다운로드를 방해하지 않는다.