for과 for-in 패턴.md

이 글은 "JavaScript Patterns" 책을 공부하며 요약해 쓴 글입니다.


for

for 루프는 배열, arguments, HTMLCollection 등 배열과 비슷한 객체를 순회한다.

 

*HTMLCollection: HTML 요소들의 리스트로 유사배열객체이다.

 

 

일반적인 for 문

 

이 패턴은 루프 순회시마다 arr의 length에 접근한다.

 

만약 arr이 배열이 아닌 HTMLCollection이라면 코드가 느려질 수 있다.

  • 실제 DOM의 접근 비용은 일반적으로 크다.
  • HTMLCollection 객체의 length 속성 접근은 실제 DOM에 질의를 요청하는 것과 같다.
  • 실제 DOM 질의는 실시간으로 처리된다. 브라우저는 DOM 조작이 일어나면 다시 브라우저에 렌더링하는데에 수 많은 처리 과정을 거치는데, 이는 많은 비용이 요구된다. (reflow를 참고)

arr.length의 값이 10000이라면 브라우저를 10000번 렌더링하는 것과 같다.

 

여러 최적화 방법들

 

1. 배열(또는 콜렉션)의 length를 캐시
 

HTMLCollection 객체의 length 값을 초기화 변수에 저장하여 한 번의 DOM 접근만이 이루어진다.

 

2. 변수 갯수 줄이기, 배열을 거꾸로 순회
 

length 변수를 없애고, 배열의 카운트를 감소시켜 0으로 내려간다. (미세 최적화)

  • 0과 비교하는 것이 배열의 length 또는 0이 아닌 값과 비교하는 것보다 대게 더 빠르다.
  • 성능이 결정적인 요소가 되는 작업에서 사용하는 것을 권장

for-in

for-in 루프는 배열이 아닌 객체를 순회할 때 사용해야 한다.

  • 자바스크립트의 배열은 객체이기 때문에 for-in 루프를 통해 순회할 수 있지만, 권장사항이 아니다.
  • 배열 객체에 사용자가 정의한 기능이 추가되면 논리적인 오류가 발생할 수 있다.
  • 열거 순서가 정해져있지 않다. 실제로 배열은 for-in이 아닌 for 루프로 순회하는 것이 좀 더 빠르다.
 

 

일어날 수 있는 오류 피하기

코드 내에 'Object.prototype.메서드명'이라는 사용자가 지정한 메서드가 모든 객체에 추가되었다고 가정하자.

이 메서드 프로퍼티는 프로토타입 체인을 따라 상속되어 모든 객체의 프로퍼티로 사용할 수 있게 된다.

이 문제로 인해 어떤 객체가 for-in 루프로 순회하는 과정에서 의도치 않게 메서드가 사용될 수 있다.

ex)

 

 

1. hasOwnProperty() 사용

Object의 hasOwnProperty 메서드를 사용하여 객체 변수의 고유 프로퍼티만을 사용할 수 있다.

 

 

2. Object.prototype.hasOwnProperty.call() 사용

이 패턴은 만약 fruits 객체의 hasOwnProperty 메서드를 오버라이딩 했을 경우에도, 온전한 hasOwnProperty 메서드를 사용할 수 있게 해준다.

 

 

3. Object.prototype.hasOwnProperty 캐시

프로퍼티 탐색이 체인을 따라 Object까지 거슬러 올라가지 않게 하기 위해, 지역 변수를 사용하여 메서드를 캐시한다.

 

 

hasOwnProperty()를 사용하지 않았다고 해서 오류가 발생하지는 않으며, 루프 속도가 약간 감소될 수 있지만, 객체와 객체 프로토타입 체인의 내용을 보장할 수 없다면 hasOwnProperty()로 확인하는 것이 좀 더 안전한 방법이다.

전역 변수 맛보기.md

이 글은 "JavaScript Patterns" 책을 공부하며 요약해 쓴 글입니다.


전역 변수의 최소화는 좋은 코드 작성과 유지보수를 함에 있어 큰 역할을 한다!!

그렇기에 전역 변수를 사용함에 있어, 안티 패턴을 최대한 피하며 개발을 하는 것이 좋다.

 

전역 변수 맛보기

자바스크립트는 함수를 사용하여 유효 범위를 관리한다. 아래는 지역 변수를 나타낸다.

 

ex) 지역변수 사용 예

 

 

반대로 전역 변수는 어떤 함수에도 속하지 않은 상태에서 선언되거나, 함수에 속하더라도 var를 통해 선언되지 않은 채로 사용되는 변수를 가리킨다.

 

ex) 전역 변수 사용 예

 

 

모든 자바스크립트 실행 환경에는 전역 객체(global object)가 존재하는데, 전역 변수를 선언하면 이는 전역 객체의 프로퍼티가 된다. 브라우저에서는 전역 객체에 window라는 프로퍼티가 존재하는데 이는 전역 객체 자신을 가리킨다.

 

ex) 모두 전역 변수

 

 

전역 객체는 this를 통해서도 접근이 가능하다.

 

ex)

 

 

전역 변수의 문제점

전역 변수의 문제점은 애플리케이션이나 웹페이지 내 모든 코드 사이에서 공유된다는 점이다.

ex) 덮어 쓰기

 

만약 개발자가 자신이 작성하지 않은 외부 코드를 가져와 삽입했을 때, yyy = 0;은 개발자가 정의한 코드이며 test 함수는 외부 코드라고 가정한다면 개발자가 test 함수를 실행했을 때 전역 변수 yyy가 10이 되는 원치않는 결과를 초래할 것이다.

 

이러한 문제를 피하기 위해서 전역 변수에 대한 안티 패턴과 개선하는 코드를 알아 보자.


1. var를 통한 변수 선언

ex) 암묵적 전역 코드 사용 == 안티 패턴

 

자바스크립트에는 암묵적 전역(implied globals)이라는 개념이 있기 때문에 선언하지 않고 사용한 변수는 자동으로 전역 객체의 프로퍼티가 되어 명시적으로 선언된 전역 변수처럼 사용될 수 있다.

 

안티 패턴을 피하기 위해서는 언제나 var를 사용하여 변수를 선언하는 것이 좋다.

 

ex) var 변수 선언

 

유효 범위 안에서만 사용 가능하여 덮어쓰기 같이 의도치 않는 실수가 일어나지 않도록 방지해준다.

 


2. var 선언에서의 연쇄적 할당

아래는 var 선언에 여러 변수를 연쇄적으로 할당한 코드의 예이다.

 

ex)

 

두 변수가 지역 변수로 할당될 것이라 예상하지만 사실 b는 전역 변수가 된다. 그 이유는 자바스크립트는 표현식의 "평가(evaulation)"가 오른쪽에서 왼쪽으로 진행되기 때문이다. 코드의 평가는 아래와 같이 된다.

 

괄호 안의 b = 0 이라는 식이 먼저 평가되는데, 이때 b는 var를 통해 선언되는 것이 아니므로 전역 변수가 된다.

 

 

변수를 미리 선언해둠으로써 연쇄 할당문의 전역 변수 생성을 피할 수 있다.

 

ex) 안티 패턴 피하기

 

 


3. 단일 var 패턴 (유용)

함수의 상단에 var 선언을 한 번만 쓰는 패턴은 유용하고 시도해 볼 만하다.

책 에서는 다음과 같은 이점이 있다고 소개한다.

  • 함수에서 필요로 하는 모든 지역 변수를 한군데서 찾을 수 있다.
  • 변수를 선언하기 전에 사용할 때 발생하는 로직상의 오류를 막아준다. [호이스팅(hoisting)과 같은]
  • 변수를 먼저 선언한 후에 사용해야 한다는 사실을 상기시키기 때문에 전역 변수를 최소화하는 데 도움이 된다.
  • 코드량이 줄어든다. (작성량과 전송량 모두 줄어든다)

코드는 아래와 같이 표현한다.

 

ex) 단일 var 패턴의 예

 

var 선언을 하나만 쓰고 쉼표를 통해 여러 변수들을 선언했다.

자바스크립트는 C와 Java와 같은 언어처럼 정적 타이핑(static type)이 아닌 동적 타이핑(dynamic type)이다. int와 char와 같이 변수의 용도에 따라 타입(type)을 미리 명시해주는 것이 아닌, var 변수에 어떤 값을 할당하든 실행 시에 자바스크립트 엔진에서 자동으로 타입(type)을 구분해준다.

이런 성격으로 인해 개발자가 매우 편리하게 코드를 작성할 수 있지만, 나중에 코드가 매우 방대해지고 용어의 뜻이 불분명할 때는 변수의 용도를 확인하기가 어려워지며 오류 또한 발생하기 쉽다.

그러므로 위와 같이 변수를 선언할 때 초기 값을 주어 초기화하는 것 역시 좋은 습관이다. 문법 오류를 막을 수 있고 코드 가독성도 향상된다.

또한 자바스크립트는 "호이스팅(hoisting, 끌어올리기)"이라는 동작 방식이 있다. 실행 문맥(execution context) 글을 보면 자세히 알 수 있는데, 함수 범위 내에 흩어져 있는 변수는 값이 할당되기 전에 모두 함수 상단으로 끌어올려져 undefined 형태로 선언된다. 이러한 특성은 로직상의 오류를 범하기 쉽기 때문에, 함수 상단에 하나의 var 선언문을 사용하여 변수들을 모아놓는 패턴을 사용하는 것이 좋다.

 

DOM(Document Object Model) 참조를 다루는 것도 좋은 예다.
다음 예제와 같이 DOM 참조를 할당한 지역 변수들을 하나의 선언문에 모아놓는다.

 

ex)

 

'JavaScript' 카테고리의 다른 글

자바스크립트 : for, for-in 패턴  (0) 2018.01.22

+ Recent posts