자바 스크립트 DOM 과 브라우저 패턴(Javascript Pattern)

Minho Yoo·2022년 8월 8일
1
post-thumbnail

DOM 접근

dom 접근은 최소화한다.
루프문 내에서 DOM 접근은 피한다.

// 안티패턴
for (let i = 0; i < 100; i++) {
  document.getElementById('result').innerHTML += i + ', ';
}

// 지역 변수를 이용한 개선
for i, content = '';
for (let i = 0; i < 100; i++) {
  content += i + ', ';
}
document.getElementById('result').innerHTML += content;

DOM 참조를 지역벼수에 할당하여 사용한다.

// 안티패턴
const padding = document.getElementById('result').style.padding,
      margin = document.getElementById('result').style.margin;

// 개선안
const style = document.getElementById('result').style.
	padding = style.padding;
	margin = style.margin;

document.queryselector('ul .selected');
// 쿼리 셀렉터는 다른 DOM 메서드 선택방식보다 빠르다.

자주 접근하는 엘리먼트에 id 속성을 추가하는 것도 성능 향상에 도움이 된다.
왜냐면, document.getElementById('id')가 노드를 찾는 가장 빠른 방법

DOM 조작

DOM 업데이트는 최소화 하는 것이 좋다.
업데이트시에 화면을 repaint 하고, 엘리먼트를 reflow 하는데 비용이 많이 들어가기 때문이다.
서브트리를 추가할 시에는 서브 트리의 구성요소를 모두 생성한 후에 마지막에 한번에 추가해준다.

// 안티 패턴
let 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);

// 개선
let p, t, frag;
frag = document.createDocumentFreagment();

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);

존재하는 트리를 변경하는 경우에는 서브트리의 루트를 복제해서 변경한 뒤 원래의 노드와 바꾼다.

const oldnode = document.getElementById('result'),
      clone = oldnode.cloneNode(true);

oldnode.parentNode.replaceChild(clone, oldnode);

이벤트

이벤트 리스너는 아래와 같이 구현할 수 있다.

const 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) {
  let 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.cancleBubble = true;
  }
  
  if (typeof e.preventDefault() === 'function') {
    e.preventDefault();
  }
  
  if (typeof e.preventDefault() !== 'undefined') {
    e.returnValue = false;
  }
}

setTimeOut()이나 Web Werker 를 이용하여 쓰레드 같은 기능을 구현할 수 있다.

XMLHttpRequest

자바스크립트에서 HTTP 요청을 생성하는 특별한 객체 (생성자 함수)

1. XMLHttpRequest(XHR) 객체를 생성

const xhr = new XMLHttpRequest();

2. 응답 객체의 상태 변경시 알람을 받기 위한 콜백함수 지정

xhr.onreadystatchange = handleResponse;

3. 요청을 보낸다.

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': HTML 에서는 필수 속성이 아니고, 마크업 유효성 검사를 위한 경우가 아니라면 사용하지 않는다.
  • async (defer): 비동기 스크립트 로딩으로, 스크립트를 받는 동안 다른 다운로드를 방해하지 않는다.
profile
Always happy coding 😊

0개의 댓글